XlibInt.c revision bd8e7fb0
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    _X_UNUSED 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 */
1241_X_NORETURN int _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
1386    /*
1387     * Store in dpy flags that the client is exiting on an unhandled XError
1388     * (pretend it is an IOError, since the application is dying anyway it
1389     * does not make a difference).
1390     * This is useful for _XReply not to hang if the application makes Xlib
1391     * calls in _fini as part of process termination.
1392     */
1393    dpy->flags |= XlibDisplayIOError;
1394
1395    exit(1);
1396    /*NOTREACHED*/
1397}
1398
1399/*ARGSUSED*/
1400Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
1401{
1402    return True;
1403}
1404
1405/*
1406 * _XError - upcall internal or user protocol error handler
1407 */
1408int _XError (
1409    Display *dpy,
1410    register xError *rep)
1411{
1412    /*
1413     * X_Error packet encountered!  We need to unpack the error before
1414     * giving it to the user.
1415     */
1416    XEvent event; /* make it a large event */
1417    register _XAsyncHandler *async, *next;
1418
1419    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
1420
1421    for (async = dpy->async_handlers; async; async = next) {
1422	next = async->next;
1423	if ((*async->handler)(dpy, (xReply *)rep,
1424			      (char *)rep, SIZEOF(xError), async->data))
1425	    return 0;
1426    }
1427
1428    event.xerror.display = dpy;
1429    event.xerror.type = X_Error;
1430    event.xerror.resourceid = rep->resourceID;
1431    event.xerror.error_code = rep->errorCode;
1432    event.xerror.request_code = rep->majorCode;
1433    event.xerror.minor_code = rep->minorCode;
1434    if (dpy->error_vec &&
1435	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
1436	return 0;
1437    if (_XErrorFunction != NULL) {
1438	int rtn_val;
1439#ifdef XTHREADS
1440	if (dpy->lock)
1441	    (*dpy->lock->user_lock_display)(dpy);
1442	UnlockDisplay(dpy);
1443#endif
1444	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
1445#ifdef XTHREADS
1446	LockDisplay(dpy);
1447	if (dpy->lock)
1448	    (*dpy->lock->user_unlock_display)(dpy);
1449#endif
1450	return rtn_val;
1451    } else {
1452	return _XDefaultError(dpy, (XErrorEvent *)&event);
1453    }
1454}
1455
1456/*
1457 * _XIOError - call user connection error handler and exit
1458 */
1459int
1460_XIOError (
1461    Display *dpy)
1462{
1463    dpy->flags |= XlibDisplayIOError;
1464#ifdef WIN32
1465    errno = WSAGetLastError();
1466#endif
1467
1468    /* This assumes that the thread calling exit will call any atexit handlers.
1469     * If this does not hold, then an alternate solution would involve
1470     * registering an atexit handler to take over the lock, which would only
1471     * assume that the same thread calls all the atexit handlers. */
1472#ifdef XTHREADS
1473    if (dpy->lock)
1474	(*dpy->lock->user_lock_display)(dpy);
1475#endif
1476    UnlockDisplay(dpy);
1477
1478    if (_XIOErrorFunction != NULL)
1479	(*_XIOErrorFunction)(dpy);
1480    else
1481	_XDefaultIOError(dpy);
1482    exit (1);
1483    /*NOTREACHED*/
1484}
1485
1486
1487/*
1488 * This routine can be used to (cheaply) get some memory within a single
1489 * Xlib routine for scratch space.  A single buffer is reused each time
1490 * if possible.  To be MT safe, you can only call this between a call to
1491 * GetReq* and a call to Data* or _XSend*, or in a context when the thread
1492 * is guaranteed to not unlock the display.
1493 */
1494char *_XAllocScratch(
1495	register Display *dpy,
1496	unsigned long nbytes)
1497{
1498	if (nbytes > dpy->scratch_length) {
1499	    Xfree (dpy->scratch_buffer);
1500	    dpy->scratch_buffer = Xmalloc(nbytes);
1501	    if (dpy->scratch_buffer)
1502		dpy->scratch_length = nbytes;
1503	    else dpy->scratch_length = 0;
1504	}
1505	return (dpy->scratch_buffer);
1506}
1507
1508/*
1509 * Scratch space allocator you can call any time, multiple times, and be
1510 * MT safe, but you must hand the buffer back with _XFreeTemp.
1511 */
1512char *_XAllocTemp(
1513    register Display *dpy,
1514    unsigned long nbytes)
1515{
1516    char *buf;
1517
1518    buf = _XAllocScratch(dpy, nbytes);
1519    dpy->scratch_buffer = NULL;
1520    dpy->scratch_length = 0;
1521    return buf;
1522}
1523
1524void _XFreeTemp(
1525    register Display *dpy,
1526    char *buf,
1527    unsigned long nbytes)
1528{
1529
1530    Xfree(dpy->scratch_buffer);
1531    dpy->scratch_buffer = buf;
1532    dpy->scratch_length = nbytes;
1533}
1534
1535/*
1536 * Given a visual id, find the visual structure for this id on this display.
1537 */
1538Visual *_XVIDtoVisual(
1539	Display *dpy,
1540	VisualID id)
1541{
1542	register int i, j, k;
1543	register Screen *sp;
1544	register Depth *dp;
1545	register Visual *vp;
1546	for (i = 0; i < dpy->nscreens; i++) {
1547		sp = &dpy->screens[i];
1548		for (j = 0; j < sp->ndepths; j++) {
1549			dp = &sp->depths[j];
1550			/* if nvisuals == 0 then visuals will be NULL */
1551			for (k = 0; k < dp->nvisuals; k++) {
1552				vp = &dp->visuals[k];
1553				if (vp->visualid == id) return (vp);
1554			}
1555		}
1556	}
1557	return (NULL);
1558}
1559
1560int
1561XFree (void *data)
1562{
1563	Xfree (data);
1564	return 1;
1565}
1566
1567#ifdef _XNEEDBCOPYFUNC
1568void _Xbcopy(b1, b2, length)
1569    register char *b1, *b2;
1570    register length;
1571{
1572    if (b1 < b2) {
1573	b2 += length;
1574	b1 += length;
1575	while (length--)
1576	    *--b2 = *--b1;
1577    } else {
1578	while (length--)
1579	    *b2++ = *b1++;
1580    }
1581}
1582#endif
1583
1584#ifdef DataRoutineIsProcedure
1585void Data(
1586	Display *dpy,
1587	_Xconst char *data,
1588	long len)
1589{
1590	if (dpy->bufptr + (len) <= dpy->bufmax) {
1591		memcpy(dpy->bufptr, data, (int)len);
1592		dpy->bufptr += ((len) + 3) & ~3;
1593	} else {
1594		_XSend(dpy, data, len);
1595	}
1596}
1597#endif /* DataRoutineIsProcedure */
1598
1599
1600#ifdef LONG64
1601int
1602_XData32(
1603    Display *dpy,
1604    register _Xconst long *data,
1605    unsigned len)
1606{
1607    register int *buf;
1608    register long i;
1609
1610    while (len) {
1611	buf = (int *)dpy->bufptr;
1612	i = dpy->bufmax - (char *)buf;
1613	if (!i) {
1614	    _XFlush(dpy);
1615	    continue;
1616	}
1617	if (len < i)
1618	    i = len;
1619	dpy->bufptr = (char *)buf + i;
1620	len -= i;
1621	i >>= 2;
1622	while (--i >= 0)
1623	    *buf++ = *data++;
1624    }
1625    return 0;
1626}
1627#endif /* LONG64 */
1628
1629
1630
1631/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
1632 * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
1633 *
1634 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
1635 *       to have sufficient information for interfacing to the network,
1636 *       and so, you may be better off using gethostname (if it exists).
1637 */
1638
1639#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
1640#define NEED_UTSNAME
1641#include <sys/utsname.h>
1642#else
1643#ifdef HAVE_UNISTD_H
1644#include <unistd.h>
1645#endif
1646#endif
1647
1648/*
1649 * _XGetHostname - similar to gethostname but allows special processing.
1650 */
1651int _XGetHostname (
1652    char *buf,
1653    int maxlen)
1654{
1655    int len;
1656
1657#ifdef NEED_UTSNAME
1658    struct utsname name;
1659
1660    if (maxlen <= 0 || buf == NULL)
1661	return 0;
1662
1663    uname (&name);
1664    len = strlen (name.nodename);
1665    if (len >= maxlen) len = maxlen - 1;
1666    strncpy (buf, name.nodename, len);
1667    buf[len] = '\0';
1668#else
1669    if (maxlen <= 0 || buf == NULL)
1670	return 0;
1671
1672    buf[0] = '\0';
1673    (void) gethostname (buf, maxlen);
1674    buf [maxlen - 1] = '\0';
1675    len = strlen(buf);
1676#endif /* NEED_UTSNAME */
1677    return len;
1678}
1679
1680
1681/*
1682 * _XScreenOfWindow - get the Screen of a given window
1683 */
1684
1685Screen *_XScreenOfWindow(Display *dpy, Window w)
1686{
1687    register int i;
1688    Window root;
1689    int x, y;				/* dummy variables */
1690    unsigned int width, height, bw, depth;  /* dummy variables */
1691
1692    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
1693		      &bw, &depth) == False) {
1694	return NULL;
1695    }
1696    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
1697	if (root == RootWindow (dpy, i)) {
1698	    return ScreenOfDisplay (dpy, i);
1699	}
1700    }
1701    return NULL;
1702}
1703
1704
1705/*
1706 * WARNING: This implementation's pre-conditions and post-conditions
1707 * must remain compatible with the old macro-based implementations of
1708 * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the
1709 * Display structure affected by those macros are part of libX11's
1710 * ABI.
1711 */
1712void *_XGetRequest(Display *dpy, CARD8 type, size_t len)
1713{
1714    xReq *req;
1715
1716    if (dpy->bufptr + len > dpy->bufmax)
1717	_XFlush(dpy);
1718    /* Request still too large, so do not allow it to overflow. */
1719    if (dpy->bufptr + len > dpy->bufmax) {
1720	fprintf(stderr,
1721		"Xlib: request %d length %zd would exceed buffer size.\n",
1722		type, len);
1723	/* Changes failure condition from overflow to NULL dereference. */
1724	return NULL;
1725    }
1726
1727    if (len % 4)
1728	fprintf(stderr,
1729		"Xlib: request %d length %zd not a multiple of 4.\n",
1730		type, len);
1731
1732    dpy->last_req = dpy->bufptr;
1733
1734    req = (xReq*)dpy->bufptr;
1735    req->reqType = type;
1736    req->length = len / 4;
1737    dpy->bufptr += len;
1738    X_DPY_REQUEST_INCREMENT(dpy);
1739    return req;
1740}
1741
1742#if defined(WIN32)
1743
1744/*
1745 * These functions are intended to be used internally to Xlib only.
1746 * These functions will always prefix the path with a DOS drive in the
1747 * form "<drive-letter>:". As such, these functions are only suitable
1748 * for use by Xlib function that supply a root-based path to some
1749 * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
1750 * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
1751 */
1752
1753static int access_file (path, pathbuf, len_pathbuf, pathret)
1754    char* path;
1755    char* pathbuf;
1756    int len_pathbuf;
1757    char** pathret;
1758{
1759    if (access (path, F_OK) == 0) {
1760	if (strlen (path) < len_pathbuf)
1761	    *pathret = pathbuf;
1762	else
1763	    *pathret = Xmalloc (strlen (path) + 1);
1764	if (*pathret) {
1765	    strcpy (*pathret, path);
1766	    return 1;
1767	}
1768    }
1769    return 0;
1770}
1771
1772static int AccessFile (path, pathbuf, len_pathbuf, pathret)
1773    char* path;
1774    char* pathbuf;
1775    int len_pathbuf;
1776    char** pathret;
1777{
1778    unsigned long drives;
1779    int i, len;
1780    char* drive;
1781    char buf[MAX_PATH];
1782    char* bufp;
1783
1784    /* just try the "raw" name first and see if it works */
1785    if (access_file (path, pathbuf, len_pathbuf, pathret))
1786	return 1;
1787
1788    /* try the places set in the environment */
1789    drive = getenv ("_XBASEDRIVE");
1790#ifdef __UNIXOS2__
1791    if (!drive)
1792	drive = getenv ("X11ROOT");
1793#endif
1794    if (!drive)
1795	drive = "C:";
1796    len = strlen (drive) + strlen (path);
1797    if (len < MAX_PATH) bufp = buf;
1798    else bufp = Xmalloc (len + 1);
1799    strcpy (bufp, drive);
1800    strcat (bufp, path);
1801    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
1802	if (bufp != buf) Xfree (bufp);
1803	return 1;
1804    }
1805
1806#ifndef __UNIXOS2__
1807    /* one last place to look */
1808    drive = getenv ("HOMEDRIVE");
1809    if (drive) {
1810	len = strlen (drive) + strlen (path);
1811	if (len < MAX_PATH) bufp = buf;
1812	else bufp = Xmalloc (len + 1);
1813	strcpy (bufp, drive);
1814	strcat (bufp, path);
1815	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
1816	    if (bufp != buf) Xfree (bufp);
1817	    return 1;
1818	}
1819    }
1820
1821    /* tried everywhere else, go fishing */
1822#define C_DRIVE ('C' - 'A')
1823#define Z_DRIVE ('Z' - 'A')
1824    /* does OS/2 (with or with gcc-emx) have getdrives? */
1825    drives = _getdrives ();
1826    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
1827	if ((1 << i) & drives) {
1828	    len = 2 + strlen (path);
1829	    if (len < MAX_PATH) bufp = buf;
1830	    else bufp = Xmalloc (len + 1);
1831	    *bufp = 'A' + i;
1832	    *(bufp + 1) = ':';
1833	    *(bufp + 2) = '\0';
1834	    strcat (bufp, path);
1835	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
1836		if (bufp != buf) Xfree (bufp);
1837		return 1;
1838	    }
1839	}
1840    }
1841#endif
1842    return 0;
1843}
1844
1845int _XOpenFile(path, flags)
1846    _Xconst char* path;
1847    int flags;
1848{
1849    char buf[MAX_PATH];
1850    char* bufp = NULL;
1851    int ret = -1;
1852    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
1853
1854    if (AccessFile (path, buf, MAX_PATH, &bufp))
1855	ret = open (bufp, flags);
1856
1857    (void) SetErrorMode (olderror);
1858
1859    if (bufp != buf) Xfree (bufp);
1860
1861    return ret;
1862}
1863
1864int _XOpenFileMode(path, flags, mode)
1865    _Xconst char* path;
1866    int flags;
1867    mode_t mode;
1868{
1869    char buf[MAX_PATH];
1870    char* bufp = NULL;
1871    int ret = -1;
1872    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
1873
1874    if (AccessFile (path, buf, MAX_PATH, &bufp))
1875	ret = open (bufp, flags, mode);
1876
1877    (void) SetErrorMode (olderror);
1878
1879    if (bufp != buf) Xfree (bufp);
1880
1881    return ret;
1882}
1883
1884void* _XFopenFile(path, mode)
1885    _Xconst char* path;
1886    _Xconst char* mode;
1887{
1888    char buf[MAX_PATH];
1889    char* bufp = NULL;
1890    void* ret = NULL;
1891    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
1892
1893    if (AccessFile (path, buf, MAX_PATH, &bufp))
1894	ret = fopen (bufp, mode);
1895
1896    (void) SetErrorMode (olderror);
1897
1898    if (bufp != buf) Xfree (bufp);
1899
1900    return ret;
1901}
1902
1903int _XAccessFile(path)
1904    _Xconst char* path;
1905{
1906    char buf[MAX_PATH];
1907    char* bufp;
1908    int ret = -1;
1909    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
1910
1911    ret = AccessFile (path, buf, MAX_PATH, &bufp);
1912
1913    (void) SetErrorMode (olderror);
1914
1915    if (bufp != buf) Xfree (bufp);
1916
1917    return ret;
1918}
1919
1920#endif
1921
1922#ifdef WIN32
1923#undef _Xdebug
1924int _Xdebug = 0;
1925int *_Xdebug_p = &_Xdebug;
1926void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
1927void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
1928void (**_XLockMutex_fn_p)(LockInfoPtr
1929#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
1930    , char * /* file */
1931    , int /* line */
1932#endif
1933        ) = &_XLockMutex_fn;
1934void (**_XUnlockMutex_fn_p)(LockInfoPtr
1935#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
1936    , char * /* file */
1937    , int /* line */
1938#endif
1939        ) = &_XUnlockMutex_fn;
1940LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
1941#endif
1942