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