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