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