XlibInt.c revision 1ab64890
1/* $Xorg: XlibInt.c,v 1.8 2001/02/09 02:03:38 xorgcvs Exp $ */
2/*
3
4Copyright 1985, 1986, 1987, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included
13in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall
24not be used in advertising or otherwise to promote the sale, use or
25other dealings in this Software without prior written authorization
26from The Open Group.
27
28*/
29/* $XFree86: xc/lib/X11/XlibInt.c,v 3.38 2003/10/30 21:55:05 alanh Exp $ */
30
31/*
32 *	XlibInt.c - Internal support routines for the C subroutine
33 *	interface library (Xlib) to the X Window System Protocol V11.0.
34 */
35#define NEED_EVENTS
36#define NEED_REPLIES
37
38#ifdef WIN32
39#define _XLIBINT_
40#endif
41#ifdef HAVE_CONFIG_H
42#include <config.h>
43#endif
44#include "Xlibint.h"
45#include <X11/Xpoll.h>
46#if !USE_XCB
47#include <X11/Xtrans/Xtrans.h>
48#include <X11/extensions/xcmiscstr.h>
49#endif /* !USE_XCB */
50#include <stdio.h>
51#ifdef WIN32
52#include <direct.h>
53#endif
54
55#ifdef XTHREADS
56#include "locking.h"
57
58/* these pointers get initialized by XInitThreads */
59LockInfoPtr _Xglobal_lock = NULL;
60void (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
61/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
62void (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
63void (*_XLockMutex_fn)(
64    LockInfoPtr /* lock */
65#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
66    , char * /* file */
67    , int /* line */
68#endif
69    ) = NULL;
70void (*_XUnlockMutex_fn)(
71    LockInfoPtr /* lock */
72#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
73    , char * /* file */
74    , int /* line */
75#endif
76    ) = NULL;
77xthread_t (*_Xthread_self_fn)(void) = NULL;
78
79#define XThread_Self()	((*_Xthread_self_fn)())
80
81#if !USE_XCB
82#define UnlockNextReplyReader(d) if ((d)->lock) \
83    (*(d)->lock->pop_reader)((d),&(d)->lock->reply_awaiters,&(d)->lock->reply_awaiters_tail)
84
85#define QueueReplyReaderLock(d) ((d)->lock ? \
86    (*(d)->lock->push_reader)(d,&(d)->lock->reply_awaiters_tail) : NULL)
87#define QueueEventReaderLock(d) ((d)->lock ? \
88    (*(d)->lock->push_reader)(d,&(d)->lock->event_awaiters_tail) : NULL)
89
90#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
91#define InternalLockDisplay(d,wskip) if ((d)->lock) \
92    (*(d)->lock->internal_lock_display)(d,wskip,__FILE__,__LINE__)
93#else
94#define InternalLockDisplay(d,wskip) if ((d)->lock) \
95    (*(d)->lock->internal_lock_display)(d,wskip)
96#endif
97#endif /* !USE_XCB */
98
99#else /* XTHREADS else */
100
101#if !USE_XCB
102#define UnlockNextReplyReader(d)
103#define UnlockNextEventReader(d)
104#define InternalLockDisplay(d,wskip)
105#endif /* !USE_XCB */
106
107#endif /* XTHREADS else */
108
109/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
110 * systems are broken and return EWOULDBLOCK when they should return EAGAIN
111 */
112#ifdef WIN32
113#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
114#else
115#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */
116#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
117#else
118#if defined(EAGAIN) && defined(EWOULDBLOCK)
119#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
120#else
121#ifdef EAGAIN
122#define ETEST() (errno == EAGAIN)
123#else
124#define ETEST() (errno == EWOULDBLOCK)
125#endif /* EAGAIN */
126#endif /* EAGAIN && EWOULDBLOCK */
127#endif /* __CYGWIN__ */
128#endif /* WIN32 */
129
130#ifdef WIN32
131#define ECHECK(err) (WSAGetLastError() == err)
132#define ESET(val) WSASetLastError(val)
133#else
134#ifdef __UNIXOS2__
135#define ECHECK(err) (errno == err)
136#define ESET(val)
137#else
138#ifdef ISC
139#define ECHECK(err) ((errno == err) || ETEST())
140#else
141#define ECHECK(err) (errno == err)
142#endif
143#define ESET(val) errno = val
144#endif
145#endif
146
147#if defined(LOCALCONN) || defined(LACHMAN)
148#ifdef EMSGSIZE
149#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE))
150#else
151#define ESZTEST() ECHECK(ERANGE)
152#endif
153#else
154#ifdef EMSGSIZE
155#define ESZTEST() ECHECK(EMSGSIZE)
156#endif
157#endif
158
159#ifdef __UNIXOS2__
160#if !USE_XCB
161#define select(n,r,w,x,t) os2ClientSelect(n,r,w,x,t)
162#endif /* !USE_XCB */
163#include <limits.h>
164#define MAX_PATH _POSIX_PATH_MAX
165#endif
166
167#if !USE_XCB
168#ifdef MUSTCOPY
169
170#define STARTITERATE(tpvar,type,start,endcond) \
171  { register char *cpvar; \
172  for (cpvar = (char *) (start); endcond; ) { \
173    type dummy; memcpy ((char *) &dummy, cpvar, SIZEOF(type)); \
174    tpvar = &dummy;
175#define ITERPTR(tpvar) cpvar
176#define RESETITERPTR(tpvar,type,start) cpvar = start
177#define INCITERPTR(tpvar,type) cpvar += SIZEOF(type)
178#define ENDITERATE }}
179
180#else
181
182#define STARTITERATE(tpvar,type,start,endcond) \
183  for (tpvar = (type *) (start); endcond; )
184#define ITERPTR(tpvar) (char *)tpvar
185#define RESETITERPTR(tpvar,type,start) tpvar = (type *) (start)
186#define INCITERPTR(tpvar,type) tpvar++
187#define ENDITERATE
188
189#endif /* MUSTCOPY */
190
191typedef union {
192    xReply rep;
193    char buf[BUFSIZE];
194} _XAlignedBuffer;
195
196static char *_XAsyncReply(
197    Display *dpy,
198    register xReply *rep,
199    char *buf,
200    register int *lenp,
201    Bool discard);
202#endif /* !USE_XCB */
203
204#define SEQLIMIT (65535 - (BUFSIZE / SIZEOF(xReq)) - 10)
205
206/*
207 * The following routines are internal routines used by Xlib for protocol
208 * packet transmission and reception.
209 *
210 * _XIOError(Display *) will be called if any sort of system call error occurs.
211 * This is assumed to be a fatal condition, i.e., XIOError should not return.
212 *
213 * _XError(Display *, xError *) will be called whenever an X_Error event is
214 * received.  This is not assumed to be a fatal condition, i.e., it is
215 * acceptable for this procedure to return.  However, XError should NOT
216 * perform any operations (directly or indirectly) on the DISPLAY.
217 *
218 * Routines declared with a return type of 'Status' return 0 on failure,
219 * and non 0 on success.  Routines with no declared return type don't
220 * return anything.  Whenever possible routines that create objects return
221 * the object they have created.
222 */
223
224#if !USE_XCB
225static xReq _dummy_request = {
226	0, 0, 0
227};
228
229/*
230 * This is an OS dependent routine which:
231 * 1) returns as soon as the connection can be written on....
232 * 2) if the connection can be read, must enqueue events and handle errors,
233 * until the connection is writable.
234 */
235static void
236_XWaitForWritable(
237    Display *dpy
238#ifdef XTHREADS
239    ,
240    xcondition_t cv		/* our reading condition variable */
241#endif
242    )
243{
244#ifdef USE_POLL
245    struct pollfd filedes;
246#else
247    fd_set r_mask;
248    fd_set w_mask;
249#endif
250    int nfound;
251
252#ifdef USE_POLL
253    filedes.fd = dpy->fd;
254    filedes.events = 0;
255#else
256    FD_ZERO(&r_mask);
257    FD_ZERO(&w_mask);
258#endif
259
260    for (;;) {
261#ifdef XTHREADS
262	/* We allow only one thread at a time to read, to minimize
263	   passing of read data between threads.
264	   Now, who is it?  If there is a non-NULL reply_awaiters and
265	   we (i.e., our cv) are not at the head of it, then whoever
266	   is at the head is the reader, and we don't read.
267	   Otherwise there is no reply_awaiters or we are at the
268	   head, having just appended ourselves.
269	   In this case, if there is a event_awaiters, then whoever
270	   is at the head of it got there before we did, and they are the
271	   reader.
272
273	   Last cases: no event_awaiters and we are at the head of
274	   reply_awaiters or reply_awaiters is NULL: we are the reader,
275	   since there is obviously no one else involved.
276
277	   XXX - what if cv is NULL and someone else comes along after
278	   us while we are waiting?
279	   */
280
281	if (!dpy->lock ||
282	    (!dpy->lock->event_awaiters &&
283	     (!dpy->lock->reply_awaiters ||
284	      dpy->lock->reply_awaiters->cv == cv)))
285#endif
286#ifdef USE_POLL
287	    filedes.events = POLLIN;
288	filedes.events |= POLLOUT;
289#else
290	FD_SET(dpy->fd, &r_mask);
291        FD_SET(dpy->fd, &w_mask);
292#endif
293
294	do {
295	    UnlockDisplay(dpy);
296#ifdef USE_POLL
297	    nfound = poll (&filedes, 1, -1);
298#else
299	    nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL);
300#endif
301	    InternalLockDisplay(dpy, cv != NULL);
302	    if (nfound < 0 && !ECHECK(EINTR))
303		_XIOError(dpy);
304	} while (nfound <= 0);
305
306	if (
307#ifdef USE_POLL
308	    filedes.revents & POLLIN
309#else
310	    FD_ISSET(dpy->fd, &r_mask)
311#endif
312	    )
313	{
314	    _XAlignedBuffer buf;
315	    BytesReadable_t pend;
316	    register int len;
317	    register xReply *rep;
318
319	    /* find out how much data can be read */
320	    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
321		_XIOError(dpy);
322	    len = pend;
323
324	    /* must read at least one xEvent; if none is pending, then
325	       we'll just block waiting for it */
326	    if (len < SIZEOF(xReply)
327#ifdef XTHREADS
328		|| dpy->async_handlers
329#endif
330		)
331		len = SIZEOF(xReply);
332
333	    /* but we won't read more than the max buffer size */
334	    if (len > BUFSIZE) len = BUFSIZE;
335
336	    /* round down to an integral number of XReps */
337	    len = (len / SIZEOF(xReply)) * SIZEOF(xReply);
338
339	    (void) _XRead (dpy, buf.buf, (long) len);
340
341	    STARTITERATE(rep,xReply,buf.buf,len > 0) {
342		if (rep->generic.type == X_Reply) {
343                    int tmp = len;
344		    RESETITERPTR(rep,xReply,
345				 _XAsyncReply (dpy, rep,
346					       ITERPTR(rep), &tmp, True));
347                    len = tmp;
348		    pend = len;
349		} else {
350		    if (rep->generic.type == X_Error)
351			_XError (dpy, (xError *)rep);
352		    else	/* must be an event packet */
353			_XEnq (dpy, (xEvent *)rep);
354		    INCITERPTR(rep,xReply);
355		    len -= SIZEOF(xReply);
356		}
357	    } ENDITERATE
358#ifdef XTHREADS
359	    if (dpy->lock && dpy->lock->event_awaiters)
360		ConditionSignal(dpy, dpy->lock->event_awaiters->cv);
361#endif
362	}
363#ifdef USE_POLL
364	if (filedes.revents & (POLLOUT|POLLHUP|POLLERR))
365#else
366	if (FD_ISSET(dpy->fd, &w_mask))
367#endif
368	{
369#ifdef XTHREADS
370	    if (dpy->lock) {
371		ConditionBroadcast(dpy, dpy->lock->writers);
372	    }
373#endif
374	    return;
375	}
376    }
377}
378#endif /* !USE_XCB */
379
380
381#define POLLFD_CACHE_SIZE 5
382
383/* initialize the struct array passed to poll() below */
384Bool _XPollfdCacheInit(
385    Display *dpy)
386{
387#ifdef USE_POLL
388    struct pollfd *pfp;
389
390    pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
391    if (!pfp)
392	return False;
393    pfp[0].fd = dpy->fd;
394    pfp[0].events = POLLIN;
395
396    dpy->filedes = (XPointer)pfp;
397#endif
398    return True;
399}
400
401void _XPollfdCacheAdd(
402    Display *dpy,
403    int fd)
404{
405#ifdef USE_POLL
406    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
407
408    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
409	pfp[dpy->im_fd_length].fd = fd;
410	pfp[dpy->im_fd_length].events = POLLIN;
411    }
412#endif
413}
414
415/* ARGSUSED */
416void _XPollfdCacheDel(
417    Display *dpy,
418    int fd)			/* not used */
419{
420#ifdef USE_POLL
421    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
422    struct _XConnectionInfo *conni;
423
424    /* just recalculate whole list */
425    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
426	int loc = 1;
427	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
428	    pfp[loc].fd = conni->fd;
429	    pfp[loc].events = POLLIN;
430	    loc++;
431	}
432    }
433#endif
434}
435
436#if !USE_XCB
437/* returns True iff there is an event in the queue newer than serial_num */
438
439static Bool
440_XNewerQueuedEvent(
441    Display *dpy,
442    int serial_num)
443{
444    _XQEvent *qev;
445
446    if (dpy->next_event_serial_num == serial_num)
447	return False;
448
449    qev = dpy->head;
450    while (qev) {
451	if (qev->qserial_num >= serial_num) {
452	    return True;
453	}
454	qev = qev->next;
455    }
456    return False;
457}
458
459static int
460_XWaitForReadable(
461  Display *dpy)
462{
463    int result;
464    int fd = dpy->fd;
465    struct _XConnectionInfo *ilist;
466    register int saved_event_serial = 0;
467    int in_read_events = 0;
468    register Bool did_proc_conni = False;
469#ifdef USE_POLL
470    struct pollfd *filedes;
471#else
472    fd_set r_mask;
473    int highest_fd = fd;
474#endif
475
476#ifdef USE_POLL
477    if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE
478	&& !(dpy->flags & XlibDisplayProcConni)) {
479	/* XXX - this fallback is gross */
480	int i;
481
482	filedes = (struct pollfd *)Xmalloc(dpy->im_fd_length * sizeof(struct pollfd));
483	filedes[0].fd = fd;
484	filedes[0].events = POLLIN;
485	for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) {
486	    filedes[i].fd = ilist->fd;
487	    filedes[i].events = POLLIN;
488	}
489    } else {
490	filedes = (struct pollfd *)dpy->filedes;
491    }
492#else
493    FD_ZERO(&r_mask);
494#endif
495    for (;;) {
496#ifndef USE_POLL
497	FD_SET(fd, &r_mask);
498	if (!(dpy->flags & XlibDisplayProcConni))
499	    for (ilist=dpy->im_fd_info; ilist; ilist=ilist->next) {
500		FD_SET(ilist->fd, &r_mask);
501		if (ilist->fd > highest_fd)
502		    highest_fd = ilist->fd;
503	    }
504#endif
505	UnlockDisplay(dpy);
506#ifdef USE_POLL
507	result = poll(filedes,
508		      (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length,
509		      -1);
510#else
511	result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL);
512#endif
513	InternalLockDisplay(dpy, dpy->flags & XlibDisplayReply);
514	if (result == -1 && !ECHECK(EINTR)) _XIOError(dpy);
515	if (result <= 0)
516	    continue;
517#ifdef USE_POLL
518	if (filedes[0].revents & (POLLIN|POLLHUP|POLLERR))
519#else
520	if (FD_ISSET(fd, &r_mask))
521#endif
522	    break;
523	if (!(dpy->flags & XlibDisplayProcConni)) {
524	    int i;
525
526	    saved_event_serial = dpy->next_event_serial_num;
527	    /* dpy flags can be clobbered by internal connection callback */
528	    in_read_events = dpy->flags & XlibDisplayReadEvents;
529	    for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) {
530#ifdef USE_POLL
531		if (filedes[i].revents & POLLIN)
532#else
533		if (FD_ISSET(ilist->fd, &r_mask))
534#endif
535		{
536		    _XProcessInternalConnection(dpy, ilist);
537		    did_proc_conni = True;
538		}
539	    }
540#ifdef USE_POLL
541	    if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE)
542		Xfree(filedes);
543#endif
544	}
545	if (did_proc_conni) {
546	    /* some internal connection callback might have done an
547	       XPutBackEvent.  We notice it here and if we needed an event,
548	       we can return all the way. */
549	    if (_XNewerQueuedEvent(dpy, saved_event_serial)
550		&& (in_read_events
551#ifdef XTHREADS
552		    || (dpy->lock && dpy->lock->event_awaiters)
553#endif
554		    ))
555		return -2;
556	    did_proc_conni = False;
557	}
558    }
559#ifdef XTHREADS
560#ifdef XTHREADS_DEBUG
561    printf("thread %x _XWaitForReadable returning\n", XThread_Self());
562#endif
563#endif
564    return 0;
565}
566#endif /* !USE_XCB */
567
568static
569int _XSeqSyncFunction(
570    register Display *dpy)
571{
572    xGetInputFocusReply rep;
573    register xReq *req;
574
575    LockDisplay(dpy);
576    if ((dpy->request - dpy->last_request_read) >= (BUFSIZE / SIZEOF(xReq))) {
577	GetEmptyReq(GetInputFocus, req);
578	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
579    }
580    /* could get XID handler while waiting for reply in MT env */
581    if (dpy->synchandler == _XSeqSyncFunction) {
582	dpy->synchandler = dpy->savedsynchandler;
583	dpy->flags &= ~XlibDisplayPrivSync;
584    }
585    UnlockDisplay(dpy);
586    SyncHandle();
587    return 0;
588}
589
590void _XSetSeqSyncFunction(
591    register Display *dpy)
592{
593    if ((dpy->request - dpy->last_request_read) >= SEQLIMIT &&
594	!(dpy->flags & XlibDisplayPrivSync)) {
595	dpy->savedsynchandler = dpy->synchandler;
596	dpy->synchandler = _XSeqSyncFunction;
597	dpy->flags |= XlibDisplayPrivSync;
598    }
599}
600
601#if !USE_XCB
602#ifdef XTHREADS
603static void _XFlushInt(
604        register Display *dpy,
605        register xcondition_t cv);
606#endif
607
608/*
609 * _XFlush - Flush the X request buffer.  If the buffer is empty, no
610 * action is taken.  This routine correctly handles incremental writes.
611 * This routine may have to be reworked if int < long.
612 */
613void _XFlush(
614	register Display *dpy)
615{
616#ifdef XTHREADS
617    /* With multi-threading we introduce an internal routine to which
618       we can pass a condition variable to do locking correctly. */
619
620    _XFlushInt(dpy, NULL);
621}
622
623/* _XFlushInt - Internal version of _XFlush used to do multi-threaded
624 * locking correctly.
625 */
626
627static void _XFlushInt(
628	register Display *dpy,
629        register xcondition_t cv)
630{
631#endif /* XTHREADS*/
632	register long size, todo;
633	register int write_stat;
634	register char *bufindex;
635	_XExtension *ext;
636
637	/* This fix resets the bufptr to the front of the buffer so
638	 * additional appends to the bufptr will not corrupt memory. Since
639	 * the server is down, these appends are no-op's anyway but
640	 * callers of _XFlush() are not verifying this before they call it.
641	 */
642	if (dpy->flags & XlibDisplayIOError)
643	{
644	    dpy->bufptr = dpy->buffer;
645	    dpy->last_req = (char *)&_dummy_request;
646	    return;
647	}
648
649#ifdef XTHREADS
650	while (dpy->flags & XlibDisplayWriting) {
651	    if (dpy->lock) {
652		ConditionWait(dpy, dpy->lock->writers);
653	    } else {
654		_XWaitForWritable (dpy, cv);
655	    }
656	}
657#endif
658	size = todo = dpy->bufptr - dpy->buffer;
659	if (!size) return;
660#ifdef XTHREADS
661	dpy->flags |= XlibDisplayWriting;
662	/* make sure no one else can put in data */
663	dpy->bufptr = dpy->bufmax;
664#endif
665	for (ext = dpy->flushes; ext; ext = ext->next_flush)
666	    (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, size);
667	bufindex = dpy->buffer;
668	/*
669	 * While write has not written the entire buffer, keep looping
670	 * until the entire buffer is written.  bufindex will be
671	 * incremented and size decremented as buffer is written out.
672	 */
673	while (size) {
674	    ESET(0);
675	    write_stat = _X11TransWrite(dpy->trans_conn,
676					bufindex, (int) todo);
677	    if (write_stat >= 0) {
678		size -= write_stat;
679		todo = size;
680		bufindex += write_stat;
681	    } else if (ETEST()) {
682		_XWaitForWritable(dpy
683#ifdef XTHREADS
684				  , cv
685#endif
686				  );
687#ifdef SUNSYSV
688	    } else if (ECHECK(0)) {
689		_XWaitForWritable(dpy
690#ifdef XTHREADS
691				  , cv
692#endif
693				  );
694#endif
695#ifdef ESZTEST
696	    } else if (ESZTEST()) {
697		if (todo > 1)
698		    todo >>= 1;
699		else {
700		    _XWaitForWritable(dpy
701#ifdef XTHREADS
702				      , cv
703#endif
704				      );
705		}
706#endif
707	    } else if (!ECHECK(EINTR)) {
708		/* Write failed! */
709		/* errno set by write system call. */
710		_XIOError(dpy);
711	    }
712	}
713	dpy->last_req = (char *)&_dummy_request;
714	_XSetSeqSyncFunction(dpy);
715	dpy->bufptr = dpy->buffer;
716#ifdef XTHREADS
717	dpy->flags &= ~XlibDisplayWriting;
718#endif
719}
720
721int
722_XEventsQueued(
723    register Display *dpy,
724    int mode)
725{
726	register int len;
727	BytesReadable_t pend;
728	_XAlignedBuffer buf;
729	register xReply *rep;
730	char *read_buf;
731#ifdef XTHREADS
732	int entry_event_serial_num;
733	struct _XCVList *cvl = NULL;
734	xthread_t self;
735
736#ifdef XTHREADS_DEBUG
737	printf("_XEventsQueued called in thread %x\n", XThread_Self());
738#endif
739#endif /* XTHREADS*/
740
741	if (mode == QueuedAfterFlush)
742	{
743	    _XFlush(dpy);
744	    if (dpy->qlen)
745		return(dpy->qlen);
746	}
747	if (dpy->flags & XlibDisplayIOError) return(dpy->qlen);
748
749#ifdef XTHREADS
750	/* create our condition variable and append to list,
751	 * unless we were called from within XProcessInternalConnection
752	 * or XLockDisplay
753	 */
754	xthread_clear_id(self);
755	if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread)
756			  || xthread_have_id (dpy->lock->locking_thread)))
757	    /* some thread is in XProcessInternalConnection or XLockDisplay
758	       so we have to see if we are it */
759	    self = XThread_Self();
760	if (!xthread_have_id(self)
761	    || (!xthread_equal(self, dpy->lock->conni_thread)
762		&& !xthread_equal(self, dpy->lock->locking_thread))) {
763	    /* In the multi-threaded case, if there is someone else
764	       reading events, then there aren't any available, so
765	       we just return.  If we waited we would block.
766	       */
767	    if (dpy->lock && dpy->lock->event_awaiters)
768		return dpy->qlen;
769	    /* nobody here but us, so lock out any newcomers */
770	    cvl = QueueEventReaderLock(dpy);
771	}
772
773	while (dpy->lock && cvl && dpy->lock->reply_first) {
774	    /* note which events we have already seen so we'll know
775	       if _XReply (in another thread) reads one */
776	    entry_event_serial_num = dpy->next_event_serial_num;
777	    ConditionWait(dpy, cvl->cv);
778	    /* did _XReply read an event we can return? */
779	    if (_XNewerQueuedEvent(dpy, entry_event_serial_num))
780	    {
781		UnlockNextEventReader(dpy);
782		return 0;
783	    }
784	}
785#endif /* XTHREADS*/
786
787	if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
788	    _XIOError(dpy);
789#ifdef XCONN_CHECK_FREQ
790	/* This is a crock, required because FIONREAD or equivalent is
791	 * not guaranteed to detect a broken connection.
792	 */
793	if (!pend && !dpy->qlen && ++dpy->conn_checker >= XCONN_CHECK_FREQ)
794	{
795	    int	result;
796#ifdef USE_POLL
797	    struct pollfd filedes;
798#else
799	    fd_set r_mask;
800	    static struct timeval zero_time;
801#endif
802
803	    dpy->conn_checker = 0;
804#ifdef USE_POLL
805	    filedes.fd = dpy->fd;
806	    filedes.events = POLLIN;
807	    if ((result = poll(&filedes, 1, 0)))
808#else
809	    FD_ZERO(&r_mask);
810	    FD_SET(dpy->fd, &r_mask);
811	    if ((result = Select(dpy->fd + 1, &r_mask, NULL, NULL, &zero_time)))
812#endif
813	    {
814		if (result > 0)
815		{
816		    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
817			_XIOError(dpy);
818		    /* we should not get zero, if we do, force a read */
819		    if (!pend)
820			pend = SIZEOF(xReply);
821		}
822		else if (result < 0 && !ECHECK(EINTR))
823		    _XIOError(dpy);
824	    }
825	}
826#endif /* XCONN_CHECK_FREQ */
827	if (!(len = pend)) {
828	    /* _XFlush can enqueue events */
829#ifdef XTHREADS
830	    if (cvl)
831#endif
832	    {
833		UnlockNextEventReader(dpy);
834	    }
835	    return(dpy->qlen);
836	}
837      /* Force a read if there is not enough data.  Otherwise,
838       * a select() loop at a higher-level will spin undesirably,
839       * and we've seen at least one OS that appears to not update
840       * the result from FIONREAD once it has returned nonzero.
841       */
842#ifdef XTHREADS
843	if (dpy->lock && dpy->lock->reply_awaiters) {
844	    read_buf = (char *)dpy->lock->reply_awaiters->buf;
845	    len = SIZEOF(xReply);
846	} else
847#endif /* XTHREADS*/
848	{
849	    read_buf = buf.buf;
850
851	    if (len < SIZEOF(xReply)
852#ifdef XTHREADS
853		|| dpy->async_handlers
854#endif
855		)
856		len = SIZEOF(xReply);
857	    else if (len > BUFSIZE)
858		len = BUFSIZE;
859	    len = (len / SIZEOF(xReply)) * SIZEOF(xReply);
860	}
861#ifdef XCONN_CHECK_FREQ
862	dpy->conn_checker = 0;
863#endif
864
865	(void) _XRead (dpy, read_buf, (long) len);
866
867#ifdef XTHREADS
868	/* what did we actually read: reply or event? */
869	if (dpy->lock && dpy->lock->reply_awaiters) {
870	    if (((xReply *)read_buf)->generic.type == X_Reply ||
871		((xReply *)read_buf)->generic.type == X_Error)
872	    {
873		dpy->lock->reply_was_read = True;
874		dpy->lock->reply_first = True;
875		if (read_buf != (char *)dpy->lock->reply_awaiters->buf)
876		    memcpy(dpy->lock->reply_awaiters->buf, read_buf,
877			   len);
878		if (cvl) {
879		    UnlockNextEventReader(dpy);
880		}
881		return(dpy->qlen); /* we read, so we can return */
882	    } else if (read_buf != buf.buf)
883		memcpy(buf.buf, read_buf, len);
884	}
885#endif /* XTHREADS*/
886
887	STARTITERATE(rep,xReply,buf.buf,len > 0) {
888	    if (rep->generic.type == X_Reply) {
889                int tmp = len;
890		RESETITERPTR(rep,xReply,
891			     _XAsyncReply (dpy, rep,
892					   ITERPTR(rep), &tmp, True));
893                len = tmp;
894		pend = len;
895	    } else {
896		if (rep->generic.type == X_Error)
897		    _XError (dpy, (xError *)rep);
898		else   /* must be an event packet */
899		    _XEnq (dpy, (xEvent *)rep);
900		INCITERPTR(rep,xReply);
901		len -= SIZEOF(xReply);
902	    }
903	} ENDITERATE
904
905#ifdef XTHREADS
906	if (cvl)
907#endif
908	{
909	    UnlockNextEventReader(dpy);
910	}
911	return(dpy->qlen);
912}
913
914/* _XReadEvents - Flush the output queue,
915 * then read as many events as possible (but at least 1) and enqueue them
916 */
917void _XReadEvents(
918	register Display *dpy)
919{
920	_XAlignedBuffer buf;
921	BytesReadable_t pend;
922	int len;
923	register xReply *rep;
924	Bool not_yet_flushed = True;
925	char *read_buf;
926	int i;
927	int entry_event_serial_num = dpy->next_event_serial_num;
928#ifdef XTHREADS
929	struct _XCVList *cvl = NULL;
930	xthread_t self;
931
932#ifdef XTHREADS_DEBUG
933	printf("_XReadEvents called in thread %x\n",
934	       XThread_Self());
935#endif
936	/* create our condition variable and append to list,
937	 * unless we were called from within XProcessInternalConnection
938	 * or XLockDisplay
939	 */
940	xthread_clear_id(self);
941	if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread)
942			  || xthread_have_id (dpy->lock->locking_thread)))
943	    /* some thread is in XProcessInternalConnection or XLockDisplay
944	       so we have to see if we are it */
945	    self = XThread_Self();
946	if (!xthread_have_id(self)
947	    || (!xthread_equal(self, dpy->lock->conni_thread)
948		&& !xthread_equal(self, dpy->lock->locking_thread)))
949	    cvl = QueueEventReaderLock(dpy);
950#endif /* XTHREADS */
951
952	do {
953#ifdef XTHREADS
954	    /* if it is not our turn to read an event off the wire,
955	       wait til we're at head of list */
956	    if (dpy->lock && cvl &&
957		(dpy->lock->event_awaiters != cvl ||
958		 dpy->lock->reply_first)) {
959		ConditionWait(dpy, cvl->cv);
960		continue;
961	    }
962#endif /* XTHREADS */
963	    /* find out how much data can be read */
964	    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
965	    	_XIOError(dpy);
966	    len = pend;
967
968	    /* must read at least one xEvent; if none is pending, then
969	       we'll just flush and block waiting for it */
970	    if (len < SIZEOF(xEvent)
971#ifdef XTHREADS
972		|| dpy->async_handlers
973#endif
974		) {
975	    	len = SIZEOF(xEvent);
976		/* don't flush until the first time we would block */
977		if (not_yet_flushed) {
978		    _XFlush (dpy);
979		    if (_XNewerQueuedEvent(dpy, entry_event_serial_num)) {
980			/* _XReply has read an event for us */
981			goto got_event;
982		    }
983		    not_yet_flushed = False;
984		}
985	    }
986
987#ifdef XTHREADS
988	    /* If someone is waiting for a reply, gamble that
989	       the reply will be the next thing on the wire
990	       and read it into their buffer. */
991	    if (dpy->lock && dpy->lock->reply_awaiters) {
992		read_buf = (char *)dpy->lock->reply_awaiters->buf;
993		len = SIZEOF(xReply);
994	    } else
995#endif /* XTHREADS*/
996	    {
997		read_buf = buf.buf;
998
999		/* but we won't read more than the max buffer size */
1000		if (len > BUFSIZE)
1001		    len = BUFSIZE;
1002
1003		/* round down to an integral number of XReps */
1004		len = (len / SIZEOF(xEvent)) * SIZEOF(xEvent);
1005	    }
1006
1007#ifdef XTHREADS
1008	    if (xthread_have_id(self))
1009		/* save value we may have to stick in conni_thread */
1010		dpy->lock->reading_thread = self;
1011#endif /* XTHREADS */
1012	    dpy->flags |= XlibDisplayReadEvents;
1013	    i = _XRead (dpy, read_buf, (long) len);
1014	    dpy->flags &= ~XlibDisplayReadEvents;
1015	    if (i == -2) {
1016		/* special flag from _XRead to say that internal connection has
1017		   done XPutBackEvent.  Which we can use so we're done. */
1018	      got_event:
1019#ifdef XTHREADS
1020		if (dpy->lock && dpy->lock->lock_wait) {
1021		    if (dpy->lock->event_awaiters != cvl)
1022			/* since it is not us, must be user lock thread */
1023			ConditionSignal(dpy,
1024					dpy->lock->event_awaiters->cv);
1025		    (*dpy->lock->lock_wait)(dpy);
1026		    continue;
1027		}
1028#endif
1029		break;
1030	    }
1031#ifdef XTHREADS
1032	    if (xthread_have_id(self))
1033		xthread_clear_id(dpy->lock->reading_thread);
1034
1035	    /* what did we actually read: reply or event? */
1036	    if (dpy->lock && dpy->lock->reply_awaiters) {
1037		if (((xReply *)read_buf)->generic.type == X_Reply ||
1038		    ((xReply *)read_buf)->generic.type == X_Error)
1039		{
1040		    dpy->lock->reply_was_read = True;
1041		    dpy->lock->reply_first = True;
1042		    if (read_buf != (char *)dpy->lock->reply_awaiters->buf)
1043			memcpy(dpy->lock->reply_awaiters->buf,
1044			       read_buf, len);
1045		    ConditionSignal(dpy, dpy->lock->reply_awaiters->cv);
1046		    continue;
1047		} else if (read_buf != buf.buf)
1048		    memcpy(buf.buf, read_buf, len);
1049	    }
1050#endif /* XTHREADS */
1051
1052	    STARTITERATE(rep,xReply,buf.buf,len > 0) {
1053		if (rep->generic.type == X_Reply) {
1054		    RESETITERPTR(rep,xReply,
1055				 _XAsyncReply (dpy, rep,
1056					       ITERPTR(rep), &len, True));
1057		    pend = len;
1058		} else {
1059		    if (rep->generic.type == X_Error)
1060			_XError (dpy, (xError *) rep);
1061		    else   /* must be an event packet */
1062			_XEnq (dpy, (xEvent *)rep);
1063		    INCITERPTR(rep,xReply);
1064		    len -= SIZEOF(xReply);
1065		}
1066	    } ENDITERATE;
1067	} while (!_XNewerQueuedEvent(dpy, entry_event_serial_num));
1068
1069	UnlockNextEventReader(dpy);
1070}
1071
1072/*
1073 * _XRead - Read bytes from the socket taking into account incomplete
1074 * reads.  This routine may have to be reworked if int < long.
1075 */
1076int _XRead(
1077	register Display *dpy,
1078	register char *data,
1079	register long size)
1080{
1081	register long bytes_read;
1082#ifdef XTHREADS
1083	int original_size = size;
1084#endif
1085
1086	if ((dpy->flags & XlibDisplayIOError) || size == 0)
1087	    return 0;
1088	ESET(0);
1089	while ((bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size))
1090		!= size) {
1091
1092	    	if (bytes_read > 0) {
1093		    size -= bytes_read;
1094		    data += bytes_read;
1095		    }
1096		else if (ETEST()) {
1097		    if (_XWaitForReadable(dpy) == -2)
1098			return -2; /* internal connection did XPutBackEvent */
1099		    ESET(0);
1100		}
1101#ifdef SUNSYSV
1102		else if (ECHECK(0)) {
1103		    if (_XWaitForReadable(dpy) == -2)
1104			return -2; /* internal connection did XPutBackEvent */
1105		}
1106#endif
1107		else if (bytes_read == 0) {
1108		    /* Read failed because of end of file! */
1109		    ESET(EPIPE);
1110		    _XIOError(dpy);
1111		    }
1112
1113		else  /* bytes_read is less than 0; presumably -1 */ {
1114		    /* If it's a system call interrupt, it's not an error. */
1115		    if (!ECHECK(EINTR))
1116		    	_XIOError(dpy);
1117		    }
1118	    	 }
1119#ifdef XTHREADS
1120       if (dpy->lock && dpy->lock->reply_bytes_left > 0)
1121       {
1122           dpy->lock->reply_bytes_left -= original_size;
1123           if (dpy->lock->reply_bytes_left == 0) {
1124	       dpy->flags &= ~XlibDisplayReply;
1125               UnlockNextReplyReader(dpy);
1126	   }
1127       }
1128#endif /* XTHREADS*/
1129	return 0;
1130}
1131#endif /* !USE_XCB */
1132
1133#ifdef LONG64
1134void _XRead32(
1135    Display *dpy,
1136    register long *data,
1137    long len)
1138{
1139    register int *buf;
1140    register long i;
1141
1142    if (len) {
1143	(void) _XRead(dpy, (char *)data, len);
1144	i = len >> 2;
1145	buf = (int *)data + i;
1146	data += i;
1147	while (--i >= 0)
1148	    *--data = *--buf;
1149    }
1150}
1151#endif /* LONG64 */
1152
1153#ifdef WORD64
1154
1155/*
1156 * XXX This is a *really* stupid way of doing this....
1157 * PACKBUFFERSIZE must be a multiple of 4.
1158 */
1159
1160#define PACKBUFFERSIZE 4096
1161
1162
1163/*
1164 * _XRead32 - Read bytes from the socket unpacking each 32 bits
1165 *            into a long (64 bits on a CRAY computer).
1166 *
1167 */
1168static void _doXRead32(
1169        register Display *dpy,
1170        register long *data
1171        register long size,
1172	register char *packbuffer)
1173{
1174 long *lpack,*lp;
1175 long mask32 = 0x00000000ffffffff;
1176 long maskw, nwords, i, bits;
1177
1178        _XReadPad (dpy, packbuffer, size);
1179
1180        lp = data;
1181        lpack = (long *) packbuffer;
1182        nwords = size >> 2;
1183        bits = 32;
1184
1185        for(i=0;i<nwords;i++){
1186            maskw = mask32 << bits;
1187           *lp++ = ( *lpack & maskw ) >> bits;
1188            bits = bits ^32;
1189            if(bits){
1190               lpack++;
1191            }
1192        }
1193}
1194
1195void _XRead32(
1196    Display *dpy,
1197    long *data,
1198    long len)
1199{
1200    char packbuffer[PACKBUFFERSIZE];
1201    unsigned nunits = PACKBUFFERSIZE >> 2;
1202
1203    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
1204	_doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer);
1205    }
1206    if (len) _doXRead32 (dpy, data, len, packbuffer);
1207}
1208
1209
1210
1211/*
1212 * _XRead16 - Read bytes from the socket unpacking each 16 bits
1213 *            into a long (64 bits on a CRAY computer).
1214 *
1215 */
1216static _doXRead16(
1217        register Display *dpy,
1218        register short *data,
1219        register long size,
1220	char *packbuffer)
1221{
1222	long *lpack,*lp;
1223	long mask16 = 0x000000000000ffff;
1224	long maskw, nwords, i, bits;
1225
1226        (void) _XRead(dpy,packbuffer,size);	/* don't do a padded read... */
1227
1228        lp = (long *) data;
1229        lpack = (long *) packbuffer;
1230        nwords = size >> 1;  /* number of 16 bit words to be unpacked */
1231        bits = 48;
1232        for(i=0;i<nwords;i++){
1233            maskw = mask16 << bits;
1234           *lp++ = ( *lpack & maskw ) >> bits;
1235            bits -= 16;
1236            if(bits < 0){
1237               lpack++;
1238               bits = 48;
1239            }
1240        }
1241}
1242
1243void _XRead16(
1244    Display *dpy,
1245    short *data,
1246    long len)
1247{
1248    char packbuffer[PACKBUFFERSIZE];
1249    unsigned nunits = PACKBUFFERSIZE >> 1;
1250
1251    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
1252	_doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer);
1253    }
1254    if (len) _doXRead16 (dpy, data, len, packbuffer);
1255}
1256
1257void _XRead16Pad(
1258    Display *dpy,
1259    short *data,
1260    long size)
1261{
1262    int slop = (size & 3);
1263    short slopbuf[3];
1264
1265    _XRead16 (dpy, data, size);
1266    if (slop > 0) {
1267	_XRead16 (dpy, slopbuf, 4 - slop);
1268    }
1269}
1270#endif /* WORD64 */
1271
1272
1273#if !USE_XCB
1274/*
1275 * _XReadPad - Read bytes from the socket taking into account incomplete
1276 * reads.  If the number of bytes is not 0 mod 4, read additional pad
1277 * bytes. This routine may have to be reworked if int < long.
1278 */
1279void _XReadPad(
1280    	register Display *dpy,
1281	register char *data,
1282	register long size)
1283{
1284    	register long bytes_read;
1285	struct iovec iov[2];
1286	char pad[3];
1287#ifdef XTHREADS
1288        int original_size;
1289#endif
1290
1291	if ((dpy->flags & XlibDisplayIOError) || size == 0) return;
1292	iov[0].iov_len = (int)size;
1293	iov[0].iov_base = data;
1294	/*
1295	 * The following hack is used to provide 32 bit long-word
1296	 * aligned padding.  The [1] vector is of length 0, 1, 2, or 3,
1297	 * whatever is needed.
1298	 */
1299
1300	iov[1].iov_len = -size & 3;
1301	iov[1].iov_base = pad;
1302	size += iov[1].iov_len;
1303#ifdef XTHREADS
1304	original_size = size;
1305#endif
1306	ESET(0);
1307	while ((bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2)) != size) {
1308
1309	    if (bytes_read > 0) {
1310		size -= bytes_read;
1311		if (iov[0].iov_len < bytes_read) {
1312		    int pad_bytes_read = bytes_read - iov[0].iov_len;
1313		    iov[1].iov_len -= pad_bytes_read;
1314		    iov[1].iov_base =
1315			(char *)iov[1].iov_base + pad_bytes_read;
1316		    iov[0].iov_len = 0;
1317		    }
1318	    	else {
1319		    iov[0].iov_len -= bytes_read;
1320	    	    iov[0].iov_base = (char *)iov[0].iov_base + bytes_read;
1321	    	}
1322	    }
1323	    else if (ETEST()) {
1324		_XWaitForReadable(dpy);
1325		ESET(0);
1326	    }
1327#ifdef SUNSYSV
1328	    else if (ECHECK(0)) {
1329		_XWaitForReadable(dpy);
1330	    }
1331#endif
1332	    else if (bytes_read == 0) {
1333		/* Read failed because of end of file! */
1334		ESET(EPIPE);
1335		_XIOError(dpy);
1336		}
1337
1338	    else  /* bytes_read is less than 0; presumably -1 */ {
1339		/* If it's a system call interrupt, it's not an error. */
1340		if (!ECHECK(EINTR))
1341		    _XIOError(dpy);
1342		}
1343	    }
1344#ifdef XTHREADS
1345       if (dpy->lock && dpy->lock->reply_bytes_left > 0)
1346       {
1347           dpy->lock->reply_bytes_left -= original_size;
1348           if (dpy->lock->reply_bytes_left == 0) {
1349	       dpy->flags &= ~XlibDisplayReply;
1350               UnlockNextReplyReader(dpy);
1351	   }
1352       }
1353#endif /* XTHREADS*/
1354}
1355
1356/*
1357 * _XSend - Flush the buffer and send the client data. 32 bit word aligned
1358 * transmission is used, if size is not 0 mod 4, extra bytes are transmitted.
1359 * This routine may have to be reworked if int < long;
1360 */
1361void
1362_XSend (
1363	register Display *dpy,
1364	_Xconst char *data,
1365	register long size)
1366{
1367	struct iovec iov[3];
1368	static char const pad[3] = {0, 0, 0};
1369           /* XText8 and XText16 require that the padding bytes be zero! */
1370
1371	long skip, dbufsize, padsize, total, todo;
1372	_XExtension *ext;
1373
1374	if (!size || (dpy->flags & XlibDisplayIOError)) return;
1375	dbufsize = dpy->bufptr - dpy->buffer;
1376#ifdef XTHREADS
1377	dpy->flags |= XlibDisplayWriting;
1378	/* make sure no one else can put in data */
1379	dpy->bufptr = dpy->bufmax;
1380#endif
1381	padsize = -size & 3;
1382	for (ext = dpy->flushes; ext; ext = ext->next_flush) {
1383	    (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, dbufsize);
1384	    (*ext->before_flush)(dpy, &ext->codes, (char *)data, size);
1385	    if (padsize)
1386		(*ext->before_flush)(dpy, &ext->codes, pad, padsize);
1387	}
1388	skip = 0;
1389	todo = total = dbufsize + size + padsize;
1390
1391	/*
1392	 * There are 3 pieces that may need to be written out:
1393	 *
1394	 *     o  whatever is in the display buffer
1395	 *     o  the data passed in by the user
1396	 *     o  any padding needed to 32bit align the whole mess
1397	 *
1398	 * This loop looks at all 3 pieces each time through.  It uses skip
1399	 * to figure out whether or not a given piece is needed.
1400	 */
1401	while (total) {
1402	    long before = skip;		/* amount of whole thing written */
1403	    long remain = todo;		/* amount to try this time, <= total */
1404	    int i = 0;
1405	    long len;
1406
1407	    /* You could be very general here and have "in" and "out" iovecs
1408	     * and write a loop without using a macro, but what the heck.  This
1409	     * translates to:
1410	     *
1411	     *     how much of this piece is new?
1412	     *     if more new then we are trying this time, clamp
1413	     *     if nothing new
1414	     *         then bump down amount already written, for next piece
1415	     *         else put new stuff in iovec, will need all of next piece
1416	     *
1417	     * Note that todo had better be at least 1 or else we'll end up
1418	     * writing 0 iovecs.
1419	     */
1420#define InsertIOV(pointer, length) \
1421	    len = (length) - before; \
1422	    if (len > remain) \
1423		len = remain; \
1424	    if (len <= 0) { \
1425		before = (-len); \
1426	    } else { \
1427		iov[i].iov_len = len; \
1428		iov[i].iov_base = (pointer) + before; \
1429		i++; \
1430		remain -= len; \
1431		before = 0; \
1432	    }
1433
1434	    InsertIOV (dpy->buffer, dbufsize)
1435	    InsertIOV ((char *)data, size)
1436	    InsertIOV ((char *)pad, padsize)
1437
1438	    ESET(0);
1439	    if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) {
1440		skip += len;
1441		total -= len;
1442		todo = total;
1443	    } else if (ETEST()) {
1444		_XWaitForWritable(dpy
1445#ifdef XTHREADS
1446				  , NULL
1447#endif
1448				  );
1449#ifdef SUNSYSV
1450	    } else if (ECHECK(0)) {
1451		_XWaitForWritable(dpy
1452#ifdef XTHREADS
1453				  , NULL
1454#endif
1455				  );
1456#endif
1457#ifdef ESZTEST
1458	    } else if (ESZTEST()) {
1459		if (todo > 1)
1460		  todo >>= 1;
1461		else {
1462		    _XWaitForWritable(dpy
1463#ifdef XTHREADS
1464				      , NULL
1465#endif
1466				      );
1467		}
1468#endif
1469	    } else if (!ECHECK(EINTR)) {
1470		_XIOError(dpy);
1471	    }
1472	}
1473	dpy->last_req = (char *) & _dummy_request;
1474	_XSetSeqSyncFunction(dpy);
1475	dpy->bufptr = dpy->buffer;
1476#ifdef XTHREADS
1477	dpy->flags &= ~XlibDisplayWriting;
1478#endif
1479	return;
1480}
1481
1482static void
1483_XGetMiscCode(
1484    register Display *dpy)
1485{
1486    xQueryExtensionReply qrep;
1487    register xQueryExtensionReq *qreq;
1488    xXCMiscGetVersionReply vrep;
1489    register xXCMiscGetVersionReq *vreq;
1490
1491    if (dpy->xcmisc_opcode)
1492	return;
1493    GetReq(QueryExtension, qreq);
1494    qreq->nbytes = sizeof(XCMiscExtensionName) - 1;
1495    qreq->length += (qreq->nbytes+(unsigned)3)>>2;
1496    _XSend(dpy, XCMiscExtensionName, (long)qreq->nbytes);
1497    if (!_XReply (dpy, (xReply *)&qrep, 0, xTrue))
1498	dpy->xcmisc_opcode = -1;
1499    else {
1500	GetReq(XCMiscGetVersion, vreq);
1501	vreq->reqType = qrep.major_opcode;
1502	vreq->miscReqType = X_XCMiscGetVersion;
1503	vreq->majorVersion = XCMiscMajorVersion;
1504	vreq->minorVersion = XCMiscMinorVersion;
1505	if (!_XReply (dpy, (xReply *)&vrep, 0, xTrue))
1506	    dpy->xcmisc_opcode = -1;
1507	else
1508	    dpy->xcmisc_opcode = qrep.major_opcode;
1509    }
1510}
1511
1512static int
1513_XIDHandler(
1514    register Display *dpy)
1515{
1516    xXCMiscGetXIDRangeReply grep;
1517    register xXCMiscGetXIDRangeReq *greq;
1518
1519    LockDisplay(dpy);
1520    _XGetMiscCode(dpy);
1521    if (dpy->xcmisc_opcode > 0) {
1522	GetReq(XCMiscGetXIDRange, greq);
1523	greq->reqType = dpy->xcmisc_opcode;
1524	greq->miscReqType = X_XCMiscGetXIDRange;
1525	if (_XReply (dpy, (xReply *)&grep, 0, xTrue) && grep.count) {
1526	    dpy->resource_id = ((grep.start_id - dpy->resource_base) >>
1527				dpy->resource_shift);
1528	    dpy->resource_max = dpy->resource_id;
1529	    if (grep.count > 5)
1530		dpy->resource_max += grep.count - 6;
1531	    dpy->resource_max <<= dpy->resource_shift;
1532	}
1533    }
1534    if (dpy->flags & XlibDisplayPrivSync) {
1535	dpy->synchandler = dpy->savedsynchandler;
1536	dpy->flags &= ~XlibDisplayPrivSync;
1537    }
1538    UnlockDisplay(dpy);
1539    SyncHandle();
1540    return 0;
1541}
1542
1543/*
1544 * _XAllocID - resource ID allocation routine.
1545 */
1546XID _XAllocID(
1547    register Display *dpy)
1548{
1549   XID id;
1550
1551   id = dpy->resource_id << dpy->resource_shift;
1552   if (id >= dpy->resource_max) {
1553       if (!(dpy->flags & XlibDisplayPrivSync)) {
1554	   dpy->savedsynchandler = dpy->synchandler;
1555	   dpy->flags |= XlibDisplayPrivSync;
1556       }
1557       dpy->synchandler = _XIDHandler;
1558       dpy->resource_max = dpy->resource_mask + 1;
1559   }
1560   if (id <= dpy->resource_mask) {
1561       dpy->resource_id++;
1562       return (dpy->resource_base + id);
1563   }
1564   if (id != 0x10000000) {
1565       (void) fprintf(stderr,
1566		      "Xlib: resource ID allocation space exhausted!\n");
1567       id = 0x10000000;
1568       dpy->resource_id = id >> dpy->resource_shift;
1569   }
1570   return id;
1571}
1572
1573/*
1574 * _XAllocIDs - multiple resource ID allocation routine.
1575 */
1576void _XAllocIDs(
1577    register Display *dpy,
1578    XID *ids,
1579    int count)
1580{
1581    XID id;
1582    int i;
1583    xXCMiscGetXIDListReply grep;
1584    register xXCMiscGetXIDListReq *greq;
1585
1586    id = dpy->resource_id << dpy->resource_shift;
1587    if (dpy->resource_max <= dpy->resource_mask &&
1588	id <= dpy->resource_mask &&
1589	(dpy->resource_max - id) > ((count - 1) << dpy->resource_shift)) {
1590	id += dpy->resource_base;
1591	for (i = 0; i < count; i++) {
1592	    ids[i] = id;
1593	    id += (1 << dpy->resource_shift);
1594	    dpy->resource_id++;
1595	}
1596	return;
1597    }
1598    grep.count = 0;
1599    _XGetMiscCode(dpy);
1600    if (dpy->xcmisc_opcode > 0) {
1601	GetReq(XCMiscGetXIDList, greq);
1602	greq->reqType = dpy->xcmisc_opcode;
1603	greq->miscReqType = X_XCMiscGetXIDList;
1604	greq->count = count;
1605	if (_XReply(dpy, (xReply *)&grep, 0, xFalse) && grep.count) {
1606	    _XRead32(dpy, (long *) ids, 4L * (long) (grep.count));
1607	    for (i = 0; i < grep.count; i++) {
1608		id = (ids[i] - dpy->resource_base) >> dpy->resource_shift;
1609		if (id >= dpy->resource_id)
1610		    dpy->resource_id = id;
1611	    }
1612	    if (id >= dpy->resource_max) {
1613		if (!(dpy->flags & XlibDisplayPrivSync)) {
1614		    dpy->savedsynchandler = dpy->synchandler;
1615		    dpy->flags |= XlibDisplayPrivSync;
1616		}
1617		dpy->synchandler = _XIDHandler;
1618		dpy->resource_max = dpy->resource_mask + 1;
1619	    }
1620	}
1621    }
1622    for (i = grep.count; i < count; i++)
1623	ids[i] = XAllocID(dpy);
1624}
1625#endif /* !USE_XCB */
1626
1627/*
1628 * The hard part about this is that we only get 16 bits from a reply.
1629 * We have three values that will march along, with the following invariant:
1630 *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
1631 * We have to keep
1632 *	dpy->request - dpy->last_request_read < 2^16
1633 * or else we won't know for sure what value to use in events.  We do this
1634 * by forcing syncs when we get close.
1635 */
1636
1637unsigned long
1638_XSetLastRequestRead(
1639    register Display *dpy,
1640    register xGenericReply *rep)
1641{
1642    register unsigned long	newseq, lastseq;
1643
1644    lastseq = dpy->last_request_read;
1645    /*
1646     * KeymapNotify has no sequence number, but is always guaranteed
1647     * to immediately follow another event, except when generated via
1648     * SendEvent (hmmm).
1649     */
1650    if ((rep->type & 0x7f) == KeymapNotify)
1651	return(lastseq);
1652
1653    newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber;
1654
1655    if (newseq < lastseq) {
1656	newseq += 0x10000;
1657	if (newseq > dpy->request) {
1658	    (void) fprintf (stderr,
1659	    "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
1660			    newseq, dpy->request,
1661			    (unsigned int) rep->type);
1662	    newseq -= 0x10000;
1663	}
1664    }
1665
1666    dpy->last_request_read = newseq;
1667    return(newseq);
1668}
1669
1670#if !USE_XCB
1671/*
1672 * _XReply - Wait for a reply packet and copy its contents into the
1673 * specified rep.  Meanwhile we must handle error and event packets that
1674 * we may encounter.
1675 */
1676Status
1677_XReply (
1678    register Display *dpy,
1679    register xReply *rep,
1680    int extra,		/* number of 32-bit words expected after the reply */
1681    Bool discard)	/* should I discard data following "extra" words? */
1682{
1683    /* Pull out the serial number now, so that (currently illegal) requests
1684     * generated by an error handler don't confuse us.
1685     */
1686    unsigned long cur_request = dpy->request;
1687#ifdef XTHREADS
1688    struct _XCVList *cvl;
1689#endif
1690
1691    if (dpy->flags & XlibDisplayIOError)
1692	return 0;
1693
1694#ifdef XTHREADS
1695    /* create our condition variable and append to list */
1696    cvl = QueueReplyReaderLock(dpy);
1697    if (cvl) {
1698	cvl->buf = rep;
1699	if (dpy->lock->reply_awaiters == cvl && !dpy->lock->event_awaiters)
1700	    dpy->lock->reply_first = True;
1701    }
1702
1703#ifdef XTHREADS_DEBUG
1704    printf("_XReply called in thread %x, adding %x to cvl\n",
1705	   XThread_Self(), cvl);
1706#endif
1707
1708    _XFlushInt(dpy, cvl ? cvl->cv : NULL);
1709    /* if it is not our turn to read a reply off the wire,
1710     * wait til we're at head of list.  if there is an event waiter,
1711     * and our reply hasn't been read, they'll be in select and will
1712     * hand control back to us next.
1713     */
1714    if(dpy->lock &&
1715       (dpy->lock->reply_awaiters != cvl || !dpy->lock->reply_first)) {
1716	ConditionWait(dpy, cvl->cv);
1717    }
1718    dpy->flags |= XlibDisplayReply;
1719#else /* XTHREADS else */
1720    _XFlush(dpy);
1721#endif
1722
1723    for (;;) {
1724#ifdef XTHREADS
1725	/* Did another thread's _XReadEvents get our reply by accident? */
1726	if (!dpy->lock || !dpy->lock->reply_was_read)
1727#endif
1728	    (void) _XRead(dpy, (char *)rep, (long)SIZEOF(xReply));
1729#ifdef XTHREADS
1730	if (dpy->lock)
1731	    dpy->lock->reply_was_read = False;
1732#endif
1733
1734	switch ((int)rep->generic.type) {
1735
1736	    case X_Reply:
1737	        /* Reply received.  Fast update for synchronous replies,
1738		 * but deal with multiple outstanding replies.
1739		 */
1740	        if (rep->generic.sequenceNumber == (cur_request & 0xffff))
1741		    dpy->last_request_read = cur_request;
1742		else {
1743		    int pend = SIZEOF(xReply);
1744		    if (_XAsyncReply(dpy, rep, (char *)rep, &pend, False)
1745			!= (char *)rep)
1746			continue;
1747		}
1748		if (extra <= rep->generic.length) {
1749		    if (extra > 0)
1750			/*
1751			 * Read the extra data into storage immediately
1752			 * following the GenericReply structure.
1753			 */
1754			(void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)),
1755				((long)extra) << 2);
1756		    if (discard) {
1757			if (extra < rep->generic.length)
1758			    _XEatData(dpy, (rep->generic.length - extra) << 2);
1759		    }
1760#ifdef XTHREADS
1761		    if (dpy->lock) {
1762			if (discard) {
1763			    dpy->lock->reply_bytes_left = 0;
1764			} else {
1765			    dpy->lock->reply_bytes_left =
1766				(rep->generic.length - extra) << 2;
1767			}
1768			if (dpy->lock->reply_bytes_left == 0) {
1769			    dpy->flags &= ~XlibDisplayReply;
1770			    UnlockNextReplyReader(dpy);
1771			}
1772		    } else
1773			dpy->flags &= ~XlibDisplayReply;
1774#endif
1775		    return 1;
1776		}
1777		/*
1778		 *if we get here, then extra > rep->generic.length--meaning we
1779		 * read a reply that's shorter than we expected.  This is an
1780		 * error,  but we still need to figure out how to handle it...
1781		 */
1782		(void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)),
1783			((long) rep->generic.length) << 2);
1784		dpy->flags &= ~XlibDisplayReply;
1785		UnlockNextReplyReader(dpy);
1786		_XIOError (dpy);
1787		return (0);
1788
1789    	    case X_Error:
1790	    	{
1791	        register _XExtension *ext;
1792		register Bool ret = False;
1793		int ret_code;
1794		xError *err = (xError *) rep;
1795		unsigned long serial;
1796
1797		dpy->flags &= ~XlibDisplayReply;
1798		serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
1799		if (serial == cur_request)
1800			/* do not die on "no such font", "can't allocate",
1801			   "can't grab" failures */
1802			switch ((int)err->errorCode) {
1803			case BadName:
1804			    switch (err->majorCode) {
1805				case X_LookupColor:
1806				case X_AllocNamedColor:
1807				    UnlockNextReplyReader(dpy);
1808				    return(0);
1809			    }
1810			    break;
1811			case BadFont:
1812			    if (err->majorCode == X_QueryFont) {
1813				UnlockNextReplyReader(dpy);
1814				return (0);
1815			    }
1816			    break;
1817			case BadAlloc:
1818			case BadAccess:
1819			    UnlockNextReplyReader(dpy);
1820			    return (0);
1821			}
1822		/*
1823		 * we better see if there is an extension who may
1824		 * want to suppress the error.
1825		 */
1826		for (ext = dpy->ext_procs; !ret && ext; ext = ext->next) {
1827		    if (ext->error)
1828		       ret = (*ext->error)(dpy, err, &ext->codes, &ret_code);
1829		}
1830		if (!ret) {
1831		    _XError(dpy, err);
1832		    ret_code = 0;
1833		}
1834		if (serial == cur_request) {
1835		    UnlockNextReplyReader(dpy);
1836		    return(ret_code);
1837		}
1838
1839		} /* case X_Error */
1840		break;
1841	    default:
1842		_XEnq(dpy, (xEvent *) rep);
1843#ifdef XTHREADS
1844		if (dpy->lock && dpy->lock->event_awaiters)
1845		    ConditionSignal(dpy, dpy->lock->event_awaiters->cv);
1846#endif
1847		break;
1848	    }
1849	}
1850}
1851
1852static char *
1853_XAsyncReply(
1854    Display *dpy,
1855    register xReply *rep,
1856    char *buf,
1857    register int *lenp,
1858    Bool discard)
1859{
1860    register _XAsyncHandler *async, *next;
1861    register int len;
1862    register Bool consumed = False;
1863    char *nbuf;
1864
1865    (void) _XSetLastRequestRead(dpy, &rep->generic);
1866    len = SIZEOF(xReply) + (rep->generic.length << 2);
1867    if (len < SIZEOF(xReply)) {
1868	_XIOError (dpy);
1869	buf += *lenp;
1870	*lenp = 0;
1871	return buf;
1872    }
1873
1874    for (async = dpy->async_handlers; async; async = next) {
1875	next = async->next;
1876	if ((consumed = (*async->handler)(dpy, rep, buf, *lenp, async->data)))
1877	    break;
1878    }
1879    if (!consumed) {
1880	if (!discard)
1881	    return buf;
1882	(void) fprintf(stderr,
1883		       "Xlib: unexpected async reply (sequence 0x%lx)!\n",
1884		       dpy->last_request_read);
1885#ifdef XTHREADS
1886#ifdef XTHREADS_DEBUG
1887	printf("thread %x, unexpected async reply\n", XThread_Self());
1888#endif
1889#endif
1890	if (len > *lenp)
1891	    _XEatData(dpy, len - *lenp);
1892    }
1893    if (len < SIZEOF(xReply))
1894    {
1895	_XIOError (dpy);
1896	buf += *lenp;
1897	*lenp = 0;
1898	return buf;
1899    }
1900    if (len >= *lenp) {
1901	buf += *lenp;
1902	*lenp = 0;
1903	return buf;
1904    }
1905    *lenp -= len;
1906    buf += len;
1907    len = *lenp;
1908    nbuf = buf;
1909    while (len > SIZEOF(xReply)) {
1910	if (*buf == X_Reply)
1911	    return nbuf;
1912	buf += SIZEOF(xReply);
1913	len -= SIZEOF(xReply);
1914    }
1915    if (len > 0 && len < SIZEOF(xReply)) {
1916	buf = nbuf;
1917	len = SIZEOF(xReply) - len;
1918	nbuf -= len;
1919	memmove(nbuf, buf, *lenp);
1920	(void) _XRead(dpy, nbuf + *lenp, (long)len);
1921	*lenp += len;
1922    }
1923    return nbuf;
1924}
1925#endif /* !USE_XCB */
1926
1927/*
1928 * Support for internal connections, such as an IM might use.
1929 * By Stephen Gildea, X Consortium, September 1993
1930 */
1931
1932/* _XRegisterInternalConnection
1933 * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
1934 * include in its select/poll mask must call this function to register the
1935 * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
1936 * will also be called.
1937 *
1938 * Whenever Xlib detects input available on fd, it will call callback
1939 * with call_data to process it.  If non-Xlib code calls select/poll
1940 * and detects input available, it must call XProcessInternalConnection,
1941 * which will call the associated callback.
1942 *
1943 * Non-Xlib code can learn about these additional fds by calling
1944 * XInternalConnectionNumbers or, more typically, by registering
1945 * a XConnectionWatchProc with XAddConnectionWatch
1946 * to be called when fds are registered or unregistered.
1947 *
1948 * Returns True if registration succeeded, False if not, typically
1949 * because could not allocate memory.
1950 * Assumes Display locked when called.
1951 */
1952Status
1953_XRegisterInternalConnection(
1954    Display* dpy,
1955    int fd,
1956    _XInternalConnectionProc callback,
1957    XPointer call_data
1958)
1959{
1960    struct _XConnectionInfo *new_conni, **iptr;
1961    struct _XConnWatchInfo *watchers;
1962    XPointer *wd;
1963
1964    new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
1965    if (!new_conni)
1966	return 0;
1967    new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer));
1968    if (!new_conni->watch_data) {
1969	Xfree(new_conni);
1970	return 0;
1971    }
1972    new_conni->fd = fd;
1973    new_conni->read_callback = callback;
1974    new_conni->call_data = call_data;
1975    new_conni->next = NULL;
1976    /* link new structure onto end of list */
1977    for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
1978	;
1979    *iptr = new_conni;
1980    dpy->im_fd_length++;
1981    _XPollfdCacheAdd(dpy, fd);
1982
1983    for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
1984	 watchers;
1985	 watchers=watchers->next, wd++) {
1986	*wd = NULL;		/* for cleanliness */
1987	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
1988    }
1989
1990    return 1;
1991}
1992
1993/* _XUnregisterInternalConnection
1994 * Each IM (or Xlib extension) that closes a file descriptor previously
1995 * registered with _XRegisterInternalConnection must call this function.
1996 * Any XConnectionWatchProc registered by XAddConnectionWatch
1997 * will also be called.
1998 *
1999 * Assumes Display locked when called.
2000 */
2001void
2002_XUnregisterInternalConnection(
2003    Display* dpy,
2004    int fd
2005)
2006{
2007    struct _XConnectionInfo *info_list, **prev;
2008    struct _XConnWatchInfo *watch;
2009    XPointer *wd;
2010
2011    for (prev = &dpy->im_fd_info; (info_list = *prev);
2012	 prev = &info_list->next) {
2013	if (info_list->fd == fd) {
2014	    *prev = info_list->next;
2015	    dpy->im_fd_length--;
2016	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
2017		 watch;
2018		 watch=watch->next, wd++) {
2019		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
2020	    }
2021	    if (info_list->watch_data)
2022		Xfree (info_list->watch_data);
2023	    Xfree (info_list);
2024	    break;
2025	}
2026    }
2027    _XPollfdCacheDel(dpy, fd);
2028}
2029
2030/* XInternalConnectionNumbers
2031 * Returns an array of fds and an array of corresponding call data.
2032 * Typically a XConnectionWatchProc registered with XAddConnectionWatch
2033 * will be used instead of this function to discover
2034 * additional fds to include in the select/poll mask.
2035 *
2036 * The list is allocated with Xmalloc and should be freed by the caller
2037 * with Xfree;
2038 */
2039Status
2040XInternalConnectionNumbers(
2041    Display *dpy,
2042    int **fd_return,
2043    int *count_return
2044)
2045{
2046    int count;
2047    struct _XConnectionInfo *info_list;
2048    int *fd_list;
2049
2050    LockDisplay(dpy);
2051    count = 0;
2052    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
2053	count++;
2054    fd_list = (int*) Xmalloc (count * sizeof(int));
2055    if (!fd_list) {
2056	UnlockDisplay(dpy);
2057	return 0;
2058    }
2059    count = 0;
2060    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
2061	fd_list[count] = info_list->fd;
2062	count++;
2063    }
2064    UnlockDisplay(dpy);
2065
2066    *fd_return = fd_list;
2067    *count_return = count;
2068    return 1;
2069}
2070
2071void _XProcessInternalConnection(
2072    Display *dpy,
2073    struct _XConnectionInfo *conn_info)
2074{
2075    dpy->flags |= XlibDisplayProcConni;
2076#if defined(XTHREADS) && !USE_XCB
2077    if (dpy->lock) {
2078	/* check cache to avoid call to thread_self */
2079	if (xthread_have_id(dpy->lock->reading_thread))
2080	    dpy->lock->conni_thread = dpy->lock->reading_thread;
2081	else
2082	    dpy->lock->conni_thread = XThread_Self();
2083    }
2084#endif /* XTHREADS && !USE_XCB */
2085    UnlockDisplay(dpy);
2086    (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
2087    LockDisplay(dpy);
2088#if defined(XTHREADS) && !USE_XCB
2089    if (dpy->lock)
2090	xthread_clear_id(dpy->lock->conni_thread);
2091#endif /* XTHREADS && !USE_XCB */
2092    dpy->flags &= ~XlibDisplayProcConni;
2093}
2094
2095/* XProcessInternalConnection
2096 * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
2097 * for this fd.
2098 * The Display is NOT locked during the call.
2099 */
2100void
2101XProcessInternalConnection(
2102    Display* dpy,
2103    int fd
2104)
2105{
2106    struct _XConnectionInfo *info_list;
2107
2108    LockDisplay(dpy);
2109    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
2110	if (info_list->fd == fd) {
2111	    _XProcessInternalConnection(dpy, info_list);
2112	    break;
2113	}
2114    }
2115    UnlockDisplay(dpy);
2116}
2117
2118/* XAddConnectionWatch
2119 * Register a callback to be called whenever _XRegisterInternalConnection
2120 * or _XUnregisterInternalConnection is called.
2121 * Callbacks are called with the Display locked.
2122 * If any connections are already registered, the callback is immediately
2123 * called for each of them.
2124 */
2125Status
2126XAddConnectionWatch(
2127    Display* dpy,
2128    XConnectionWatchProc callback,
2129    XPointer client_data
2130)
2131{
2132    struct _XConnWatchInfo *new_watcher, **wptr;
2133    struct _XConnectionInfo *info_list;
2134    XPointer *wd_array;
2135
2136    LockDisplay(dpy);
2137
2138    /* allocate new watch data */
2139    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
2140	wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data,
2141					(dpy->watcher_count + 1) *
2142					sizeof(XPointer));
2143	if (!wd_array) {
2144	    UnlockDisplay(dpy);
2145	    return 0;
2146	}
2147	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
2148    }
2149
2150    new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo));
2151    if (!new_watcher) {
2152	UnlockDisplay(dpy);
2153	return 0;
2154    }
2155    new_watcher->fn = callback;
2156    new_watcher->client_data = client_data;
2157    new_watcher->next = NULL;
2158
2159    /* link new structure onto end of list */
2160    for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
2161	;
2162    *wptr = new_watcher;
2163    dpy->watcher_count++;
2164
2165    /* call new watcher on all currently registered fds */
2166    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
2167	(*callback) (dpy, client_data, info_list->fd, True,
2168		     info_list->watch_data + dpy->watcher_count - 1);
2169    }
2170
2171    UnlockDisplay(dpy);
2172    return 1;
2173}
2174
2175/* XRemoveConnectionWatch
2176 * Unregister a callback registered by XAddConnectionWatch.
2177 * Both callback and client_data must match what was passed to
2178 * XAddConnectionWatch.
2179 */
2180void
2181XRemoveConnectionWatch(
2182    Display* dpy,
2183    XConnectionWatchProc callback,
2184    XPointer client_data
2185)
2186{
2187    struct _XConnWatchInfo *watch;
2188    struct _XConnWatchInfo *previous = NULL;
2189    struct _XConnectionInfo *conni;
2190    int counter = 0;
2191
2192    LockDisplay(dpy);
2193    for (watch=dpy->conn_watchers; watch; watch=watch->next) {
2194	if (watch->fn == callback  &&  watch->client_data == client_data) {
2195	    if (previous)
2196		previous->next = watch->next;
2197	    else
2198		dpy->conn_watchers = watch->next;
2199	    Xfree (watch);
2200	    dpy->watcher_count--;
2201	    /* remove our watch_data for each connection */
2202	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
2203		/* don't bother realloc'ing; these arrays are small anyway */
2204		/* overlapping */
2205		memmove(conni->watch_data+counter,
2206			conni->watch_data+counter+1,
2207			dpy->watcher_count - counter);
2208	    }
2209	    break;
2210	}
2211	previous = watch;
2212	counter++;
2213    }
2214    UnlockDisplay(dpy);
2215}
2216
2217/* end of internal connections support */
2218
2219
2220#if !USE_XCB
2221/* Read and discard "n" 8-bit bytes of data */
2222
2223void _XEatData(
2224    Display *dpy,
2225    register unsigned long n)
2226{
2227#define SCRATCHSIZE 2048
2228    char buf[SCRATCHSIZE];
2229
2230    while (n > 0) {
2231	register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n;
2232	(void) _XRead (dpy, buf, bytes_read);
2233	n -= bytes_read;
2234    }
2235#undef SCRATCHSIZE
2236}
2237#endif /* !USE_XCB */
2238
2239
2240/*
2241 * _XEnq - Place event packets on the display's queue.
2242 * note that no squishing of move events in V11, since there
2243 * is pointer motion hints....
2244 */
2245void _XEnq(
2246	register Display *dpy,
2247	register xEvent *event)
2248{
2249	register _XQEvent *qelt;
2250
2251	if ((qelt = dpy->qfree)) {
2252		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
2253		dpy->qfree = qelt->next;
2254	}
2255	else if ((qelt =
2256	    (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) {
2257		/* Malloc call failed! */
2258		ESET(ENOMEM);
2259		_XIOError(dpy);
2260	}
2261	qelt->next = NULL;
2262	/* go call through display to find proper event reformatter */
2263	if ((*dpy->event_vec[event->u.u.type & 0177])(dpy, &qelt->event, event)) {
2264	    qelt->qserial_num = dpy->next_event_serial_num++;
2265	    if (dpy->tail)	dpy->tail->next = qelt;
2266	    else 		dpy->head = qelt;
2267
2268	    dpy->tail = qelt;
2269	    dpy->qlen++;
2270	} else {
2271	    /* ignored, or stashed away for many-to-one compression */
2272	    qelt->next = dpy->qfree;
2273	    dpy->qfree = qelt;
2274	}
2275}
2276
2277/*
2278 * _XDeq - Remove event packet from the display's queue.
2279 */
2280void _XDeq(
2281    register Display *dpy,
2282    register _XQEvent *prev,	/* element before qelt */
2283    register _XQEvent *qelt)	/* element to be unlinked */
2284{
2285    if (prev) {
2286	if ((prev->next = qelt->next) == NULL)
2287	    dpy->tail = prev;
2288    } else {
2289	/* no prev, so removing first elt */
2290	if ((dpy->head = qelt->next) == NULL)
2291	    dpy->tail = NULL;
2292    }
2293    qelt->qserial_num = 0;
2294    qelt->next = dpy->qfree;
2295    dpy->qfree = qelt;
2296    dpy->qlen--;
2297}
2298
2299/*
2300 * EventToWire in separate file in that often not needed.
2301 */
2302
2303/*ARGSUSED*/
2304Bool
2305_XUnknownWireEvent(
2306    register Display *dpy,	/* pointer to display structure */
2307    register XEvent *re,	/* pointer to where event should be reformatted */
2308    register xEvent *event)	/* wire protocol event */
2309{
2310#ifdef notdef
2311	(void) fprintf(stderr,
2312	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
2313			event->u.u.type, dpy);
2314#endif
2315	return(False);
2316}
2317
2318/*ARGSUSED*/
2319Status
2320_XUnknownNativeEvent(
2321    register Display *dpy,	/* pointer to display structure */
2322    register XEvent *re,	/* pointer to where event should be reformatted */
2323    register xEvent *event)	/* wire protocol event */
2324{
2325#ifdef notdef
2326	(void) fprintf(stderr,
2327 	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
2328			re->type, dpy);
2329#endif
2330	return(0);
2331}
2332/*
2333 * reformat a wire event into an XEvent structure of the right type.
2334 */
2335Bool
2336_XWireToEvent(
2337    register Display *dpy,	/* pointer to display structure */
2338    register XEvent *re,	/* pointer to where event should be reformatted */
2339    register xEvent *event)	/* wire protocol event */
2340{
2341
2342	re->type = event->u.u.type & 0x7f;
2343	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
2344					(xGenericReply *)event);
2345	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
2346	((XAnyEvent *)re)->display = dpy;
2347
2348	/* Ignore the leading bit of the event type since it is set when a
2349		client sends an event rather than the server. */
2350
2351	switch (event-> u.u.type & 0177) {
2352	      case KeyPress:
2353	      case KeyRelease:
2354	        {
2355			register XKeyEvent *ev = (XKeyEvent*) re;
2356			ev->root 	= event->u.keyButtonPointer.root;
2357			ev->window 	= event->u.keyButtonPointer.event;
2358			ev->subwindow 	= event->u.keyButtonPointer.child;
2359			ev->time 	= event->u.keyButtonPointer.time;
2360			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
2361			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
2362			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
2363			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
2364			ev->state	= event->u.keyButtonPointer.state;
2365			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
2366			ev->keycode 	= event->u.u.detail;
2367		}
2368	      	break;
2369	      case ButtonPress:
2370	      case ButtonRelease:
2371	        {
2372			register XButtonEvent *ev =  (XButtonEvent *) re;
2373			ev->root 	= event->u.keyButtonPointer.root;
2374			ev->window 	= event->u.keyButtonPointer.event;
2375			ev->subwindow 	= event->u.keyButtonPointer.child;
2376			ev->time 	= event->u.keyButtonPointer.time;
2377			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
2378			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
2379			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
2380			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
2381			ev->state	= event->u.keyButtonPointer.state;
2382			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
2383			ev->button 	= event->u.u.detail;
2384		}
2385	        break;
2386	      case MotionNotify:
2387	        {
2388			register XMotionEvent *ev =   (XMotionEvent *)re;
2389			ev->root 	= event->u.keyButtonPointer.root;
2390			ev->window 	= event->u.keyButtonPointer.event;
2391			ev->subwindow 	= event->u.keyButtonPointer.child;
2392			ev->time 	= event->u.keyButtonPointer.time;
2393			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
2394			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
2395			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
2396			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
2397			ev->state	= event->u.keyButtonPointer.state;
2398			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
2399			ev->is_hint 	= event->u.u.detail;
2400		}
2401	        break;
2402	      case EnterNotify:
2403	      case LeaveNotify:
2404		{
2405			register XCrossingEvent *ev   = (XCrossingEvent *) re;
2406			ev->root	= event->u.enterLeave.root;
2407			ev->window	= event->u.enterLeave.event;
2408			ev->subwindow	= event->u.enterLeave.child;
2409			ev->time	= event->u.enterLeave.time;
2410			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
2411			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
2412			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
2413			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
2414			ev->state	= event->u.enterLeave.state;
2415			ev->mode	= event->u.enterLeave.mode;
2416			ev->same_screen = (event->u.enterLeave.flags &
2417				ELFlagSameScreen) && True;
2418			ev->focus	= (event->u.enterLeave.flags &
2419			  	ELFlagFocus) && True;
2420			ev->detail	= event->u.u.detail;
2421		}
2422		  break;
2423	      case FocusIn:
2424	      case FocusOut:
2425		{
2426			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
2427			ev->window 	= event->u.focus.window;
2428			ev->mode	= event->u.focus.mode;
2429			ev->detail	= event->u.u.detail;
2430		}
2431		  break;
2432	      case KeymapNotify:
2433		{
2434			register XKeymapEvent *ev = (XKeymapEvent *) re;
2435			ev->window	= None;
2436			memcpy(&ev->key_vector[1],
2437			       (char *)((xKeymapEvent *) event)->map,
2438			       sizeof (((xKeymapEvent *) event)->map));
2439		}
2440		break;
2441	      case Expose:
2442		{
2443			register XExposeEvent *ev = (XExposeEvent *) re;
2444			ev->window	= event->u.expose.window;
2445			ev->x		= event->u.expose.x;
2446			ev->y		= event->u.expose.y;
2447			ev->width	= event->u.expose.width;
2448			ev->height	= event->u.expose.height;
2449			ev->count	= event->u.expose.count;
2450		}
2451		break;
2452	      case GraphicsExpose:
2453		{
2454		    register XGraphicsExposeEvent *ev =
2455			(XGraphicsExposeEvent *) re;
2456		    ev->drawable	= event->u.graphicsExposure.drawable;
2457		    ev->x		= event->u.graphicsExposure.x;
2458		    ev->y		= event->u.graphicsExposure.y;
2459		    ev->width		= event->u.graphicsExposure.width;
2460		    ev->height		= event->u.graphicsExposure.height;
2461		    ev->count		= event->u.graphicsExposure.count;
2462		    ev->major_code	= event->u.graphicsExposure.majorEvent;
2463		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
2464		}
2465		break;
2466	      case NoExpose:
2467		{
2468		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
2469		    ev->drawable	= event->u.noExposure.drawable;
2470		    ev->major_code	= event->u.noExposure.majorEvent;
2471		    ev->minor_code	= event->u.noExposure.minorEvent;
2472		}
2473		break;
2474	      case VisibilityNotify:
2475		{
2476		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
2477		    ev->window		= event->u.visibility.window;
2478		    ev->state		= event->u.visibility.state;
2479		}
2480		break;
2481	      case CreateNotify:
2482		{
2483		    register XCreateWindowEvent *ev =
2484			 (XCreateWindowEvent *) re;
2485		    ev->window		= event->u.createNotify.window;
2486		    ev->parent		= event->u.createNotify.parent;
2487		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
2488		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
2489		    ev->width		= event->u.createNotify.width;
2490		    ev->height		= event->u.createNotify.height;
2491		    ev->border_width	= event->u.createNotify.borderWidth;
2492		    ev->override_redirect	= event->u.createNotify.override;
2493		}
2494		break;
2495	      case DestroyNotify:
2496		{
2497		    register XDestroyWindowEvent *ev =
2498				(XDestroyWindowEvent *) re;
2499		    ev->window		= event->u.destroyNotify.window;
2500		    ev->event		= event->u.destroyNotify.event;
2501		}
2502		break;
2503	      case UnmapNotify:
2504		{
2505		    register XUnmapEvent *ev = (XUnmapEvent *) re;
2506		    ev->window		= event->u.unmapNotify.window;
2507		    ev->event		= event->u.unmapNotify.event;
2508		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
2509		}
2510		break;
2511	      case MapNotify:
2512		{
2513		    register XMapEvent *ev = (XMapEvent *) re;
2514		    ev->window		= event->u.mapNotify.window;
2515		    ev->event		= event->u.mapNotify.event;
2516		    ev->override_redirect	= event->u.mapNotify.override;
2517		}
2518		break;
2519	      case MapRequest:
2520		{
2521		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
2522		    ev->window		= event->u.mapRequest.window;
2523		    ev->parent		= event->u.mapRequest.parent;
2524		}
2525		break;
2526	      case ReparentNotify:
2527		{
2528		    register XReparentEvent *ev = (XReparentEvent *) re;
2529		    ev->event		= event->u.reparent.event;
2530		    ev->window		= event->u.reparent.window;
2531		    ev->parent		= event->u.reparent.parent;
2532		    ev->x		= cvtINT16toInt(event->u.reparent.x);
2533		    ev->y		= cvtINT16toInt(event->u.reparent.y);
2534		    ev->override_redirect	= event->u.reparent.override;
2535		}
2536		break;
2537	      case ConfigureNotify:
2538		{
2539		    register XConfigureEvent *ev = (XConfigureEvent *) re;
2540		    ev->event	= event->u.configureNotify.event;
2541		    ev->window	= event->u.configureNotify.window;
2542		    ev->above	= event->u.configureNotify.aboveSibling;
2543		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
2544		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
2545		    ev->width	= event->u.configureNotify.width;
2546		    ev->height	= event->u.configureNotify.height;
2547		    ev->border_width  = event->u.configureNotify.borderWidth;
2548		    ev->override_redirect = event->u.configureNotify.override;
2549		}
2550		break;
2551	      case ConfigureRequest:
2552		{
2553		    register XConfigureRequestEvent *ev =
2554		        (XConfigureRequestEvent *) re;
2555		    ev->window		= event->u.configureRequest.window;
2556		    ev->parent		= event->u.configureRequest.parent;
2557		    ev->above		= event->u.configureRequest.sibling;
2558		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
2559		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
2560		    ev->width		= event->u.configureRequest.width;
2561		    ev->height		= event->u.configureRequest.height;
2562		    ev->border_width	= event->u.configureRequest.borderWidth;
2563		    ev->value_mask	= event->u.configureRequest.valueMask;
2564		    ev->detail  	= event->u.u.detail;
2565		}
2566		break;
2567	      case GravityNotify:
2568		{
2569		    register XGravityEvent *ev = (XGravityEvent *) re;
2570		    ev->window		= event->u.gravity.window;
2571		    ev->event		= event->u.gravity.event;
2572		    ev->x		= cvtINT16toInt(event->u.gravity.x);
2573		    ev->y		= cvtINT16toInt(event->u.gravity.y);
2574		}
2575		break;
2576	      case ResizeRequest:
2577		{
2578		    register XResizeRequestEvent *ev =
2579			(XResizeRequestEvent *) re;
2580		    ev->window		= event->u.resizeRequest.window;
2581		    ev->width		= event->u.resizeRequest.width;
2582		    ev->height		= event->u.resizeRequest.height;
2583		}
2584		break;
2585	      case CirculateNotify:
2586		{
2587		    register XCirculateEvent *ev = (XCirculateEvent *) re;
2588		    ev->window		= event->u.circulate.window;
2589		    ev->event		= event->u.circulate.event;
2590		    ev->place		= event->u.circulate.place;
2591		}
2592		break;
2593	      case CirculateRequest:
2594		{
2595		    register XCirculateRequestEvent *ev =
2596		        (XCirculateRequestEvent *) re;
2597		    ev->window		= event->u.circulate.window;
2598		    ev->parent		= event->u.circulate.event;
2599		    ev->place		= event->u.circulate.place;
2600		}
2601		break;
2602	      case PropertyNotify:
2603		{
2604		    register XPropertyEvent *ev = (XPropertyEvent *) re;
2605		    ev->window		= event->u.property.window;
2606		    ev->atom		= event->u.property.atom;
2607		    ev->time		= event->u.property.time;
2608		    ev->state		= event->u.property.state;
2609		}
2610		break;
2611	      case SelectionClear:
2612		{
2613		    register XSelectionClearEvent *ev =
2614			 (XSelectionClearEvent *) re;
2615		    ev->window		= event->u.selectionClear.window;
2616		    ev->selection	= event->u.selectionClear.atom;
2617		    ev->time		= event->u.selectionClear.time;
2618		}
2619		break;
2620	      case SelectionRequest:
2621		{
2622		    register XSelectionRequestEvent *ev =
2623		        (XSelectionRequestEvent *) re;
2624		    ev->owner		= event->u.selectionRequest.owner;
2625		    ev->requestor	= event->u.selectionRequest.requestor;
2626		    ev->selection	= event->u.selectionRequest.selection;
2627		    ev->target		= event->u.selectionRequest.target;
2628		    ev->property	= event->u.selectionRequest.property;
2629		    ev->time		= event->u.selectionRequest.time;
2630		}
2631		break;
2632	      case SelectionNotify:
2633		{
2634		    register XSelectionEvent *ev = (XSelectionEvent *) re;
2635		    ev->requestor	= event->u.selectionNotify.requestor;
2636		    ev->selection	= event->u.selectionNotify.selection;
2637		    ev->target		= event->u.selectionNotify.target;
2638		    ev->property	= event->u.selectionNotify.property;
2639		    ev->time		= event->u.selectionNotify.time;
2640		}
2641		break;
2642	      case ColormapNotify:
2643		{
2644		    register XColormapEvent *ev = (XColormapEvent *) re;
2645		    ev->window		= event->u.colormap.window;
2646		    ev->colormap	= event->u.colormap.colormap;
2647		    ev->new		= event->u.colormap.new;
2648		    ev->state		= event->u.colormap.state;
2649	        }
2650		break;
2651	      case ClientMessage:
2652		{
2653		   register int i;
2654		   register XClientMessageEvent *ev
2655		   			= (XClientMessageEvent *) re;
2656		   ev->window		= event->u.clientMessage.window;
2657		   ev->format		= event->u.u.detail;
2658		   switch (ev->format) {
2659			case 8:
2660			   ev->message_type = event->u.clientMessage.u.b.type;
2661			   for (i = 0; i < 20; i++)
2662			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
2663			   break;
2664			case 16:
2665			   ev->message_type = event->u.clientMessage.u.s.type;
2666			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
2667			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
2668			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
2669			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
2670			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
2671			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
2672			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
2673			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
2674			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
2675			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
2676			   break;
2677			case 32:
2678			   ev->message_type = event->u.clientMessage.u.l.type;
2679			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
2680			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
2681			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
2682			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
2683			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
2684			   break;
2685			default: /* XXX should never occur */
2686				break;
2687		    }
2688	        }
2689		break;
2690	      case MappingNotify:
2691		{
2692		   register XMappingEvent *ev = (XMappingEvent *)re;
2693		   ev->window		= 0;
2694		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
2695		   ev->request 		= event->u.mappingNotify.request;
2696		   ev->count 		= event->u.mappingNotify.count;
2697		}
2698		break;
2699	      default:
2700		return(_XUnknownWireEvent(dpy, re, event));
2701	}
2702	return(True);
2703}
2704
2705
2706/*
2707 * _XDefaultIOError - Default fatal system error reporting routine.  Called
2708 * when an X internal system error is encountered.
2709 */
2710int _XDefaultIOError(
2711	Display *dpy)
2712{
2713	if (ECHECK(EPIPE)) {
2714	    (void) fprintf (stderr,
2715	"X connection to %s broken (explicit kill or server shutdown).\r\n",
2716			    DisplayString (dpy));
2717	} else {
2718	    (void) fprintf (stderr,
2719			"XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
2720#ifdef WIN32
2721			WSAGetLastError(), strerror(WSAGetLastError()),
2722#else
2723			errno, strerror (errno),
2724#endif
2725			DisplayString (dpy));
2726	    (void) fprintf (stderr,
2727	 "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
2728			NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
2729			QLength(dpy));
2730
2731	}
2732	exit(1);
2733        return(0); /* dummy - function should never return */
2734}
2735
2736
2737static int _XPrintDefaultError(
2738    Display *dpy,
2739    XErrorEvent *event,
2740    FILE *fp)
2741{
2742    char buffer[BUFSIZ];
2743    char mesg[BUFSIZ];
2744    char number[32];
2745    const char *mtype = "XlibMessage";
2746    register _XExtension *ext = (_XExtension *)NULL;
2747    _XExtension *bext = (_XExtension *)NULL;
2748    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
2749    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
2750    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
2751    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
2752	mesg, BUFSIZ);
2753    (void) fprintf(fp, mesg, event->request_code);
2754    if (event->request_code < 128) {
2755	sprintf(number, "%d", event->request_code);
2756	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
2757    } else {
2758	for (ext = dpy->ext_procs;
2759	     ext && (ext->codes.major_opcode != event->request_code);
2760	     ext = ext->next)
2761	  ;
2762	if (ext)
2763	    strcpy(buffer, ext->name);
2764	else
2765	    buffer[0] = '\0';
2766    }
2767    (void) fprintf(fp, " (%s)\n", buffer);
2768    if (event->request_code >= 128) {
2769	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
2770			      mesg, BUFSIZ);
2771	fputs("  ", fp);
2772	(void) fprintf(fp, mesg, event->minor_code);
2773	if (ext) {
2774	    sprintf(mesg, "%s.%d", ext->name, event->minor_code);
2775	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
2776	    (void) fprintf(fp, " (%s)", buffer);
2777	}
2778	fputs("\n", fp);
2779    }
2780    if (event->error_code >= 128) {
2781	/* kludge, try to find the extension that caused it */
2782	buffer[0] = '\0';
2783	for (ext = dpy->ext_procs; ext; ext = ext->next) {
2784	    if (ext->error_string)
2785		(*ext->error_string)(dpy, event->error_code, &ext->codes,
2786				     buffer, BUFSIZ);
2787	    if (buffer[0]) {
2788		bext = ext;
2789		break;
2790	    }
2791	    if (ext->codes.first_error &&
2792		ext->codes.first_error < (int)event->error_code &&
2793		(!bext || ext->codes.first_error > bext->codes.first_error))
2794		bext = ext;
2795	}
2796	if (bext)
2797	    sprintf(buffer, "%s.%d", bext->name,
2798		    event->error_code - bext->codes.first_error);
2799	else
2800	    strcpy(buffer, "Value");
2801	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
2802	if (mesg[0]) {
2803	    fputs("  ", fp);
2804	    (void) fprintf(fp, mesg, event->resourceid);
2805	    fputs("\n", fp);
2806	}
2807	/* let extensions try to print the values */
2808	for (ext = dpy->ext_procs; ext; ext = ext->next) {
2809	    if (ext->error_values)
2810		(*ext->error_values)(dpy, event, fp);
2811	}
2812    } else if ((event->error_code == BadWindow) ||
2813	       (event->error_code == BadPixmap) ||
2814	       (event->error_code == BadCursor) ||
2815	       (event->error_code == BadFont) ||
2816	       (event->error_code == BadDrawable) ||
2817	       (event->error_code == BadColor) ||
2818	       (event->error_code == BadGC) ||
2819	       (event->error_code == BadIDChoice) ||
2820	       (event->error_code == BadValue) ||
2821	       (event->error_code == BadAtom)) {
2822	if (event->error_code == BadValue)
2823	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
2824				  mesg, BUFSIZ);
2825	else if (event->error_code == BadAtom)
2826	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
2827				  mesg, BUFSIZ);
2828	else
2829	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
2830				  mesg, BUFSIZ);
2831	fputs("  ", fp);
2832	(void) fprintf(fp, mesg, event->resourceid);
2833	fputs("\n", fp);
2834    }
2835    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
2836			  mesg, BUFSIZ);
2837    fputs("  ", fp);
2838    (void) fprintf(fp, mesg, event->serial);
2839    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
2840			  mesg, BUFSIZ);
2841    fputs("\n  ", fp);
2842    (void) fprintf(fp, mesg, dpy->request);
2843    fputs("\n", fp);
2844    if (event->error_code == BadImplementation) return 0;
2845    return 1;
2846}
2847
2848int _XDefaultError(
2849	Display *dpy,
2850	XErrorEvent *event)
2851{
2852    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
2853    exit(1);
2854    /*NOTREACHED*/
2855}
2856
2857/*ARGSUSED*/
2858Bool _XDefaultWireError(display, he, we)
2859    Display     *display;
2860    XErrorEvent *he;
2861    xError      *we;
2862{
2863    return True;
2864}
2865
2866/*
2867 * _XError - upcall internal or user protocol error handler
2868 */
2869int _XError (
2870    Display *dpy,
2871    register xError *rep)
2872{
2873    /*
2874     * X_Error packet encountered!  We need to unpack the error before
2875     * giving it to the user.
2876     */
2877    XEvent event; /* make it a large event */
2878    register _XAsyncHandler *async, *next;
2879
2880    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
2881
2882    for (async = dpy->async_handlers; async; async = next) {
2883	next = async->next;
2884	if ((*async->handler)(dpy, (xReply *)rep,
2885			      (char *)rep, SIZEOF(xError), async->data))
2886	    return 0;
2887    }
2888
2889    event.xerror.display = dpy;
2890    event.xerror.type = X_Error;
2891    event.xerror.resourceid = rep->resourceID;
2892    event.xerror.error_code = rep->errorCode;
2893    event.xerror.request_code = rep->majorCode;
2894    event.xerror.minor_code = rep->minorCode;
2895    if (dpy->error_vec &&
2896	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
2897	return 0;
2898    if (_XErrorFunction != NULL) {
2899	int rtn_val;
2900#if defined(XTHREADS) && !USE_XCB
2901	if (dpy->lock)
2902	    (*dpy->lock->user_lock_display)(dpy);
2903	UnlockDisplay(dpy);
2904#endif /* XTHREADS && !USE_XCB */
2905	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
2906#if defined(XTHREADS) && !USE_XCB
2907	LockDisplay(dpy);
2908	if (dpy->lock)
2909	    (*dpy->lock->user_unlock_display)(dpy);
2910#endif /* XTHREADS && !USE_XCB */
2911	return rtn_val;
2912    } else {
2913	return _XDefaultError(dpy, (XErrorEvent *)&event);
2914    }
2915}
2916
2917/*
2918 * _XIOError - call user connection error handler and exit
2919 */
2920int
2921_XIOError (
2922    Display *dpy)
2923{
2924    dpy->flags |= XlibDisplayIOError;
2925#ifdef WIN32
2926    errno = WSAGetLastError();
2927#endif
2928
2929    /* This assumes that the thread calling exit will call any atexit handlers.
2930     * If this does not hold, then an alternate solution would involve
2931     * registering an atexit handler to take over the lock, which would only
2932     * assume that the same thread calls all the atexit handlers. */
2933#ifdef XTHREADS
2934    if (dpy->lock)
2935	(*dpy->lock->user_lock_display)(dpy);
2936#endif
2937    UnlockDisplay(dpy);
2938
2939    if (_XIOErrorFunction != NULL)
2940	(*_XIOErrorFunction)(dpy);
2941    else
2942	_XDefaultIOError(dpy);
2943    exit (1);
2944    return 0;
2945}
2946
2947
2948/*
2949 * This routine can be used to (cheaply) get some memory within a single
2950 * Xlib routine for scratch space.  A single buffer is reused each time
2951 * if possible.  To be MT safe, you can only call this between a call to
2952 * GetReq* and a call to Data* or _XSend*, or in a context when the thread
2953 * is guaranteed to not unlock the display.
2954 */
2955char *_XAllocScratch(
2956	register Display *dpy,
2957	unsigned long nbytes)
2958{
2959	if (nbytes > dpy->scratch_length) {
2960	    if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
2961	    if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes)))
2962		dpy->scratch_length = nbytes;
2963	    else dpy->scratch_length = 0;
2964	}
2965	return (dpy->scratch_buffer);
2966}
2967
2968/*
2969 * Scratch space allocator you can call any time, multiple times, and be
2970 * MT safe, but you must hand the buffer back with _XFreeTemp.
2971 */
2972char *_XAllocTemp(
2973    register Display *dpy,
2974    unsigned long nbytes)
2975{
2976    char *buf;
2977
2978    buf = _XAllocScratch(dpy, nbytes);
2979    dpy->scratch_buffer = NULL;
2980    dpy->scratch_length = 0;
2981    return buf;
2982}
2983
2984void _XFreeTemp(
2985    register Display *dpy,
2986    char *buf,
2987    unsigned long nbytes)
2988{
2989    if (dpy->scratch_buffer)
2990	Xfree(dpy->scratch_buffer);
2991    dpy->scratch_buffer = buf;
2992    dpy->scratch_length = nbytes;
2993}
2994
2995/*
2996 * Given a visual id, find the visual structure for this id on this display.
2997 */
2998Visual *_XVIDtoVisual(
2999	Display *dpy,
3000	VisualID id)
3001{
3002	register int i, j, k;
3003	register Screen *sp;
3004	register Depth *dp;
3005	register Visual *vp;
3006	for (i = 0; i < dpy->nscreens; i++) {
3007		sp = &dpy->screens[i];
3008		for (j = 0; j < sp->ndepths; j++) {
3009			dp = &sp->depths[j];
3010			/* if nvisuals == 0 then visuals will be NULL */
3011			for (k = 0; k < dp->nvisuals; k++) {
3012				vp = &dp->visuals[k];
3013				if (vp->visualid == id) return (vp);
3014			}
3015		}
3016	}
3017	return (NULL);
3018}
3019
3020int
3021XFree (void *data)
3022{
3023	Xfree (data);
3024	return 1;
3025}
3026
3027#ifdef _XNEEDBCOPYFUNC
3028void _Xbcopy(b1, b2, length)
3029    register char *b1, *b2;
3030    register length;
3031{
3032    if (b1 < b2) {
3033	b2 += length;
3034	b1 += length;
3035	while (length--)
3036	    *--b2 = *--b1;
3037    } else {
3038	while (length--)
3039	    *b2++ = *b1++;
3040    }
3041}
3042#endif
3043
3044#ifdef DataRoutineIsProcedure
3045void Data(
3046	Display *dpy,
3047	char *data,
3048	long len)
3049{
3050	if (dpy->bufptr + (len) <= dpy->bufmax) {
3051		memcpy(dpy->bufptr, data, (int)len);
3052		dpy->bufptr += ((len) + 3) & ~3;
3053	} else {
3054		_XSend(dpy, data, len);
3055	}
3056}
3057#endif /* DataRoutineIsProcedure */
3058
3059
3060#ifdef LONG64
3061int
3062_XData32(
3063    Display *dpy,
3064    register long *data,
3065    unsigned len)
3066{
3067    register int *buf;
3068    register long i;
3069
3070    while (len) {
3071	buf = (int *)dpy->bufptr;
3072	i = dpy->bufmax - (char *)buf;
3073	if (!i) {
3074	    _XFlush(dpy);
3075	    continue;
3076	}
3077	if (len < i)
3078	    i = len;
3079	dpy->bufptr = (char *)buf + i;
3080	len -= i;
3081	i >>= 2;
3082	while (--i >= 0)
3083	    *buf++ = *data++;
3084    }
3085    return 0;
3086}
3087#endif /* LONG64 */
3088
3089#ifdef WORD64
3090
3091/*
3092 * XXX This is a *really* stupid way of doing this.  It should just use
3093 * dpy->bufptr directly, taking into account where in the word it is.
3094 */
3095
3096/*
3097 * Data16 - Place 16 bit data in the buffer.
3098 *
3099 * "dpy" is a pointer to a Display.
3100 * "data" is a pointer to the data.
3101 * "len" is the length in bytes of the data.
3102 */
3103
3104static doData16(
3105    register Display *dpy,
3106    short *data,
3107    unsigned len,
3108    char *packbuffer)
3109{
3110    long *lp,*lpack;
3111    long i, nwords,bits;
3112    long mask16 = 0x000000000000ffff;
3113
3114        lp = (long *)data;
3115        lpack = (long *)packbuffer;
3116
3117/*  nwords is the number of 16 bit values to be packed,
3118 *  the low order 16 bits of each word will be packed
3119 *  into 64 bit words
3120 */
3121        nwords = len >> 1;
3122        bits = 48;
3123
3124        for(i=0;i<nwords;i++){
3125	   if (bits == 48) *lpack = 0;
3126           *lpack ^= (*lp & mask16) << bits;
3127           bits -= 16 ;
3128           lp++;
3129           if(bits < 0){
3130               lpack++;
3131               bits = 48;
3132           }
3133        }
3134        Data(dpy, packbuffer, len);
3135}
3136
3137_XData16 (
3138    Display *dpy,
3139    short *data,
3140    unsigned len)
3141{
3142    char packbuffer[PACKBUFFERSIZE];
3143    unsigned nunits = PACKBUFFERSIZE >> 1;
3144
3145    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
3146	doData16 (dpy, data, PACKBUFFERSIZE, packbuffer);
3147    }
3148    if (len) doData16 (dpy, data, len, packbuffer);
3149}
3150
3151/*
3152 * Data32 - Place 32 bit data in the buffer.
3153 *
3154 * "dpy" is a pointer to a Display.
3155 * "data" is a pointer to the data.
3156 * "len" is the length in bytes of the data.
3157 */
3158
3159static doData32(
3160    register Display *dpy
3161    long *data,
3162    unsigned len,
3163    char *packbuffer)
3164{
3165    long *lp,*lpack;
3166    long i,bits,nwords;
3167    long mask32 = 0x00000000ffffffff;
3168
3169        lpack = (long *) packbuffer;
3170        lp = data;
3171
3172/*  nwords is the number of 32 bit values to be packed
3173 *  the low order 32 bits of each word will be packed
3174 *  into 64 bit words
3175 */
3176        nwords = len >> 2;
3177        bits = 32;
3178
3179        for(i=0;i<nwords;i++){
3180	   if (bits == 32) *lpack = 0;
3181           *lpack ^= (*lp & mask32) << bits;
3182           bits = bits ^32;
3183           lp++;
3184           if(bits)
3185              lpack++;
3186        }
3187        Data(dpy, packbuffer, len);
3188}
3189
3190void _XData32(
3191    Display *dpy,
3192    long *data,
3193    unsigned len,
3194{
3195    char packbuffer[PACKBUFFERSIZE];
3196    unsigned nunits = PACKBUFFERSIZE >> 2;
3197
3198    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
3199	doData32 (dpy, data, PACKBUFFERSIZE, packbuffer);
3200    }
3201    if (len) doData32 (dpy, data, len, packbuffer);
3202}
3203
3204#endif /* WORD64 */
3205
3206
3207/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
3208 * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
3209 *
3210 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
3211 *       to have sufficient information for interfacing to the network,
3212 *       and so, you may be better off using gethostname (if it exists).
3213 */
3214
3215#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4)
3216#define NEED_UTSNAME
3217#include <sys/utsname.h>
3218#endif
3219
3220/*
3221 * _XGetHostname - similar to gethostname but allows special processing.
3222 */
3223int _XGetHostname (
3224    char *buf,
3225    int maxlen)
3226{
3227    int len;
3228
3229#ifdef NEED_UTSNAME
3230    struct utsname name;
3231
3232    if (maxlen <= 0 || buf == NULL)
3233	return 0;
3234
3235    uname (&name);
3236    len = strlen (name.nodename);
3237    if (len >= maxlen) len = maxlen - 1;
3238    strncpy (buf, name.nodename, len);
3239    buf[len] = '\0';
3240#else
3241    if (maxlen <= 0 || buf == NULL)
3242	return 0;
3243
3244    buf[0] = '\0';
3245    (void) gethostname (buf, maxlen);
3246    buf [maxlen - 1] = '\0';
3247    len = strlen(buf);
3248#endif /* NEED_UTSNAME */
3249    return len;
3250}
3251
3252
3253/*
3254 * _XScreenOfWindow - get the Screen of a given window
3255 */
3256
3257Screen *_XScreenOfWindow (dpy, w)
3258    Display *dpy;
3259    Window w;
3260{
3261    register int i;
3262    Window root;
3263    int x, y;				/* dummy variables */
3264    unsigned int width, height, bw, depth;  /* dummy variables */
3265
3266    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
3267		      &bw, &depth) == False) {
3268	return None;
3269    }
3270    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
3271	if (root == RootWindow (dpy, i)) {
3272	    return ScreenOfDisplay (dpy, i);
3273	}
3274    }
3275    return NULL;
3276}
3277
3278
3279#if defined(WIN32)
3280
3281/*
3282 * These functions are intended to be used internally to Xlib only.
3283 * These functions will always prefix the path with a DOS drive in the
3284 * form "<drive-letter>:". As such, these functions are only suitable
3285 * for use by Xlib function that supply a root-based path to some
3286 * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
3287 * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
3288 */
3289
3290static int access_file (path, pathbuf, len_pathbuf, pathret)
3291    char* path;
3292    char* pathbuf;
3293    int len_pathbuf;
3294    char** pathret;
3295{
3296    if (access (path, F_OK) == 0) {
3297	if (strlen (path) < len_pathbuf)
3298	    *pathret = pathbuf;
3299	else
3300	    *pathret = Xmalloc (strlen (path) + 1);
3301	if (*pathret) {
3302	    strcpy (*pathret, path);
3303	    return 1;
3304	}
3305    }
3306    return 0;
3307}
3308
3309static int AccessFile (path, pathbuf, len_pathbuf, pathret)
3310    char* path;
3311    char* pathbuf;
3312    int len_pathbuf;
3313    char** pathret;
3314{
3315    unsigned long drives;
3316    int i, len;
3317    char* drive;
3318    char buf[MAX_PATH];
3319    char* bufp;
3320
3321    /* just try the "raw" name first and see if it works */
3322    if (access_file (path, pathbuf, len_pathbuf, pathret))
3323	return 1;
3324
3325    /* try the places set in the environment */
3326    drive = getenv ("_XBASEDRIVE");
3327#ifdef __UNIXOS2__
3328    if (!drive)
3329	drive = getenv ("X11ROOT");
3330#endif
3331    if (!drive)
3332	drive = "C:";
3333    len = strlen (drive) + strlen (path);
3334    if (len < MAX_PATH) bufp = buf;
3335    else bufp = Xmalloc (len + 1);
3336    strcpy (bufp, drive);
3337    strcat (bufp, path);
3338    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
3339	if (bufp != buf) Xfree (bufp);
3340	return 1;
3341    }
3342
3343#ifndef __UNIXOS2__
3344    /* one last place to look */
3345    drive = getenv ("HOMEDRIVE");
3346    if (drive) {
3347	len = strlen (drive) + strlen (path);
3348	if (len < MAX_PATH) bufp = buf;
3349	else bufp = Xmalloc (len + 1);
3350	strcpy (bufp, drive);
3351	strcat (bufp, path);
3352	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
3353	    if (bufp != buf) Xfree (bufp);
3354	    return 1;
3355	}
3356    }
3357
3358    /* tried everywhere else, go fishing */
3359#define C_DRIVE ('C' - 'A')
3360#define Z_DRIVE ('Z' - 'A')
3361    /* does OS/2 (with or with gcc-emx) have getdrives? */
3362    drives = _getdrives ();
3363    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
3364	if ((1 << i) & drives) {
3365	    len = 2 + strlen (path);
3366	    if (len < MAX_PATH) bufp = buf;
3367	    else bufp = Xmalloc (len + 1);
3368	    *bufp = 'A' + i;
3369	    *(bufp + 1) = ':';
3370	    *(bufp + 2) = '\0';
3371	    strcat (bufp, path);
3372	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
3373		if (bufp != buf) Xfree (bufp);
3374		return 1;
3375	    }
3376	}
3377    }
3378#endif
3379    return 0;
3380}
3381
3382int _XOpenFile(path, flags)
3383    _Xconst char* path;
3384    int flags;
3385{
3386    char buf[MAX_PATH];
3387    char* bufp = NULL;
3388    int ret = -1;
3389    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
3390
3391    if (AccessFile (path, buf, MAX_PATH, &bufp))
3392	ret = open (bufp, flags);
3393
3394    (void) SetErrorMode (olderror);
3395
3396    if (bufp != buf) Xfree (bufp);
3397
3398    return ret;
3399}
3400
3401int _XOpenFileMode(path, flags, mode)
3402    _Xconst char* path;
3403    int flags;
3404    mode_t mode;
3405{
3406    char buf[MAX_PATH];
3407    char* bufp = NULL;
3408    int ret = -1;
3409    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
3410
3411    if (AccessFile (path, buf, MAX_PATH, &bufp))
3412	ret = open (bufp, flags, mode);
3413
3414    (void) SetErrorMode (olderror);
3415
3416    if (bufp != buf) Xfree (bufp);
3417
3418    return ret;
3419}
3420
3421void* _XFopenFile(path, mode)
3422    _Xconst char* path;
3423    _Xconst char* mode;
3424{
3425    char buf[MAX_PATH];
3426    char* bufp = NULL;
3427    void* ret = NULL;
3428    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
3429
3430    if (AccessFile (path, buf, MAX_PATH, &bufp))
3431	ret = fopen (bufp, mode);
3432
3433    (void) SetErrorMode (olderror);
3434
3435    if (bufp != buf) Xfree (bufp);
3436
3437    return ret;
3438}
3439
3440int _XAccessFile(path)
3441    _Xconst char* path;
3442{
3443    char buf[MAX_PATH];
3444    char* bufp;
3445    int ret = -1;
3446    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
3447
3448    ret = AccessFile (path, buf, MAX_PATH, &bufp);
3449
3450    (void) SetErrorMode (olderror);
3451
3452    if (bufp != buf) Xfree (bufp);
3453
3454    return ret;
3455}
3456
3457#endif
3458
3459#ifdef WIN32
3460#undef _Xdebug
3461int _Xdebug = 0;
3462int *_Xdebug_p = &_Xdebug;
3463void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
3464void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
3465void (**_XLockMutex_fn_p)(LockInfoPtr
3466#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
3467    , char * /* file */
3468    , int /* line */
3469#endif
3470        ) = &_XLockMutex_fn;
3471void (**_XUnlockMutex_fn_p)(LockInfoPtr
3472#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
3473    , char * /* file */
3474    , int /* line */
3475#endif
3476        ) = &_XUnlockMutex_fn;
3477LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
3478#endif
3479