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