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 #ifdef WIN32
   1252     u_long bytes = 0;
   1253     int last_error = WSAGetLastError();
   1254     ioctlsocket(ConnectionNumber(dpy), FIONREAD, &bytes);
   1255     WSASetLastError(last_error);
   1256     return (int) bytes;
   1257 #else
   1258     int bytes = 0;
   1259     int last_error = errno;
   1260     ioctl(ConnectionNumber(dpy), FIONREAD, &bytes);
   1261     errno = last_error;
   1262     return bytes;
   1263 #endif
   1264 }
   1265 
   1266 _X_NORETURN void _XDefaultIOErrorExit(
   1267 	Display *dpy,
   1268 	void *user_data)
   1269 {
   1270     exit(1);
   1271     /*NOTREACHED*/
   1272 }
   1273 
   1274 /*
   1275  * _XDefaultIOError - Default fatal system error reporting routine.  Called
   1276  * when an X internal system error is encountered.
   1277  */
   1278 _X_NORETURN int _XDefaultIOError(
   1279 	Display *dpy)
   1280 {
   1281 	int killed = ECHECK(EPIPE);
   1282 
   1283 	/*
   1284 	 * If the socket was closed on the far end, the final recvmsg in
   1285 	 * xcb will have thrown EAGAIN because we're non-blocking. Detect
   1286 	 * this to get the more informative error message.
   1287 	 */
   1288 	if (ECHECK(EAGAIN) && SocketBytesReadable(dpy) <= 0)
   1289 	    killed = True;
   1290 
   1291 	if (killed) {
   1292 	    fprintf (stderr,
   1293                      "X connection to %s broken (explicit kill or server shutdown).\r\n",
   1294                      DisplayString (dpy));
   1295 	} else {
   1296             fprintf (stderr,
   1297                      "XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
   1298 #ifdef WIN32
   1299                       WSAGetLastError(), strerror(WSAGetLastError()),
   1300 #else
   1301                       errno, strerror (errno),
   1302 #endif
   1303                       DisplayString (dpy));
   1304 	    fprintf (stderr,
   1305 		     "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
   1306 		     NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
   1307 		     QLength(dpy));
   1308         }
   1309 
   1310 	exit(1);
   1311 	/*NOTREACHED*/
   1312 }
   1313 
   1314 
   1315 static int _XPrintDefaultError(
   1316     Display *dpy,
   1317     XErrorEvent *event,
   1318     FILE *fp)
   1319 {
   1320     char buffer[BUFSIZ];
   1321     char mesg[BUFSIZ];
   1322     char number[32];
   1323     const char *mtype = "XlibMessage";
   1324     register _XExtension *ext = (_XExtension *)NULL;
   1325     _XExtension *bext = (_XExtension *)NULL;
   1326     XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
   1327     XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
   1328     (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
   1329     XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
   1330 	mesg, BUFSIZ);
   1331     (void) fprintf(fp, mesg, event->request_code);
   1332     if (event->request_code < 128) {
   1333 	snprintf(number, sizeof(number), "%d", event->request_code);
   1334 	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
   1335     } else {
   1336 	for (ext = dpy->ext_procs;
   1337 	     ext && (ext->codes.major_opcode != event->request_code);
   1338 	     ext = ext->next)
   1339 	  ;
   1340 	if (ext) {
   1341 	    strncpy(buffer, ext->name, BUFSIZ);
   1342 	    buffer[BUFSIZ - 1] = '\0';
   1343         } else
   1344 	    buffer[0] = '\0';
   1345     }
   1346     (void) fprintf(fp, " (%s)\n", buffer);
   1347     if (event->request_code >= 128) {
   1348 	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
   1349 			      mesg, BUFSIZ);
   1350 	fputs("  ", fp);
   1351 	(void) fprintf(fp, mesg, event->minor_code);
   1352 	if (ext) {
   1353 	    snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code);
   1354 	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
   1355 	    (void) fprintf(fp, " (%s)", buffer);
   1356 	}
   1357 	fputs("\n", fp);
   1358     }
   1359     if (event->error_code >= 128) {
   1360 	/* kludge, try to find the extension that caused it */
   1361 	buffer[0] = '\0';
   1362 	for (ext = dpy->ext_procs; ext; ext = ext->next) {
   1363 	    if (ext->error_string)
   1364 		(*ext->error_string)(dpy, event->error_code, &ext->codes,
   1365 				     buffer, BUFSIZ);
   1366 	    if (buffer[0]) {
   1367 		bext = ext;
   1368 		break;
   1369 	    }
   1370 	    if (ext->codes.first_error &&
   1371 		ext->codes.first_error < (int)event->error_code &&
   1372 		(!bext || ext->codes.first_error > bext->codes.first_error))
   1373 		bext = ext;
   1374 	}
   1375 	if (bext)
   1376 	    snprintf(buffer, sizeof(buffer), "%s.%d", bext->name,
   1377                      event->error_code - bext->codes.first_error);
   1378 	else
   1379 	    strcpy(buffer, "Value");
   1380 	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
   1381 	if (mesg[0]) {
   1382 	    fputs("  ", fp);
   1383 	    (void) fprintf(fp, mesg, event->resourceid);
   1384 	    fputs("\n", fp);
   1385 	}
   1386 	/* let extensions try to print the values */
   1387 	for (ext = dpy->ext_procs; ext; ext = ext->next) {
   1388 	    if (ext->error_values)
   1389 		(*ext->error_values)(dpy, event, fp);
   1390 	}
   1391     } else if ((event->error_code == BadWindow) ||
   1392 	       (event->error_code == BadPixmap) ||
   1393 	       (event->error_code == BadCursor) ||
   1394 	       (event->error_code == BadFont) ||
   1395 	       (event->error_code == BadDrawable) ||
   1396 	       (event->error_code == BadColor) ||
   1397 	       (event->error_code == BadGC) ||
   1398 	       (event->error_code == BadIDChoice) ||
   1399 	       (event->error_code == BadValue) ||
   1400 	       (event->error_code == BadAtom)) {
   1401 	if (event->error_code == BadValue)
   1402 	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
   1403 				  mesg, BUFSIZ);
   1404 	else if (event->error_code == BadAtom)
   1405 	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
   1406 				  mesg, BUFSIZ);
   1407 	else
   1408 	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
   1409 				  mesg, BUFSIZ);
   1410 	fputs("  ", fp);
   1411 	(void) fprintf(fp, mesg, event->resourceid);
   1412 	fputs("\n", fp);
   1413     }
   1414     XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
   1415 			  mesg, BUFSIZ);
   1416     fputs("  ", fp);
   1417     (void) fprintf(fp, mesg, event->serial);
   1418     XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%lld",
   1419 			  mesg, BUFSIZ);
   1420     fputs("\n  ", fp);
   1421     (void) fprintf(fp, mesg, (unsigned long long)(X_DPY_GET_REQUEST(dpy)));
   1422     fputs("\n", fp);
   1423     if (event->error_code == BadImplementation) return 0;
   1424     return 1;
   1425 }
   1426 
   1427 int _XDefaultError(
   1428 	Display *dpy,
   1429 	XErrorEvent *event)
   1430 {
   1431     if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
   1432 
   1433     /*
   1434      * Store in dpy flags that the client is exiting on an unhandled XError
   1435      * (pretend it is an IOError, since the application is dying anyway it
   1436      * does not make a difference).
   1437      * This is useful for _XReply not to hang if the application makes Xlib
   1438      * calls in _fini as part of process termination.
   1439      */
   1440     dpy->flags |= XlibDisplayIOError;
   1441 
   1442     exit(1);
   1443     /*NOTREACHED*/
   1444 }
   1445 
   1446 /*ARGSUSED*/
   1447 Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
   1448 {
   1449     return True;
   1450 }
   1451 
   1452 /*
   1453  * _XError - upcall internal or user protocol error handler
   1454  */
   1455 int _XError (
   1456     Display *dpy,
   1457     register xError *rep)
   1458 {
   1459     /*
   1460      * X_Error packet encountered!  We need to unpack the error before
   1461      * giving it to the user.
   1462      */
   1463     XEvent event; /* make it a large event */
   1464     register _XAsyncHandler *async, *next;
   1465 
   1466     event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
   1467 
   1468     for (async = dpy->async_handlers; async; async = next) {
   1469 	next = async->next;
   1470 	if ((*async->handler)(dpy, (xReply *)rep,
   1471 			      (char *)rep, SIZEOF(xError), async->data))
   1472 	    return 0;
   1473     }
   1474 
   1475     event.xerror.display = dpy;
   1476     event.xerror.type = X_Error;
   1477     event.xerror.resourceid = rep->resourceID;
   1478     event.xerror.error_code = rep->errorCode;
   1479     event.xerror.request_code = rep->majorCode;
   1480     event.xerror.minor_code = rep->minorCode;
   1481     if (dpy->error_vec &&
   1482 	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
   1483 	return 0;
   1484     if (_XErrorFunction != NULL) {
   1485 	int rtn_val;
   1486 #ifdef XTHREADS
   1487 	struct _XErrorThreadInfo thread_info = {
   1488 		.error_thread = xthread_self(),
   1489 		.next = dpy->error_threads
   1490 	}, **prev;
   1491 	dpy->error_threads = &thread_info;
   1492 	if (dpy->lock)
   1493 	    (*dpy->lock->user_lock_display)(dpy);
   1494 	UnlockDisplay(dpy);
   1495 #endif
   1496 	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
   1497 #ifdef XTHREADS
   1498 	LockDisplay(dpy);
   1499 	if (dpy->lock)
   1500 	    (*dpy->lock->user_unlock_display)(dpy);
   1501 
   1502 	/* unlink thread_info from the list */
   1503 	for (prev = &dpy->error_threads; *prev != &thread_info; prev = &(*prev)->next)
   1504 		;
   1505 	*prev = thread_info.next;
   1506 #endif
   1507 	return rtn_val;
   1508     } else {
   1509 	return _XDefaultError(dpy, (XErrorEvent *)&event);
   1510     }
   1511 }
   1512 
   1513 /*
   1514  * _XIOError - call user connection error handler and exit
   1515  */
   1516 int
   1517 _XIOError (
   1518     Display *dpy)
   1519 {
   1520     XIOErrorExitHandler exit_handler;
   1521     void *exit_handler_data;
   1522 
   1523     dpy->flags |= XlibDisplayIOError;
   1524 #ifdef WIN32
   1525     errno = WSAGetLastError();
   1526 #endif
   1527 
   1528     /* This assumes that the thread calling exit will call any atexit handlers.
   1529      * If this does not hold, then an alternate solution would involve
   1530      * registering an atexit handler to take over the lock, which would only
   1531      * assume that the same thread calls all the atexit handlers. */
   1532 #ifdef XTHREADS
   1533     if (dpy->lock)
   1534 	(*dpy->lock->user_lock_display)(dpy);
   1535 #endif
   1536     exit_handler = dpy->exit_handler;
   1537     exit_handler_data = dpy->exit_handler_data;
   1538     UnlockDisplay(dpy);
   1539 
   1540     if (_XIOErrorFunction != NULL)
   1541 	(*_XIOErrorFunction)(dpy);
   1542     else
   1543 	_XDefaultIOError(dpy);
   1544 
   1545     exit_handler(dpy, exit_handler_data);
   1546     return 1;
   1547 }
   1548 
   1549 
   1550 /*
   1551  * This routine can be used to (cheaply) get some memory within a single
   1552  * Xlib routine for scratch space.  A single buffer is reused each time
   1553  * if possible.  To be MT safe, you can only call this between a call to
   1554  * GetReq* and a call to Data* or _XSend*, or in a context when the thread
   1555  * is guaranteed to not unlock the display.
   1556  */
   1557 char *_XAllocScratch(
   1558 	register Display *dpy,
   1559 	unsigned long nbytes)
   1560 {
   1561 	if (nbytes > dpy->scratch_length) {
   1562 	    Xfree (dpy->scratch_buffer);
   1563 	    dpy->scratch_buffer = Xmalloc(nbytes);
   1564 	    if (dpy->scratch_buffer)
   1565 		dpy->scratch_length = nbytes;
   1566 	    else dpy->scratch_length = 0;
   1567 	}
   1568 	return (dpy->scratch_buffer);
   1569 }
   1570 
   1571 /*
   1572  * Scratch space allocator you can call any time, multiple times, and be
   1573  * MT safe, but you must hand the buffer back with _XFreeTemp.
   1574  */
   1575 char *_XAllocTemp(
   1576     register Display *dpy,
   1577     unsigned long nbytes)
   1578 {
   1579     char *buf;
   1580 
   1581     buf = _XAllocScratch(dpy, nbytes);
   1582     dpy->scratch_buffer = NULL;
   1583     dpy->scratch_length = 0;
   1584     return buf;
   1585 }
   1586 
   1587 void _XFreeTemp(
   1588     register Display *dpy,
   1589     char *buf,
   1590     unsigned long nbytes)
   1591 {
   1592 
   1593     Xfree(dpy->scratch_buffer);
   1594     dpy->scratch_buffer = buf;
   1595     dpy->scratch_length = nbytes;
   1596 }
   1597 
   1598 /*
   1599  * Given a visual id, find the visual structure for this id on this display.
   1600  */
   1601 Visual *_XVIDtoVisual(
   1602 	Display *dpy,
   1603 	VisualID id)
   1604 {
   1605 	register int i, j, k;
   1606 	register Screen *sp;
   1607 	register Depth *dp;
   1608 	register Visual *vp;
   1609 	for (i = 0; i < dpy->nscreens; i++) {
   1610 		sp = &dpy->screens[i];
   1611 		for (j = 0; j < sp->ndepths; j++) {
   1612 			dp = &sp->depths[j];
   1613 			/* if nvisuals == 0 then visuals will be NULL */
   1614 			for (k = 0; k < dp->nvisuals; k++) {
   1615 				vp = &dp->visuals[k];
   1616 				if (vp->visualid == id) return (vp);
   1617 			}
   1618 		}
   1619 	}
   1620 	return (NULL);
   1621 }
   1622 
   1623 int
   1624 XFree (void *data)
   1625 {
   1626 	Xfree (data);
   1627 	return 1;
   1628 }
   1629 
   1630 #ifdef _XNEEDBCOPYFUNC
   1631 void _Xbcopy(b1, b2, length)
   1632     register char *b1, *b2;
   1633     register length;
   1634 {
   1635     if (b1 < b2) {
   1636 	b2 += length;
   1637 	b1 += length;
   1638 	while (length--)
   1639 	    *--b2 = *--b1;
   1640     } else {
   1641 	while (length--)
   1642 	    *b2++ = *b1++;
   1643     }
   1644 }
   1645 #endif
   1646 
   1647 #ifdef DataRoutineIsProcedure
   1648 void Data(
   1649 	Display *dpy,
   1650 	_Xconst char *data,
   1651 	long len)
   1652 {
   1653 	if (dpy->bufptr + (len) <= dpy->bufmax) {
   1654 		memcpy(dpy->bufptr, data, (int)len);
   1655 		dpy->bufptr += ((len) + 3) & ~3;
   1656 	} else {
   1657 		_XSend(dpy, data, len);
   1658 	}
   1659 }
   1660 #endif /* DataRoutineIsProcedure */
   1661 
   1662 
   1663 #ifdef LONG64
   1664 int
   1665 _XData32(
   1666     Display *dpy,
   1667     _Xconst long *data,
   1668     unsigned len)
   1669 {
   1670     register int *buf;
   1671     register long i;
   1672 
   1673     while (len) {
   1674 	buf = (int *)dpy->bufptr;
   1675 	i = dpy->bufmax - (char *)buf;
   1676 	if (!i) {
   1677 	    _XFlush(dpy);
   1678 	    continue;
   1679 	}
   1680 	if (len < i)
   1681 	    i = len;
   1682 	dpy->bufptr = (char *)buf + i;
   1683 	len -= i;
   1684 	i >>= 2;
   1685 	while (--i >= 0)
   1686 	    *buf++ = *data++;
   1687     }
   1688     return 0;
   1689 }
   1690 #endif /* LONG64 */
   1691 
   1692 
   1693 
   1694 /* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
   1695  * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
   1696  *
   1697  * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
   1698  *       to have sufficient information for interfacing to the network,
   1699  *       and so, you may be better off using gethostname (if it exists).
   1700  */
   1701 
   1702 #if defined(_POSIX_SOURCE) || defined(SVR4)
   1703 #define NEED_UTSNAME
   1704 #include <sys/utsname.h>
   1705 #else
   1706 #ifdef HAVE_UNISTD_H
   1707 #include <unistd.h>
   1708 #endif
   1709 #endif
   1710 
   1711 /*
   1712  * _XGetHostname - similar to gethostname but allows special processing.
   1713  */
   1714 int _XGetHostname (
   1715     char *buf,
   1716     int maxlen)
   1717 {
   1718     int len;
   1719 
   1720 #ifdef NEED_UTSNAME
   1721     struct utsname name;
   1722 
   1723     if (maxlen <= 0 || buf == NULL)
   1724 	return 0;
   1725 
   1726     uname (&name);
   1727     len = (int) strlen (name.nodename);
   1728     if (len >= maxlen) len = maxlen - 1;
   1729     strncpy (buf, name.nodename, (size_t) len);
   1730     buf[len] = '\0';
   1731 #else
   1732     if (maxlen <= 0 || buf == NULL)
   1733 	return 0;
   1734 
   1735     buf[0] = '\0';
   1736     (void) gethostname (buf, maxlen);
   1737     buf [maxlen - 1] = '\0';
   1738     len = (int) strlen(buf);
   1739 #endif /* NEED_UTSNAME */
   1740     return len;
   1741 }
   1742 
   1743 
   1744 /*
   1745  * _XScreenOfWindow - get the Screen of a given window
   1746  */
   1747 
   1748 Screen *_XScreenOfWindow(Display *dpy, Window w)
   1749 {
   1750     register int i;
   1751     Window root;
   1752     int x, y;				/* dummy variables */
   1753     unsigned int width, height, bw, depth;  /* dummy variables */
   1754 
   1755     if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
   1756 		      &bw, &depth) == False) {
   1757 	return NULL;
   1758     }
   1759     for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
   1760 	if (root == RootWindow (dpy, i)) {
   1761 	    return ScreenOfDisplay (dpy, i);
   1762 	}
   1763     }
   1764     return NULL;
   1765 }
   1766 
   1767 
   1768 /*
   1769  * WARNING: This implementation's pre-conditions and post-conditions
   1770  * must remain compatible with the old macro-based implementations of
   1771  * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the
   1772  * Display structure affected by those macros are part of libX11's
   1773  * ABI.
   1774  */
   1775 void *_XGetRequest(Display *dpy, CARD8 type, size_t len)
   1776 {
   1777     xReq *req;
   1778 
   1779     if (dpy->bufptr + len > dpy->bufmax)
   1780 	_XFlush(dpy);
   1781     /* Request still too large, so do not allow it to overflow. */
   1782     if (dpy->bufptr + len > dpy->bufmax) {
   1783 	fprintf(stderr,
   1784 		"Xlib: request %d length %zd would exceed buffer size.\n",
   1785 		type, len);
   1786 	/* Changes failure condition from overflow to NULL dereference. */
   1787 	return NULL;
   1788     }
   1789 
   1790     if (len % 4)
   1791 	fprintf(stderr,
   1792 		"Xlib: request %d length %zd not a multiple of 4.\n",
   1793 		type, len);
   1794 
   1795     dpy->last_req = dpy->bufptr;
   1796 
   1797     req = (xReq*)dpy->bufptr;
   1798     *req = (xReq) {
   1799         .reqType = type,
   1800         .data = 0,
   1801         .length = len / 4
   1802     };
   1803     dpy->bufptr += len;
   1804     X_DPY_REQUEST_INCREMENT(dpy);
   1805     return req;
   1806 }
   1807 
   1808 #if defined(WIN32)
   1809 
   1810 /*
   1811  * These functions are intended to be used internally to Xlib only.
   1812  * These functions will always prefix the path with a DOS drive in the
   1813  * form "<drive-letter>:". As such, these functions are only suitable
   1814  * for use by Xlib function that supply a root-based path to some
   1815  * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
   1816  * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
   1817  */
   1818 
   1819 static int access_file (path, pathbuf, len_pathbuf, pathret)
   1820     char* path;
   1821     char* pathbuf;
   1822     int len_pathbuf;
   1823     char** pathret;
   1824 {
   1825     if (access (path, F_OK) == 0) {
   1826 	if (strlen (path) < len_pathbuf)
   1827 	    *pathret = pathbuf;
   1828 	else
   1829 	    *pathret = Xmalloc (strlen (path) + 1);
   1830 	if (*pathret) {
   1831 	    strcpy (*pathret, path);
   1832 	    return 1;
   1833 	}
   1834     }
   1835     return 0;
   1836 }
   1837 
   1838 static int AccessFile (path, pathbuf, len_pathbuf, pathret)
   1839     char* path;
   1840     char* pathbuf;
   1841     int len_pathbuf;
   1842     char** pathret;
   1843 {
   1844     unsigned long drives;
   1845     int i, len;
   1846     char* drive;
   1847     char buf[MAX_PATH];
   1848     char* bufp;
   1849 
   1850     /* just try the "raw" name first and see if it works */
   1851     if (access_file (path, pathbuf, len_pathbuf, pathret))
   1852 	return 1;
   1853 
   1854     /* try the places set in the environment */
   1855     drive = getenv ("_XBASEDRIVE");
   1856     if (!drive)
   1857 	drive = "C:";
   1858     len = strlen (drive) + strlen (path);
   1859     if (len < MAX_PATH) bufp = buf;
   1860     else bufp = Xmalloc (len + 1);
   1861     strcpy (bufp, drive);
   1862     strcat (bufp, path);
   1863     if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
   1864 	if (bufp != buf) Xfree (bufp);
   1865 	return 1;
   1866     }
   1867 
   1868     /* one last place to look */
   1869     drive = getenv ("HOMEDRIVE");
   1870     if (drive) {
   1871 	len = strlen (drive) + strlen (path);
   1872 	if (len < MAX_PATH) bufp = buf;
   1873 	else bufp = Xmalloc (len + 1);
   1874 	strcpy (bufp, drive);
   1875 	strcat (bufp, path);
   1876 	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
   1877 	    if (bufp != buf) Xfree (bufp);
   1878 	    return 1;
   1879 	}
   1880     }
   1881 
   1882     /* tried everywhere else, go fishing */
   1883 #define C_DRIVE ('C' - 'A')
   1884 #define Z_DRIVE ('Z' - 'A')
   1885     drives = _getdrives ();
   1886     for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
   1887 	if ((1 << i) & drives) {
   1888 	    len = 2 + strlen (path);
   1889 	    if (len < MAX_PATH) bufp = buf;
   1890 	    else bufp = Xmalloc (len + 1);
   1891 	    *bufp = 'A' + i;
   1892 	    *(bufp + 1) = ':';
   1893 	    *(bufp + 2) = '\0';
   1894 	    strcat (bufp, path);
   1895 	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
   1896 		if (bufp != buf) Xfree (bufp);
   1897 		return 1;
   1898 	    }
   1899 	}
   1900     }
   1901     return 0;
   1902 }
   1903 
   1904 int _XOpenFile(path, flags)
   1905     _Xconst char* path;
   1906     int flags;
   1907 {
   1908     char buf[MAX_PATH];
   1909     char* bufp = NULL;
   1910     int ret = -1;
   1911     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
   1912 
   1913     if (AccessFile (path, buf, MAX_PATH, &bufp))
   1914 	ret = open (bufp, flags);
   1915 
   1916     (void) SetErrorMode (olderror);
   1917 
   1918     if (bufp != buf) Xfree (bufp);
   1919 
   1920     return ret;
   1921 }
   1922 
   1923 int _XOpenFileMode(path, flags, mode)
   1924     _Xconst char* path;
   1925     int flags;
   1926     mode_t mode;
   1927 {
   1928     char buf[MAX_PATH];
   1929     char* bufp = NULL;
   1930     int ret = -1;
   1931     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
   1932 
   1933     if (AccessFile (path, buf, MAX_PATH, &bufp))
   1934 	ret = open (bufp, flags, mode);
   1935 
   1936     (void) SetErrorMode (olderror);
   1937 
   1938     if (bufp != buf) Xfree (bufp);
   1939 
   1940     return ret;
   1941 }
   1942 
   1943 void* _XFopenFile(path, mode)
   1944     _Xconst char* path;
   1945     _Xconst char* mode;
   1946 {
   1947     char buf[MAX_PATH];
   1948     char* bufp = NULL;
   1949     void* ret = NULL;
   1950     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
   1951 
   1952     if (AccessFile (path, buf, MAX_PATH, &bufp))
   1953 	ret = fopen (bufp, mode);
   1954 
   1955     (void) SetErrorMode (olderror);
   1956 
   1957     if (bufp != buf) Xfree (bufp);
   1958 
   1959     return ret;
   1960 }
   1961 
   1962 int _XAccessFile(path)
   1963     _Xconst char* path;
   1964 {
   1965     char buf[MAX_PATH];
   1966     char* bufp;
   1967     int ret = -1;
   1968     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
   1969 
   1970     ret = AccessFile (path, buf, MAX_PATH, &bufp);
   1971 
   1972     (void) SetErrorMode (olderror);
   1973 
   1974     if (bufp != buf) Xfree (bufp);
   1975 
   1976     return ret;
   1977 }
   1978 
   1979 #endif
   1980 
   1981 #ifdef WIN32
   1982 #undef _Xdebug
   1983 int _Xdebug = 0;
   1984 int *_Xdebug_p = &_Xdebug;
   1985 void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
   1986 void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
   1987 void (**_XLockMutex_fn_p)(LockInfoPtr
   1988 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
   1989     , char * /* file */
   1990     , int /* line */
   1991 #endif
   1992         ) = &_XLockMutex_fn;
   1993 void (**_XUnlockMutex_fn_p)(LockInfoPtr
   1994 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
   1995     , char * /* file */
   1996     , int /* line */
   1997 #endif
   1998         ) = &_XUnlockMutex_fn;
   1999 LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
   2000 #endif
   2001