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