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