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