XlibInt.c revision 88de56cc
11ab64890Smrg/* 21ab64890Smrg 31ab64890SmrgCopyright 1985, 1986, 1987, 1998 The Open Group 41ab64890Smrg 51ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its 61ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that 71ab64890Smrgthe above copyright notice appear in all copies and that both that 81ab64890Smrgcopyright notice and this permission notice appear in supporting 91ab64890Smrgdocumentation. 101ab64890Smrg 111ab64890SmrgThe above copyright notice and this permission notice shall be included 121ab64890Smrgin all copies or substantial portions of the Software. 131ab64890Smrg 141ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 171ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 181ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 191ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 201ab64890SmrgOTHER DEALINGS IN THE SOFTWARE. 211ab64890Smrg 221ab64890SmrgExcept as contained in this notice, the name of The Open Group shall 231ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or 241ab64890Smrgother dealings in this Software without prior written authorization 251ab64890Smrgfrom The Open Group. 261ab64890Smrg 271ab64890Smrg*/ 281ab64890Smrg 291ab64890Smrg/* 301ab64890Smrg * XlibInt.c - Internal support routines for the C subroutine 311ab64890Smrg * interface library (Xlib) to the X Window System Protocol V11.0. 321ab64890Smrg */ 331ab64890Smrg#define NEED_EVENTS 341ab64890Smrg#define NEED_REPLIES 351ab64890Smrg 361ab64890Smrg#ifdef WIN32 371ab64890Smrg#define _XLIBINT_ 381ab64890Smrg#endif 391ab64890Smrg#ifdef HAVE_CONFIG_H 401ab64890Smrg#include <config.h> 411ab64890Smrg#endif 421ab64890Smrg#include "Xlibint.h" 4361b2299dSmrg#include "Xprivate.h" 441ab64890Smrg#include <X11/Xpoll.h> 451ab64890Smrg#if !USE_XCB 461ab64890Smrg#include <X11/Xtrans/Xtrans.h> 471ab64890Smrg#include <X11/extensions/xcmiscstr.h> 481ab64890Smrg#endif /* !USE_XCB */ 4961b2299dSmrg#include <assert.h> 501ab64890Smrg#include <stdio.h> 511ab64890Smrg#ifdef WIN32 521ab64890Smrg#include <direct.h> 531ab64890Smrg#endif 541ab64890Smrg 551ab64890Smrg#ifdef XTHREADS 561ab64890Smrg#include "locking.h" 571ab64890Smrg 581ab64890Smrg/* these pointers get initialized by XInitThreads */ 591ab64890SmrgLockInfoPtr _Xglobal_lock = NULL; 601ab64890Smrgvoid (*_XCreateMutex_fn)(LockInfoPtr) = NULL; 611ab64890Smrg/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */ 621ab64890Smrgvoid (*_XFreeMutex_fn)(LockInfoPtr) = NULL; 631ab64890Smrgvoid (*_XLockMutex_fn)( 641ab64890Smrg LockInfoPtr /* lock */ 651ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 661ab64890Smrg , char * /* file */ 671ab64890Smrg , int /* line */ 681ab64890Smrg#endif 691ab64890Smrg ) = NULL; 701ab64890Smrgvoid (*_XUnlockMutex_fn)( 711ab64890Smrg LockInfoPtr /* lock */ 721ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 731ab64890Smrg , char * /* file */ 741ab64890Smrg , int /* line */ 751ab64890Smrg#endif 761ab64890Smrg ) = NULL; 771ab64890Smrgxthread_t (*_Xthread_self_fn)(void) = NULL; 781ab64890Smrg 791ab64890Smrg#define XThread_Self() ((*_Xthread_self_fn)()) 801ab64890Smrg 811ab64890Smrg#if !USE_XCB 821ab64890Smrg#define UnlockNextReplyReader(d) if ((d)->lock) \ 831ab64890Smrg (*(d)->lock->pop_reader)((d),&(d)->lock->reply_awaiters,&(d)->lock->reply_awaiters_tail) 841ab64890Smrg 851ab64890Smrg#define QueueReplyReaderLock(d) ((d)->lock ? \ 861ab64890Smrg (*(d)->lock->push_reader)(d,&(d)->lock->reply_awaiters_tail) : NULL) 871ab64890Smrg#define QueueEventReaderLock(d) ((d)->lock ? \ 881ab64890Smrg (*(d)->lock->push_reader)(d,&(d)->lock->event_awaiters_tail) : NULL) 891ab64890Smrg#endif /* !USE_XCB */ 901ab64890Smrg 911ab64890Smrg#else /* XTHREADS else */ 921ab64890Smrg 931ab64890Smrg#if !USE_XCB 9461b2299dSmrg#define UnlockNextReplyReader(d) 951ab64890Smrg#define UnlockNextEventReader(d) 961ab64890Smrg#endif /* !USE_XCB */ 971ab64890Smrg 9861b2299dSmrg#endif /* XTHREADS else */ 991ab64890Smrg 1001ab64890Smrg/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX 1011ab64890Smrg * systems are broken and return EWOULDBLOCK when they should return EAGAIN 1021ab64890Smrg */ 1031ab64890Smrg#ifdef WIN32 1041ab64890Smrg#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) 1051ab64890Smrg#else 1061ab64890Smrg#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */ 1071ab64890Smrg#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) 1081ab64890Smrg#else 1091ab64890Smrg#if defined(EAGAIN) && defined(EWOULDBLOCK) 1101ab64890Smrg#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) 1111ab64890Smrg#else 1121ab64890Smrg#ifdef EAGAIN 1131ab64890Smrg#define ETEST() (errno == EAGAIN) 1141ab64890Smrg#else 1151ab64890Smrg#define ETEST() (errno == EWOULDBLOCK) 1161ab64890Smrg#endif /* EAGAIN */ 1171ab64890Smrg#endif /* EAGAIN && EWOULDBLOCK */ 1181ab64890Smrg#endif /* __CYGWIN__ */ 1191ab64890Smrg#endif /* WIN32 */ 1201ab64890Smrg 1211ab64890Smrg#ifdef WIN32 1221ab64890Smrg#define ECHECK(err) (WSAGetLastError() == err) 1231ab64890Smrg#define ESET(val) WSASetLastError(val) 1241ab64890Smrg#else 1251ab64890Smrg#ifdef __UNIXOS2__ 1261ab64890Smrg#define ECHECK(err) (errno == err) 1271ab64890Smrg#define ESET(val) 1281ab64890Smrg#else 1291ab64890Smrg#define ECHECK(err) (errno == err) 1301ab64890Smrg#define ESET(val) errno = val 1311ab64890Smrg#endif 1321ab64890Smrg#endif 1331ab64890Smrg 1341ab64890Smrg#if defined(LOCALCONN) || defined(LACHMAN) 1351ab64890Smrg#ifdef EMSGSIZE 1361ab64890Smrg#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE)) 1371ab64890Smrg#else 1381ab64890Smrg#define ESZTEST() ECHECK(ERANGE) 1391ab64890Smrg#endif 1401ab64890Smrg#else 1411ab64890Smrg#ifdef EMSGSIZE 1421ab64890Smrg#define ESZTEST() ECHECK(EMSGSIZE) 1431ab64890Smrg#endif 1441ab64890Smrg#endif 1451ab64890Smrg 1461ab64890Smrg#ifdef __UNIXOS2__ 1471ab64890Smrg#if !USE_XCB 1481ab64890Smrg#define select(n,r,w,x,t) os2ClientSelect(n,r,w,x,t) 1491ab64890Smrg#endif /* !USE_XCB */ 1501ab64890Smrg#include <limits.h> 1511ab64890Smrg#define MAX_PATH _POSIX_PATH_MAX 1521ab64890Smrg#endif 1531ab64890Smrg 1541ab64890Smrg#if !USE_XCB 1551ab64890Smrg#ifdef MUSTCOPY 1561ab64890Smrg 1571ab64890Smrg#define STARTITERATE(tpvar,type,start,endcond) \ 1581ab64890Smrg { register char *cpvar; \ 1591ab64890Smrg for (cpvar = (char *) (start); endcond; ) { \ 1601ab64890Smrg type dummy; memcpy ((char *) &dummy, cpvar, SIZEOF(type)); \ 1611ab64890Smrg tpvar = &dummy; 1621ab64890Smrg#define ITERPTR(tpvar) cpvar 1631ab64890Smrg#define RESETITERPTR(tpvar,type,start) cpvar = start 1641ab64890Smrg#define INCITERPTR(tpvar,type) cpvar += SIZEOF(type) 1651ab64890Smrg#define ENDITERATE }} 1661ab64890Smrg 1671ab64890Smrg#else 1681ab64890Smrg 1691ab64890Smrg#define STARTITERATE(tpvar,type,start,endcond) \ 1701ab64890Smrg for (tpvar = (type *) (start); endcond; ) 1711ab64890Smrg#define ITERPTR(tpvar) (char *)tpvar 1721ab64890Smrg#define RESETITERPTR(tpvar,type,start) tpvar = (type *) (start) 1731ab64890Smrg#define INCITERPTR(tpvar,type) tpvar++ 1741ab64890Smrg#define ENDITERATE 1751ab64890Smrg 1761ab64890Smrg#endif /* MUSTCOPY */ 1771ab64890Smrg 1781ab64890Smrgtypedef union { 1791ab64890Smrg xReply rep; 1801ab64890Smrg char buf[BUFSIZE]; 1811ab64890Smrg} _XAlignedBuffer; 1821ab64890Smrg 1831ab64890Smrgstatic char *_XAsyncReply( 1841ab64890Smrg Display *dpy, 1851ab64890Smrg register xReply *rep, 1861ab64890Smrg char *buf, 1871ab64890Smrg register int *lenp, 1881ab64890Smrg Bool discard); 1891ab64890Smrg#endif /* !USE_XCB */ 1901ab64890Smrg 1911ab64890Smrg/* 1921ab64890Smrg * The following routines are internal routines used by Xlib for protocol 1931ab64890Smrg * packet transmission and reception. 1941ab64890Smrg * 1951ab64890Smrg * _XIOError(Display *) will be called if any sort of system call error occurs. 1961ab64890Smrg * This is assumed to be a fatal condition, i.e., XIOError should not return. 1971ab64890Smrg * 1981ab64890Smrg * _XError(Display *, xError *) will be called whenever an X_Error event is 1991ab64890Smrg * received. This is not assumed to be a fatal condition, i.e., it is 2001ab64890Smrg * acceptable for this procedure to return. However, XError should NOT 2011ab64890Smrg * perform any operations (directly or indirectly) on the DISPLAY. 2021ab64890Smrg * 2031ab64890Smrg * Routines declared with a return type of 'Status' return 0 on failure, 20461b2299dSmrg * and non 0 on success. Routines with no declared return type don't 2051ab64890Smrg * return anything. Whenever possible routines that create objects return 2061ab64890Smrg * the object they have created. 2071ab64890Smrg */ 2081ab64890Smrg 2091ab64890Smrg#if !USE_XCB 2101ab64890Smrgstatic xReq _dummy_request = { 2111ab64890Smrg 0, 0, 0 2121ab64890Smrg}; 2131ab64890Smrg 2141ab64890Smrg/* 2151ab64890Smrg * This is an OS dependent routine which: 2161ab64890Smrg * 1) returns as soon as the connection can be written on.... 2171ab64890Smrg * 2) if the connection can be read, must enqueue events and handle errors, 2181ab64890Smrg * until the connection is writable. 2191ab64890Smrg */ 2201ab64890Smrgstatic void 2211ab64890Smrg_XWaitForWritable( 2221ab64890Smrg Display *dpy 2231ab64890Smrg#ifdef XTHREADS 2241ab64890Smrg , 2251ab64890Smrg xcondition_t cv /* our reading condition variable */ 2261ab64890Smrg#endif 2271ab64890Smrg ) 2281ab64890Smrg{ 2291ab64890Smrg#ifdef USE_POLL 2301ab64890Smrg struct pollfd filedes; 2311ab64890Smrg#else 2321ab64890Smrg fd_set r_mask; 2331ab64890Smrg fd_set w_mask; 2341ab64890Smrg#endif 2351ab64890Smrg int nfound; 2361ab64890Smrg 2371ab64890Smrg#ifdef USE_POLL 2381ab64890Smrg filedes.fd = dpy->fd; 2391ab64890Smrg filedes.events = 0; 2401ab64890Smrg#else 2411ab64890Smrg FD_ZERO(&r_mask); 2421ab64890Smrg FD_ZERO(&w_mask); 2431ab64890Smrg#endif 2441ab64890Smrg 2451ab64890Smrg for (;;) { 2461ab64890Smrg#ifdef XTHREADS 2471ab64890Smrg /* We allow only one thread at a time to read, to minimize 2481ab64890Smrg passing of read data between threads. 2491ab64890Smrg Now, who is it? If there is a non-NULL reply_awaiters and 2501ab64890Smrg we (i.e., our cv) are not at the head of it, then whoever 2511ab64890Smrg is at the head is the reader, and we don't read. 2521ab64890Smrg Otherwise there is no reply_awaiters or we are at the 2531ab64890Smrg head, having just appended ourselves. 2541ab64890Smrg In this case, if there is a event_awaiters, then whoever 2551ab64890Smrg is at the head of it got there before we did, and they are the 2561ab64890Smrg reader. 2571ab64890Smrg 2581ab64890Smrg Last cases: no event_awaiters and we are at the head of 2591ab64890Smrg reply_awaiters or reply_awaiters is NULL: we are the reader, 2601ab64890Smrg since there is obviously no one else involved. 2611ab64890Smrg 2621ab64890Smrg XXX - what if cv is NULL and someone else comes along after 2631ab64890Smrg us while we are waiting? 2641ab64890Smrg */ 26561b2299dSmrg 2661ab64890Smrg if (!dpy->lock || 2671ab64890Smrg (!dpy->lock->event_awaiters && 2681ab64890Smrg (!dpy->lock->reply_awaiters || 2691ab64890Smrg dpy->lock->reply_awaiters->cv == cv))) 2701ab64890Smrg#endif 2711ab64890Smrg#ifdef USE_POLL 2721ab64890Smrg filedes.events = POLLIN; 2731ab64890Smrg filedes.events |= POLLOUT; 2741ab64890Smrg#else 2751ab64890Smrg FD_SET(dpy->fd, &r_mask); 2761ab64890Smrg FD_SET(dpy->fd, &w_mask); 2771ab64890Smrg#endif 2781ab64890Smrg 2791ab64890Smrg do { 2801ab64890Smrg UnlockDisplay(dpy); 2811ab64890Smrg#ifdef USE_POLL 2821ab64890Smrg nfound = poll (&filedes, 1, -1); 2831ab64890Smrg#else 2841ab64890Smrg nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL); 2851ab64890Smrg#endif 2861ab64890Smrg InternalLockDisplay(dpy, cv != NULL); 2872e9c7c8cSmrg if (nfound < 0 && !(ECHECK(EINTR) || ETEST())) 2881ab64890Smrg _XIOError(dpy); 2891ab64890Smrg } while (nfound <= 0); 2901ab64890Smrg 2911ab64890Smrg if ( 2921ab64890Smrg#ifdef USE_POLL 2931ab64890Smrg filedes.revents & POLLIN 2941ab64890Smrg#else 2951ab64890Smrg FD_ISSET(dpy->fd, &r_mask) 2961ab64890Smrg#endif 2971ab64890Smrg ) 2981ab64890Smrg { 2991ab64890Smrg _XAlignedBuffer buf; 3001ab64890Smrg BytesReadable_t pend; 3011ab64890Smrg register int len; 3021ab64890Smrg register xReply *rep; 3031ab64890Smrg 3041ab64890Smrg /* find out how much data can be read */ 3051ab64890Smrg if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) 3061ab64890Smrg _XIOError(dpy); 3071ab64890Smrg len = pend; 3081ab64890Smrg 3091ab64890Smrg /* must read at least one xEvent; if none is pending, then 3101ab64890Smrg we'll just block waiting for it */ 3111ab64890Smrg if (len < SIZEOF(xReply) 3121ab64890Smrg#ifdef XTHREADS 3131ab64890Smrg || dpy->async_handlers 3141ab64890Smrg#endif 3151ab64890Smrg ) 3161ab64890Smrg len = SIZEOF(xReply); 31761b2299dSmrg 3181ab64890Smrg /* but we won't read more than the max buffer size */ 3191ab64890Smrg if (len > BUFSIZE) len = BUFSIZE; 3201ab64890Smrg 3211ab64890Smrg /* round down to an integral number of XReps */ 3221ab64890Smrg len = (len / SIZEOF(xReply)) * SIZEOF(xReply); 3231ab64890Smrg 3241ab64890Smrg (void) _XRead (dpy, buf.buf, (long) len); 3251ab64890Smrg 3261ab64890Smrg STARTITERATE(rep,xReply,buf.buf,len > 0) { 3271ab64890Smrg if (rep->generic.type == X_Reply) { 3281ab64890Smrg int tmp = len; 3291ab64890Smrg RESETITERPTR(rep,xReply, 3301ab64890Smrg _XAsyncReply (dpy, rep, 3311ab64890Smrg ITERPTR(rep), &tmp, True)); 3321ab64890Smrg len = tmp; 3331ab64890Smrg pend = len; 3341ab64890Smrg } else { 3351ab64890Smrg if (rep->generic.type == X_Error) 3361ab64890Smrg _XError (dpy, (xError *)rep); 3371ab64890Smrg else /* must be an event packet */ 3381ab64890Smrg _XEnq (dpy, (xEvent *)rep); 3391ab64890Smrg INCITERPTR(rep,xReply); 3401ab64890Smrg len -= SIZEOF(xReply); 3411ab64890Smrg } 3421ab64890Smrg } ENDITERATE 3431ab64890Smrg#ifdef XTHREADS 3441ab64890Smrg if (dpy->lock && dpy->lock->event_awaiters) 3451ab64890Smrg ConditionSignal(dpy, dpy->lock->event_awaiters->cv); 3461ab64890Smrg#endif 3471ab64890Smrg } 3481ab64890Smrg#ifdef USE_POLL 3491ab64890Smrg if (filedes.revents & (POLLOUT|POLLHUP|POLLERR)) 3501ab64890Smrg#else 3511ab64890Smrg if (FD_ISSET(dpy->fd, &w_mask)) 3521ab64890Smrg#endif 3531ab64890Smrg { 3541ab64890Smrg#ifdef XTHREADS 3551ab64890Smrg if (dpy->lock) { 3561ab64890Smrg ConditionBroadcast(dpy, dpy->lock->writers); 3571ab64890Smrg } 3581ab64890Smrg#endif 3591ab64890Smrg return; 3601ab64890Smrg } 3611ab64890Smrg } 3621ab64890Smrg} 3631ab64890Smrg#endif /* !USE_XCB */ 3641ab64890Smrg 3651ab64890Smrg 3661ab64890Smrg#define POLLFD_CACHE_SIZE 5 3671ab64890Smrg 3681ab64890Smrg/* initialize the struct array passed to poll() below */ 3691ab64890SmrgBool _XPollfdCacheInit( 3701ab64890Smrg Display *dpy) 3711ab64890Smrg{ 3721ab64890Smrg#ifdef USE_POLL 3731ab64890Smrg struct pollfd *pfp; 3741ab64890Smrg 3751ab64890Smrg pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd)); 3761ab64890Smrg if (!pfp) 3771ab64890Smrg return False; 3781ab64890Smrg pfp[0].fd = dpy->fd; 3791ab64890Smrg pfp[0].events = POLLIN; 3801ab64890Smrg 3811ab64890Smrg dpy->filedes = (XPointer)pfp; 3821ab64890Smrg#endif 3831ab64890Smrg return True; 3841ab64890Smrg} 3851ab64890Smrg 3861ab64890Smrgvoid _XPollfdCacheAdd( 3871ab64890Smrg Display *dpy, 3881ab64890Smrg int fd) 3891ab64890Smrg{ 3901ab64890Smrg#ifdef USE_POLL 3911ab64890Smrg struct pollfd *pfp = (struct pollfd *)dpy->filedes; 3921ab64890Smrg 3931ab64890Smrg if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { 3941ab64890Smrg pfp[dpy->im_fd_length].fd = fd; 3951ab64890Smrg pfp[dpy->im_fd_length].events = POLLIN; 3961ab64890Smrg } 3971ab64890Smrg#endif 3981ab64890Smrg} 3991ab64890Smrg 4001ab64890Smrg/* ARGSUSED */ 4011ab64890Smrgvoid _XPollfdCacheDel( 4021ab64890Smrg Display *dpy, 4031ab64890Smrg int fd) /* not used */ 4041ab64890Smrg{ 4051ab64890Smrg#ifdef USE_POLL 4061ab64890Smrg struct pollfd *pfp = (struct pollfd *)dpy->filedes; 4071ab64890Smrg struct _XConnectionInfo *conni; 4081ab64890Smrg 4091ab64890Smrg /* just recalculate whole list */ 4101ab64890Smrg if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { 4111ab64890Smrg int loc = 1; 4121ab64890Smrg for (conni = dpy->im_fd_info; conni; conni=conni->next) { 4131ab64890Smrg pfp[loc].fd = conni->fd; 4141ab64890Smrg pfp[loc].events = POLLIN; 4151ab64890Smrg loc++; 4161ab64890Smrg } 4171ab64890Smrg } 4181ab64890Smrg#endif 4191ab64890Smrg} 4201ab64890Smrg 4211ab64890Smrg#if !USE_XCB 4221ab64890Smrg/* returns True iff there is an event in the queue newer than serial_num */ 4231ab64890Smrg 4241ab64890Smrgstatic Bool 4251ab64890Smrg_XNewerQueuedEvent( 4261ab64890Smrg Display *dpy, 4271ab64890Smrg int serial_num) 4281ab64890Smrg{ 4291ab64890Smrg _XQEvent *qev; 4301ab64890Smrg 4311ab64890Smrg if (dpy->next_event_serial_num == serial_num) 4321ab64890Smrg return False; 4331ab64890Smrg 4341ab64890Smrg qev = dpy->head; 4351ab64890Smrg while (qev) { 4361ab64890Smrg if (qev->qserial_num >= serial_num) { 4371ab64890Smrg return True; 4381ab64890Smrg } 4391ab64890Smrg qev = qev->next; 4401ab64890Smrg } 4411ab64890Smrg return False; 4421ab64890Smrg} 4431ab64890Smrg 4441ab64890Smrgstatic int 4451ab64890Smrg_XWaitForReadable( 4461ab64890Smrg Display *dpy) 4471ab64890Smrg{ 4481ab64890Smrg int result; 4491ab64890Smrg int fd = dpy->fd; 45061b2299dSmrg struct _XConnectionInfo *ilist; 4511ab64890Smrg register int saved_event_serial = 0; 4521ab64890Smrg int in_read_events = 0; 4531ab64890Smrg register Bool did_proc_conni = False; 4541ab64890Smrg#ifdef USE_POLL 4551ab64890Smrg struct pollfd *filedes; 4561ab64890Smrg#else 4571ab64890Smrg fd_set r_mask; 4581ab64890Smrg int highest_fd = fd; 4591ab64890Smrg#endif 4601ab64890Smrg 4611ab64890Smrg#ifdef USE_POLL 4621ab64890Smrg if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE 4631ab64890Smrg && !(dpy->flags & XlibDisplayProcConni)) { 4641ab64890Smrg /* XXX - this fallback is gross */ 4651ab64890Smrg int i; 4661ab64890Smrg 4671ab64890Smrg filedes = (struct pollfd *)Xmalloc(dpy->im_fd_length * sizeof(struct pollfd)); 4681ab64890Smrg filedes[0].fd = fd; 4691ab64890Smrg filedes[0].events = POLLIN; 4701ab64890Smrg for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) { 4711ab64890Smrg filedes[i].fd = ilist->fd; 4721ab64890Smrg filedes[i].events = POLLIN; 4731ab64890Smrg } 4741ab64890Smrg } else { 4751ab64890Smrg filedes = (struct pollfd *)dpy->filedes; 4761ab64890Smrg } 4771ab64890Smrg#else 4781ab64890Smrg FD_ZERO(&r_mask); 4791ab64890Smrg#endif 4801ab64890Smrg for (;;) { 4811ab64890Smrg#ifndef USE_POLL 4821ab64890Smrg FD_SET(fd, &r_mask); 4831ab64890Smrg if (!(dpy->flags & XlibDisplayProcConni)) 4841ab64890Smrg for (ilist=dpy->im_fd_info; ilist; ilist=ilist->next) { 4851ab64890Smrg FD_SET(ilist->fd, &r_mask); 4861ab64890Smrg if (ilist->fd > highest_fd) 4871ab64890Smrg highest_fd = ilist->fd; 4881ab64890Smrg } 4891ab64890Smrg#endif 4901ab64890Smrg UnlockDisplay(dpy); 4911ab64890Smrg#ifdef USE_POLL 4921ab64890Smrg result = poll(filedes, 4931ab64890Smrg (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length, 4941ab64890Smrg -1); 4951ab64890Smrg#else 4961ab64890Smrg result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL); 4971ab64890Smrg#endif 4981ab64890Smrg InternalLockDisplay(dpy, dpy->flags & XlibDisplayReply); 4992e9c7c8cSmrg if (result == -1 && !(ECHECK(EINTR) || ETEST())) _XIOError(dpy); 5001ab64890Smrg if (result <= 0) 5011ab64890Smrg continue; 5021ab64890Smrg#ifdef USE_POLL 5031ab64890Smrg if (filedes[0].revents & (POLLIN|POLLHUP|POLLERR)) 5041ab64890Smrg#else 5051ab64890Smrg if (FD_ISSET(fd, &r_mask)) 5061ab64890Smrg#endif 5071ab64890Smrg break; 5081ab64890Smrg if (!(dpy->flags & XlibDisplayProcConni)) { 5091ab64890Smrg int i; 5101ab64890Smrg 5111ab64890Smrg saved_event_serial = dpy->next_event_serial_num; 5121ab64890Smrg /* dpy flags can be clobbered by internal connection callback */ 5131ab64890Smrg in_read_events = dpy->flags & XlibDisplayReadEvents; 5141ab64890Smrg for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) { 5151ab64890Smrg#ifdef USE_POLL 5161ab64890Smrg if (filedes[i].revents & POLLIN) 5171ab64890Smrg#else 5181ab64890Smrg if (FD_ISSET(ilist->fd, &r_mask)) 5191ab64890Smrg#endif 5201ab64890Smrg { 5211ab64890Smrg _XProcessInternalConnection(dpy, ilist); 5221ab64890Smrg did_proc_conni = True; 5231ab64890Smrg } 5241ab64890Smrg } 5251ab64890Smrg#ifdef USE_POLL 5261ab64890Smrg if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE) 5271ab64890Smrg Xfree(filedes); 5281ab64890Smrg#endif 5291ab64890Smrg } 5301ab64890Smrg if (did_proc_conni) { 5311ab64890Smrg /* some internal connection callback might have done an 5321ab64890Smrg XPutBackEvent. We notice it here and if we needed an event, 5331ab64890Smrg we can return all the way. */ 5341ab64890Smrg if (_XNewerQueuedEvent(dpy, saved_event_serial) 5351ab64890Smrg && (in_read_events 5361ab64890Smrg#ifdef XTHREADS 5371ab64890Smrg || (dpy->lock && dpy->lock->event_awaiters) 5381ab64890Smrg#endif 5391ab64890Smrg )) 5401ab64890Smrg return -2; 5411ab64890Smrg did_proc_conni = False; 5421ab64890Smrg } 5431ab64890Smrg } 5441ab64890Smrg#ifdef XTHREADS 5451ab64890Smrg#ifdef XTHREADS_DEBUG 5461ab64890Smrg printf("thread %x _XWaitForReadable returning\n", XThread_Self()); 5471ab64890Smrg#endif 5481ab64890Smrg#endif 5491ab64890Smrg return 0; 5501ab64890Smrg} 5511ab64890Smrg#endif /* !USE_XCB */ 5521ab64890Smrg 55361b2299dSmrgstatic int sync_hazard(Display *dpy) 55461b2299dSmrg{ 55561b2299dSmrg unsigned long span = dpy->request - dpy->last_request_read; 55661b2299dSmrg unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10); 55761b2299dSmrg return span >= 65535 - hazard - 10; 55861b2299dSmrg} 55961b2299dSmrg 5601ab64890Smrgstatic 56188de56ccSmrgvoid sync_while_locked(Display *dpy) 56288de56ccSmrg{ 56388de56ccSmrg#ifdef XTHREADS 56488de56ccSmrg if (dpy->lock) 56588de56ccSmrg (*dpy->lock->user_lock_display)(dpy); 56688de56ccSmrg#endif 56788de56ccSmrg UnlockDisplay(dpy); 56888de56ccSmrg SyncHandle(); 56988de56ccSmrg InternalLockDisplay(dpy, /* don't skip user locks */ 0); 57088de56ccSmrg#ifdef XTHREADS 57188de56ccSmrg if (dpy->lock) 57288de56ccSmrg (*dpy->lock->user_unlock_display)(dpy); 57388de56ccSmrg#endif 57488de56ccSmrg} 57588de56ccSmrg 57688de56ccSmrgvoid _XSeqSyncFunction( 5771ab64890Smrg register Display *dpy) 5781ab64890Smrg{ 5791ab64890Smrg xGetInputFocusReply rep; 5801ab64890Smrg register xReq *req; 5811ab64890Smrg 58261b2299dSmrg if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) { 5831ab64890Smrg GetEmptyReq(GetInputFocus, req); 5841ab64890Smrg (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); 58588de56ccSmrg sync_while_locked(dpy); 58661b2299dSmrg } else if (sync_hazard(dpy)) 58761b2299dSmrg _XSetPrivSyncFunction(dpy); 5881ab64890Smrg} 5891ab64890Smrg 59088de56ccSmrg/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */ 59161b2299dSmrgstatic int 59261b2299dSmrg_XPrivSyncFunction (Display *dpy) 59361b2299dSmrg{ 59488de56ccSmrg#if XTHREADS 59588de56ccSmrg assert(!dpy->lock_fns); 59688de56ccSmrg#endif 59761b2299dSmrg assert(dpy->synchandler == _XPrivSyncFunction); 59861b2299dSmrg assert((dpy->flags & XlibDisplayPrivSync) != 0); 59961b2299dSmrg dpy->synchandler = dpy->savedsynchandler; 60061b2299dSmrg dpy->savedsynchandler = NULL; 60161b2299dSmrg dpy->flags &= ~XlibDisplayPrivSync; 60288de56ccSmrg if(dpy->synchandler) 60388de56ccSmrg dpy->synchandler(dpy); 60461b2299dSmrg _XIDHandler(dpy); 60561b2299dSmrg _XSeqSyncFunction(dpy); 60661b2299dSmrg return 0; 60761b2299dSmrg} 60861b2299dSmrg 60961b2299dSmrgvoid _XSetPrivSyncFunction(Display *dpy) 6101ab64890Smrg{ 61188de56ccSmrg#ifdef XTHREADS 61288de56ccSmrg if (dpy->lock_fns) 61388de56ccSmrg return; 61488de56ccSmrg#endif 61561b2299dSmrg if (!(dpy->flags & XlibDisplayPrivSync)) { 6161ab64890Smrg dpy->savedsynchandler = dpy->synchandler; 61761b2299dSmrg dpy->synchandler = _XPrivSyncFunction; 6181ab64890Smrg dpy->flags |= XlibDisplayPrivSync; 6191ab64890Smrg } 6201ab64890Smrg} 6211ab64890Smrg 62261b2299dSmrgvoid _XSetSeqSyncFunction(Display *dpy) 62361b2299dSmrg{ 62461b2299dSmrg if (sync_hazard(dpy)) 62561b2299dSmrg _XSetPrivSyncFunction (dpy); 62661b2299dSmrg} 62761b2299dSmrg 6281ab64890Smrg#if !USE_XCB 6291ab64890Smrg#ifdef XTHREADS 6301ab64890Smrgstatic void _XFlushInt( 6311ab64890Smrg register Display *dpy, 6321ab64890Smrg register xcondition_t cv); 6331ab64890Smrg#endif 6341ab64890Smrg 6351ab64890Smrg/* 6361ab64890Smrg * _XFlush - Flush the X request buffer. If the buffer is empty, no 6371ab64890Smrg * action is taken. This routine correctly handles incremental writes. 6381ab64890Smrg * This routine may have to be reworked if int < long. 6391ab64890Smrg */ 6401ab64890Smrgvoid _XFlush( 6411ab64890Smrg register Display *dpy) 6421ab64890Smrg{ 6431ab64890Smrg#ifdef XTHREADS 6441ab64890Smrg /* With multi-threading we introduce an internal routine to which 6451ab64890Smrg we can pass a condition variable to do locking correctly. */ 6461ab64890Smrg 6471ab64890Smrg _XFlushInt(dpy, NULL); 6481ab64890Smrg} 6491ab64890Smrg 6501ab64890Smrg/* _XFlushInt - Internal version of _XFlush used to do multi-threaded 6511ab64890Smrg * locking correctly. 6521ab64890Smrg */ 6531ab64890Smrg 6541ab64890Smrgstatic void _XFlushInt( 6551ab64890Smrg register Display *dpy, 6561ab64890Smrg register xcondition_t cv) 6571ab64890Smrg{ 6581ab64890Smrg#endif /* XTHREADS*/ 6591ab64890Smrg register long size, todo; 6601ab64890Smrg register int write_stat; 6611ab64890Smrg register char *bufindex; 6621ab64890Smrg _XExtension *ext; 6631ab64890Smrg 6641ab64890Smrg /* This fix resets the bufptr to the front of the buffer so 6651ab64890Smrg * additional appends to the bufptr will not corrupt memory. Since 66661b2299dSmrg * the server is down, these appends are no-op's anyway but 6671ab64890Smrg * callers of _XFlush() are not verifying this before they call it. 6681ab64890Smrg */ 6691ab64890Smrg if (dpy->flags & XlibDisplayIOError) 6701ab64890Smrg { 6711ab64890Smrg dpy->bufptr = dpy->buffer; 6721ab64890Smrg dpy->last_req = (char *)&_dummy_request; 6731ab64890Smrg return; 6741ab64890Smrg } 6751ab64890Smrg 6761ab64890Smrg#ifdef XTHREADS 6771ab64890Smrg while (dpy->flags & XlibDisplayWriting) { 6781ab64890Smrg if (dpy->lock) { 6791ab64890Smrg ConditionWait(dpy, dpy->lock->writers); 6801ab64890Smrg } else { 6811ab64890Smrg _XWaitForWritable (dpy, cv); 6821ab64890Smrg } 6831ab64890Smrg } 6841ab64890Smrg#endif 6851ab64890Smrg size = todo = dpy->bufptr - dpy->buffer; 6861ab64890Smrg if (!size) return; 6871ab64890Smrg#ifdef XTHREADS 6881ab64890Smrg dpy->flags |= XlibDisplayWriting; 6891ab64890Smrg /* make sure no one else can put in data */ 6901ab64890Smrg dpy->bufptr = dpy->bufmax; 6911ab64890Smrg#endif 6921ab64890Smrg for (ext = dpy->flushes; ext; ext = ext->next_flush) 6931ab64890Smrg (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, size); 6941ab64890Smrg bufindex = dpy->buffer; 6951ab64890Smrg /* 6961ab64890Smrg * While write has not written the entire buffer, keep looping 6971ab64890Smrg * until the entire buffer is written. bufindex will be 6981ab64890Smrg * incremented and size decremented as buffer is written out. 6991ab64890Smrg */ 7001ab64890Smrg while (size) { 7011ab64890Smrg ESET(0); 7021ab64890Smrg write_stat = _X11TransWrite(dpy->trans_conn, 7031ab64890Smrg bufindex, (int) todo); 7041ab64890Smrg if (write_stat >= 0) { 7051ab64890Smrg size -= write_stat; 7061ab64890Smrg todo = size; 7071ab64890Smrg bufindex += write_stat; 7081ab64890Smrg } else if (ETEST()) { 7091ab64890Smrg _XWaitForWritable(dpy 7101ab64890Smrg#ifdef XTHREADS 7111ab64890Smrg , cv 7121ab64890Smrg#endif 7131ab64890Smrg ); 7141ab64890Smrg#ifdef SUNSYSV 7151ab64890Smrg } else if (ECHECK(0)) { 7161ab64890Smrg _XWaitForWritable(dpy 7171ab64890Smrg#ifdef XTHREADS 7181ab64890Smrg , cv 7191ab64890Smrg#endif 7201ab64890Smrg ); 7211ab64890Smrg#endif 7221ab64890Smrg#ifdef ESZTEST 7231ab64890Smrg } else if (ESZTEST()) { 72461b2299dSmrg if (todo > 1) 7251ab64890Smrg todo >>= 1; 7261ab64890Smrg else { 7271ab64890Smrg _XWaitForWritable(dpy 7281ab64890Smrg#ifdef XTHREADS 7291ab64890Smrg , cv 7301ab64890Smrg#endif 7311ab64890Smrg ); 7321ab64890Smrg } 7331ab64890Smrg#endif 7341ab64890Smrg } else if (!ECHECK(EINTR)) { 7351ab64890Smrg /* Write failed! */ 7361ab64890Smrg /* errno set by write system call. */ 7371ab64890Smrg _XIOError(dpy); 7381ab64890Smrg } 7391ab64890Smrg } 7401ab64890Smrg dpy->last_req = (char *)&_dummy_request; 7411ab64890Smrg _XSetSeqSyncFunction(dpy); 7421ab64890Smrg dpy->bufptr = dpy->buffer; 7431ab64890Smrg#ifdef XTHREADS 7441ab64890Smrg dpy->flags &= ~XlibDisplayWriting; 7451ab64890Smrg#endif 7461ab64890Smrg} 7471ab64890Smrg 7481ab64890Smrgint 7491ab64890Smrg_XEventsQueued( 7501ab64890Smrg register Display *dpy, 7511ab64890Smrg int mode) 7521ab64890Smrg{ 7531ab64890Smrg register int len; 7541ab64890Smrg BytesReadable_t pend; 7551ab64890Smrg _XAlignedBuffer buf; 7561ab64890Smrg register xReply *rep; 7571ab64890Smrg char *read_buf; 7581ab64890Smrg#ifdef XTHREADS 7591ab64890Smrg int entry_event_serial_num; 7601ab64890Smrg struct _XCVList *cvl = NULL; 7611ab64890Smrg xthread_t self; 7621ab64890Smrg 7631ab64890Smrg#ifdef XTHREADS_DEBUG 7641ab64890Smrg printf("_XEventsQueued called in thread %x\n", XThread_Self()); 7651ab64890Smrg#endif 7661ab64890Smrg#endif /* XTHREADS*/ 7671ab64890Smrg 7681ab64890Smrg if (mode == QueuedAfterFlush) 7691ab64890Smrg { 7701ab64890Smrg _XFlush(dpy); 7711ab64890Smrg if (dpy->qlen) 7721ab64890Smrg return(dpy->qlen); 7731ab64890Smrg } 7741ab64890Smrg if (dpy->flags & XlibDisplayIOError) return(dpy->qlen); 7751ab64890Smrg 7761ab64890Smrg#ifdef XTHREADS 7771ab64890Smrg /* create our condition variable and append to list, 7781ab64890Smrg * unless we were called from within XProcessInternalConnection 7791ab64890Smrg * or XLockDisplay 7801ab64890Smrg */ 7811ab64890Smrg xthread_clear_id(self); 7821ab64890Smrg if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread) 7831ab64890Smrg || xthread_have_id (dpy->lock->locking_thread))) 7841ab64890Smrg /* some thread is in XProcessInternalConnection or XLockDisplay 7851ab64890Smrg so we have to see if we are it */ 7861ab64890Smrg self = XThread_Self(); 7871ab64890Smrg if (!xthread_have_id(self) 7881ab64890Smrg || (!xthread_equal(self, dpy->lock->conni_thread) 7891ab64890Smrg && !xthread_equal(self, dpy->lock->locking_thread))) { 7901ab64890Smrg /* In the multi-threaded case, if there is someone else 7911ab64890Smrg reading events, then there aren't any available, so 7921ab64890Smrg we just return. If we waited we would block. 7931ab64890Smrg */ 7941ab64890Smrg if (dpy->lock && dpy->lock->event_awaiters) 7951ab64890Smrg return dpy->qlen; 7961ab64890Smrg /* nobody here but us, so lock out any newcomers */ 7971ab64890Smrg cvl = QueueEventReaderLock(dpy); 7981ab64890Smrg } 7991ab64890Smrg 8001ab64890Smrg while (dpy->lock && cvl && dpy->lock->reply_first) { 8011ab64890Smrg /* note which events we have already seen so we'll know 8021ab64890Smrg if _XReply (in another thread) reads one */ 8031ab64890Smrg entry_event_serial_num = dpy->next_event_serial_num; 8041ab64890Smrg ConditionWait(dpy, cvl->cv); 8051ab64890Smrg /* did _XReply read an event we can return? */ 8061ab64890Smrg if (_XNewerQueuedEvent(dpy, entry_event_serial_num)) 8071ab64890Smrg { 8081ab64890Smrg UnlockNextEventReader(dpy); 8091ab64890Smrg return 0; 8101ab64890Smrg } 8111ab64890Smrg } 8121ab64890Smrg#endif /* XTHREADS*/ 8131ab64890Smrg 8141ab64890Smrg if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) 8151ab64890Smrg _XIOError(dpy); 8161ab64890Smrg#ifdef XCONN_CHECK_FREQ 8171ab64890Smrg /* This is a crock, required because FIONREAD or equivalent is 8181ab64890Smrg * not guaranteed to detect a broken connection. 8191ab64890Smrg */ 8201ab64890Smrg if (!pend && !dpy->qlen && ++dpy->conn_checker >= XCONN_CHECK_FREQ) 8211ab64890Smrg { 8221ab64890Smrg int result; 8231ab64890Smrg#ifdef USE_POLL 8241ab64890Smrg struct pollfd filedes; 8251ab64890Smrg#else 8261ab64890Smrg fd_set r_mask; 8271ab64890Smrg static struct timeval zero_time; 8281ab64890Smrg#endif 8291ab64890Smrg 8301ab64890Smrg dpy->conn_checker = 0; 8311ab64890Smrg#ifdef USE_POLL 8321ab64890Smrg filedes.fd = dpy->fd; 8331ab64890Smrg filedes.events = POLLIN; 8341ab64890Smrg if ((result = poll(&filedes, 1, 0))) 8351ab64890Smrg#else 8361ab64890Smrg FD_ZERO(&r_mask); 8371ab64890Smrg FD_SET(dpy->fd, &r_mask); 8381ab64890Smrg if ((result = Select(dpy->fd + 1, &r_mask, NULL, NULL, &zero_time))) 8391ab64890Smrg#endif 8401ab64890Smrg { 8411ab64890Smrg if (result > 0) 8421ab64890Smrg { 8431ab64890Smrg if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) 8441ab64890Smrg _XIOError(dpy); 8451ab64890Smrg /* we should not get zero, if we do, force a read */ 8461ab64890Smrg if (!pend) 8471ab64890Smrg pend = SIZEOF(xReply); 8481ab64890Smrg } 8492e9c7c8cSmrg else if (result < 0 && !(ECHECK(EINTR) || ETEST())) 8501ab64890Smrg _XIOError(dpy); 8511ab64890Smrg } 8521ab64890Smrg } 8531ab64890Smrg#endif /* XCONN_CHECK_FREQ */ 8541ab64890Smrg if (!(len = pend)) { 8551ab64890Smrg /* _XFlush can enqueue events */ 8561ab64890Smrg#ifdef XTHREADS 8571ab64890Smrg if (cvl) 8581ab64890Smrg#endif 8591ab64890Smrg { 8601ab64890Smrg UnlockNextEventReader(dpy); 8611ab64890Smrg } 8621ab64890Smrg return(dpy->qlen); 8631ab64890Smrg } 8641ab64890Smrg /* Force a read if there is not enough data. Otherwise, 8651ab64890Smrg * a select() loop at a higher-level will spin undesirably, 8661ab64890Smrg * and we've seen at least one OS that appears to not update 8671ab64890Smrg * the result from FIONREAD once it has returned nonzero. 8681ab64890Smrg */ 8691ab64890Smrg#ifdef XTHREADS 8701ab64890Smrg if (dpy->lock && dpy->lock->reply_awaiters) { 8711ab64890Smrg read_buf = (char *)dpy->lock->reply_awaiters->buf; 8721ab64890Smrg len = SIZEOF(xReply); 8731ab64890Smrg } else 8741ab64890Smrg#endif /* XTHREADS*/ 8751ab64890Smrg { 8761ab64890Smrg read_buf = buf.buf; 87761b2299dSmrg 8781ab64890Smrg if (len < SIZEOF(xReply) 8791ab64890Smrg#ifdef XTHREADS 8801ab64890Smrg || dpy->async_handlers 8811ab64890Smrg#endif 8821ab64890Smrg ) 8831ab64890Smrg len = SIZEOF(xReply); 8841ab64890Smrg else if (len > BUFSIZE) 8851ab64890Smrg len = BUFSIZE; 8861ab64890Smrg len = (len / SIZEOF(xReply)) * SIZEOF(xReply); 8871ab64890Smrg } 8881ab64890Smrg#ifdef XCONN_CHECK_FREQ 8891ab64890Smrg dpy->conn_checker = 0; 8901ab64890Smrg#endif 8911ab64890Smrg 8921ab64890Smrg (void) _XRead (dpy, read_buf, (long) len); 89361b2299dSmrg 8941ab64890Smrg#ifdef XTHREADS 8951ab64890Smrg /* what did we actually read: reply or event? */ 8961ab64890Smrg if (dpy->lock && dpy->lock->reply_awaiters) { 8971ab64890Smrg if (((xReply *)read_buf)->generic.type == X_Reply || 8981ab64890Smrg ((xReply *)read_buf)->generic.type == X_Error) 8991ab64890Smrg { 9001ab64890Smrg dpy->lock->reply_was_read = True; 9011ab64890Smrg dpy->lock->reply_first = True; 9021ab64890Smrg if (read_buf != (char *)dpy->lock->reply_awaiters->buf) 9031ab64890Smrg memcpy(dpy->lock->reply_awaiters->buf, read_buf, 9041ab64890Smrg len); 9051ab64890Smrg if (cvl) { 9061ab64890Smrg UnlockNextEventReader(dpy); 9071ab64890Smrg } 9081ab64890Smrg return(dpy->qlen); /* we read, so we can return */ 9091ab64890Smrg } else if (read_buf != buf.buf) 9101ab64890Smrg memcpy(buf.buf, read_buf, len); 9111ab64890Smrg } 9121ab64890Smrg#endif /* XTHREADS*/ 9131ab64890Smrg 9141ab64890Smrg STARTITERATE(rep,xReply,buf.buf,len > 0) { 9151ab64890Smrg if (rep->generic.type == X_Reply) { 9161ab64890Smrg int tmp = len; 9171ab64890Smrg RESETITERPTR(rep,xReply, 9181ab64890Smrg _XAsyncReply (dpy, rep, 9191ab64890Smrg ITERPTR(rep), &tmp, True)); 9201ab64890Smrg len = tmp; 9211ab64890Smrg pend = len; 9221ab64890Smrg } else { 9231ab64890Smrg if (rep->generic.type == X_Error) 9241ab64890Smrg _XError (dpy, (xError *)rep); 9251ab64890Smrg else /* must be an event packet */ 9261ab64890Smrg _XEnq (dpy, (xEvent *)rep); 9271ab64890Smrg INCITERPTR(rep,xReply); 9281ab64890Smrg len -= SIZEOF(xReply); 9291ab64890Smrg } 9301ab64890Smrg } ENDITERATE 9311ab64890Smrg 9321ab64890Smrg#ifdef XTHREADS 9331ab64890Smrg if (cvl) 9341ab64890Smrg#endif 9351ab64890Smrg { 9361ab64890Smrg UnlockNextEventReader(dpy); 9371ab64890Smrg } 9381ab64890Smrg return(dpy->qlen); 9391ab64890Smrg} 9401ab64890Smrg 9411ab64890Smrg/* _XReadEvents - Flush the output queue, 9421ab64890Smrg * then read as many events as possible (but at least 1) and enqueue them 9431ab64890Smrg */ 9441ab64890Smrgvoid _XReadEvents( 9451ab64890Smrg register Display *dpy) 9461ab64890Smrg{ 9471ab64890Smrg _XAlignedBuffer buf; 9481ab64890Smrg BytesReadable_t pend; 9491ab64890Smrg int len; 9501ab64890Smrg register xReply *rep; 9511ab64890Smrg Bool not_yet_flushed = True; 9521ab64890Smrg char *read_buf; 9531ab64890Smrg int i; 9541ab64890Smrg int entry_event_serial_num = dpy->next_event_serial_num; 9551ab64890Smrg#ifdef XTHREADS 9561ab64890Smrg struct _XCVList *cvl = NULL; 9571ab64890Smrg xthread_t self; 9581ab64890Smrg 9591ab64890Smrg#ifdef XTHREADS_DEBUG 9601ab64890Smrg printf("_XReadEvents called in thread %x\n", 9611ab64890Smrg XThread_Self()); 9621ab64890Smrg#endif 9631ab64890Smrg /* create our condition variable and append to list, 9641ab64890Smrg * unless we were called from within XProcessInternalConnection 9651ab64890Smrg * or XLockDisplay 9661ab64890Smrg */ 9671ab64890Smrg xthread_clear_id(self); 9681ab64890Smrg if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread) 9691ab64890Smrg || xthread_have_id (dpy->lock->locking_thread))) 9701ab64890Smrg /* some thread is in XProcessInternalConnection or XLockDisplay 9711ab64890Smrg so we have to see if we are it */ 9721ab64890Smrg self = XThread_Self(); 9731ab64890Smrg if (!xthread_have_id(self) 9741ab64890Smrg || (!xthread_equal(self, dpy->lock->conni_thread) 9751ab64890Smrg && !xthread_equal(self, dpy->lock->locking_thread))) 9761ab64890Smrg cvl = QueueEventReaderLock(dpy); 9771ab64890Smrg#endif /* XTHREADS */ 9781ab64890Smrg 9791ab64890Smrg do { 9801ab64890Smrg#ifdef XTHREADS 9811ab64890Smrg /* if it is not our turn to read an event off the wire, 9821ab64890Smrg wait til we're at head of list */ 9831ab64890Smrg if (dpy->lock && cvl && 9841ab64890Smrg (dpy->lock->event_awaiters != cvl || 9851ab64890Smrg dpy->lock->reply_first)) { 9861ab64890Smrg ConditionWait(dpy, cvl->cv); 9871ab64890Smrg continue; 9881ab64890Smrg } 9891ab64890Smrg#endif /* XTHREADS */ 9901ab64890Smrg /* find out how much data can be read */ 9911ab64890Smrg if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) 9921ab64890Smrg _XIOError(dpy); 9931ab64890Smrg len = pend; 9941ab64890Smrg 9951ab64890Smrg /* must read at least one xEvent; if none is pending, then 9961ab64890Smrg we'll just flush and block waiting for it */ 9971ab64890Smrg if (len < SIZEOF(xEvent) 9981ab64890Smrg#ifdef XTHREADS 9991ab64890Smrg || dpy->async_handlers 10001ab64890Smrg#endif 10011ab64890Smrg ) { 10021ab64890Smrg len = SIZEOF(xEvent); 10031ab64890Smrg /* don't flush until the first time we would block */ 10041ab64890Smrg if (not_yet_flushed) { 10051ab64890Smrg _XFlush (dpy); 10061ab64890Smrg if (_XNewerQueuedEvent(dpy, entry_event_serial_num)) { 10071ab64890Smrg /* _XReply has read an event for us */ 10081ab64890Smrg goto got_event; 10091ab64890Smrg } 10101ab64890Smrg not_yet_flushed = False; 10111ab64890Smrg } 10121ab64890Smrg } 10131ab64890Smrg 10141ab64890Smrg#ifdef XTHREADS 10151ab64890Smrg /* If someone is waiting for a reply, gamble that 10161ab64890Smrg the reply will be the next thing on the wire 10171ab64890Smrg and read it into their buffer. */ 10181ab64890Smrg if (dpy->lock && dpy->lock->reply_awaiters) { 10191ab64890Smrg read_buf = (char *)dpy->lock->reply_awaiters->buf; 10201ab64890Smrg len = SIZEOF(xReply); 10211ab64890Smrg } else 10221ab64890Smrg#endif /* XTHREADS*/ 10231ab64890Smrg { 10241ab64890Smrg read_buf = buf.buf; 10251ab64890Smrg 10261ab64890Smrg /* but we won't read more than the max buffer size */ 10271ab64890Smrg if (len > BUFSIZE) 10281ab64890Smrg len = BUFSIZE; 10291ab64890Smrg 10301ab64890Smrg /* round down to an integral number of XReps */ 10311ab64890Smrg len = (len / SIZEOF(xEvent)) * SIZEOF(xEvent); 10321ab64890Smrg } 10331ab64890Smrg 10341ab64890Smrg#ifdef XTHREADS 10351ab64890Smrg if (xthread_have_id(self)) 10361ab64890Smrg /* save value we may have to stick in conni_thread */ 10371ab64890Smrg dpy->lock->reading_thread = self; 10381ab64890Smrg#endif /* XTHREADS */ 10391ab64890Smrg dpy->flags |= XlibDisplayReadEvents; 10401ab64890Smrg i = _XRead (dpy, read_buf, (long) len); 10411ab64890Smrg dpy->flags &= ~XlibDisplayReadEvents; 10421ab64890Smrg if (i == -2) { 10431ab64890Smrg /* special flag from _XRead to say that internal connection has 10441ab64890Smrg done XPutBackEvent. Which we can use so we're done. */ 10451ab64890Smrg got_event: 10461ab64890Smrg#ifdef XTHREADS 10471ab64890Smrg if (dpy->lock && dpy->lock->lock_wait) { 10481ab64890Smrg if (dpy->lock->event_awaiters != cvl) 10491ab64890Smrg /* since it is not us, must be user lock thread */ 10501ab64890Smrg ConditionSignal(dpy, 10511ab64890Smrg dpy->lock->event_awaiters->cv); 10521ab64890Smrg (*dpy->lock->lock_wait)(dpy); 10531ab64890Smrg continue; 10541ab64890Smrg } 10551ab64890Smrg#endif 10561ab64890Smrg break; 10571ab64890Smrg } 10581ab64890Smrg#ifdef XTHREADS 10591ab64890Smrg if (xthread_have_id(self)) 10601ab64890Smrg xthread_clear_id(dpy->lock->reading_thread); 10611ab64890Smrg 10621ab64890Smrg /* what did we actually read: reply or event? */ 10631ab64890Smrg if (dpy->lock && dpy->lock->reply_awaiters) { 10641ab64890Smrg if (((xReply *)read_buf)->generic.type == X_Reply || 10651ab64890Smrg ((xReply *)read_buf)->generic.type == X_Error) 10661ab64890Smrg { 10671ab64890Smrg dpy->lock->reply_was_read = True; 10681ab64890Smrg dpy->lock->reply_first = True; 10691ab64890Smrg if (read_buf != (char *)dpy->lock->reply_awaiters->buf) 10701ab64890Smrg memcpy(dpy->lock->reply_awaiters->buf, 10711ab64890Smrg read_buf, len); 10721ab64890Smrg ConditionSignal(dpy, dpy->lock->reply_awaiters->cv); 10731ab64890Smrg continue; 10741ab64890Smrg } else if (read_buf != buf.buf) 10751ab64890Smrg memcpy(buf.buf, read_buf, len); 10761ab64890Smrg } 10771ab64890Smrg#endif /* XTHREADS */ 10781ab64890Smrg 10791ab64890Smrg STARTITERATE(rep,xReply,buf.buf,len > 0) { 10801ab64890Smrg if (rep->generic.type == X_Reply) { 10811ab64890Smrg RESETITERPTR(rep,xReply, 10821ab64890Smrg _XAsyncReply (dpy, rep, 10831ab64890Smrg ITERPTR(rep), &len, True)); 108461b2299dSmrg pend = len; 10851ab64890Smrg } else { 10861ab64890Smrg if (rep->generic.type == X_Error) 10871ab64890Smrg _XError (dpy, (xError *) rep); 10881ab64890Smrg else /* must be an event packet */ 108961b2299dSmrg { 109061b2299dSmrg if (rep->generic.type == GenericEvent) 109161b2299dSmrg { 109261b2299dSmrg int evlen; 109361b2299dSmrg evlen = (rep->generic.length << 2); 109461b2299dSmrg if (_XRead(dpy, &read_buf[len], evlen) == -2) 109561b2299dSmrg goto got_event; /* XXX: aargh! */ 109661b2299dSmrg } 109761b2299dSmrg 109861b2299dSmrg _XEnq (dpy, (xEvent *)rep); 109961b2299dSmrg } 11001ab64890Smrg INCITERPTR(rep,xReply); 11011ab64890Smrg len -= SIZEOF(xReply); 11021ab64890Smrg } 11031ab64890Smrg } ENDITERATE; 11041ab64890Smrg } while (!_XNewerQueuedEvent(dpy, entry_event_serial_num)); 11051ab64890Smrg 11061ab64890Smrg UnlockNextEventReader(dpy); 11071ab64890Smrg} 11081ab64890Smrg 110961b2299dSmrg/* 11101ab64890Smrg * _XRead - Read bytes from the socket taking into account incomplete 11111ab64890Smrg * reads. This routine may have to be reworked if int < long. 11121ab64890Smrg */ 11131ab64890Smrgint _XRead( 11141ab64890Smrg register Display *dpy, 11151ab64890Smrg register char *data, 11161ab64890Smrg register long size) 11171ab64890Smrg{ 11181ab64890Smrg register long bytes_read; 11191ab64890Smrg#ifdef XTHREADS 11201ab64890Smrg int original_size = size; 11211ab64890Smrg#endif 11221ab64890Smrg 11231ab64890Smrg if ((dpy->flags & XlibDisplayIOError) || size == 0) 11241ab64890Smrg return 0; 11251ab64890Smrg ESET(0); 11261ab64890Smrg while ((bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size)) 11271ab64890Smrg != size) { 11281ab64890Smrg 11291ab64890Smrg if (bytes_read > 0) { 11301ab64890Smrg size -= bytes_read; 11311ab64890Smrg data += bytes_read; 11321ab64890Smrg } 11331ab64890Smrg else if (ETEST()) { 11341ab64890Smrg if (_XWaitForReadable(dpy) == -2) 11351ab64890Smrg return -2; /* internal connection did XPutBackEvent */ 11361ab64890Smrg ESET(0); 11371ab64890Smrg } 11381ab64890Smrg#ifdef SUNSYSV 11391ab64890Smrg else if (ECHECK(0)) { 11401ab64890Smrg if (_XWaitForReadable(dpy) == -2) 11411ab64890Smrg return -2; /* internal connection did XPutBackEvent */ 11421ab64890Smrg } 11431ab64890Smrg#endif 11441ab64890Smrg else if (bytes_read == 0) { 11451ab64890Smrg /* Read failed because of end of file! */ 11461ab64890Smrg ESET(EPIPE); 11471ab64890Smrg _XIOError(dpy); 11481ab64890Smrg } 11491ab64890Smrg 11501ab64890Smrg else /* bytes_read is less than 0; presumably -1 */ { 11511ab64890Smrg /* If it's a system call interrupt, it's not an error. */ 11521ab64890Smrg if (!ECHECK(EINTR)) 11531ab64890Smrg _XIOError(dpy); 11541ab64890Smrg } 11551ab64890Smrg } 11561ab64890Smrg#ifdef XTHREADS 11571ab64890Smrg if (dpy->lock && dpy->lock->reply_bytes_left > 0) 11581ab64890Smrg { 11591ab64890Smrg dpy->lock->reply_bytes_left -= original_size; 11601ab64890Smrg if (dpy->lock->reply_bytes_left == 0) { 11611ab64890Smrg dpy->flags &= ~XlibDisplayReply; 11621ab64890Smrg UnlockNextReplyReader(dpy); 11631ab64890Smrg } 11641ab64890Smrg } 11651ab64890Smrg#endif /* XTHREADS*/ 11661ab64890Smrg return 0; 11671ab64890Smrg} 11681ab64890Smrg#endif /* !USE_XCB */ 11691ab64890Smrg 11701ab64890Smrg#ifdef LONG64 11711ab64890Smrgvoid _XRead32( 11721ab64890Smrg Display *dpy, 11731ab64890Smrg register long *data, 11741ab64890Smrg long len) 11751ab64890Smrg{ 11761ab64890Smrg register int *buf; 11771ab64890Smrg register long i; 11781ab64890Smrg 11791ab64890Smrg if (len) { 11801ab64890Smrg (void) _XRead(dpy, (char *)data, len); 11811ab64890Smrg i = len >> 2; 11821ab64890Smrg buf = (int *)data + i; 11831ab64890Smrg data += i; 11841ab64890Smrg while (--i >= 0) 11851ab64890Smrg *--data = *--buf; 11861ab64890Smrg } 11871ab64890Smrg} 11881ab64890Smrg#endif /* LONG64 */ 11891ab64890Smrg 11901ab64890Smrg#ifdef WORD64 11911ab64890Smrg 11921ab64890Smrg/* 11931ab64890Smrg * XXX This is a *really* stupid way of doing this.... 11941ab64890Smrg * PACKBUFFERSIZE must be a multiple of 4. 11951ab64890Smrg */ 11961ab64890Smrg 11971ab64890Smrg#define PACKBUFFERSIZE 4096 11981ab64890Smrg 11991ab64890Smrg 12001ab64890Smrg/* 12011ab64890Smrg * _XRead32 - Read bytes from the socket unpacking each 32 bits 12021ab64890Smrg * into a long (64 bits on a CRAY computer). 120361b2299dSmrg * 12041ab64890Smrg */ 12051ab64890Smrgstatic void _doXRead32( 12061ab64890Smrg register Display *dpy, 12071ab64890Smrg register long *data 12081ab64890Smrg register long size, 12091ab64890Smrg register char *packbuffer) 12101ab64890Smrg{ 12111ab64890Smrg long *lpack,*lp; 12121ab64890Smrg long mask32 = 0x00000000ffffffff; 12131ab64890Smrg long maskw, nwords, i, bits; 12141ab64890Smrg 12151ab64890Smrg _XReadPad (dpy, packbuffer, size); 12161ab64890Smrg 12171ab64890Smrg lp = data; 12181ab64890Smrg lpack = (long *) packbuffer; 12191ab64890Smrg nwords = size >> 2; 12201ab64890Smrg bits = 32; 12211ab64890Smrg 12221ab64890Smrg for(i=0;i<nwords;i++){ 12231ab64890Smrg maskw = mask32 << bits; 12241ab64890Smrg *lp++ = ( *lpack & maskw ) >> bits; 12251ab64890Smrg bits = bits ^32; 12261ab64890Smrg if(bits){ 12271ab64890Smrg lpack++; 12281ab64890Smrg } 12291ab64890Smrg } 12301ab64890Smrg} 12311ab64890Smrg 12321ab64890Smrgvoid _XRead32( 12331ab64890Smrg Display *dpy, 12341ab64890Smrg long *data, 12351ab64890Smrg long len) 12361ab64890Smrg{ 12371ab64890Smrg char packbuffer[PACKBUFFERSIZE]; 12381ab64890Smrg unsigned nunits = PACKBUFFERSIZE >> 2; 12391ab64890Smrg 12401ab64890Smrg for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 12411ab64890Smrg _doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer); 12421ab64890Smrg } 12431ab64890Smrg if (len) _doXRead32 (dpy, data, len, packbuffer); 12441ab64890Smrg} 12451ab64890Smrg 12461ab64890Smrg 12471ab64890Smrg 12481ab64890Smrg/* 12491ab64890Smrg * _XRead16 - Read bytes from the socket unpacking each 16 bits 12501ab64890Smrg * into a long (64 bits on a CRAY computer). 12511ab64890Smrg * 12521ab64890Smrg */ 12531ab64890Smrgstatic _doXRead16( 12541ab64890Smrg register Display *dpy, 12551ab64890Smrg register short *data, 12561ab64890Smrg register long size, 12571ab64890Smrg char *packbuffer) 12581ab64890Smrg{ 12591ab64890Smrg long *lpack,*lp; 12601ab64890Smrg long mask16 = 0x000000000000ffff; 12611ab64890Smrg long maskw, nwords, i, bits; 12621ab64890Smrg 12631ab64890Smrg (void) _XRead(dpy,packbuffer,size); /* don't do a padded read... */ 12641ab64890Smrg 12651ab64890Smrg lp = (long *) data; 12661ab64890Smrg lpack = (long *) packbuffer; 12671ab64890Smrg nwords = size >> 1; /* number of 16 bit words to be unpacked */ 12681ab64890Smrg bits = 48; 12691ab64890Smrg for(i=0;i<nwords;i++){ 12701ab64890Smrg maskw = mask16 << bits; 12711ab64890Smrg *lp++ = ( *lpack & maskw ) >> bits; 12721ab64890Smrg bits -= 16; 12731ab64890Smrg if(bits < 0){ 12741ab64890Smrg lpack++; 12751ab64890Smrg bits = 48; 12761ab64890Smrg } 12771ab64890Smrg } 12781ab64890Smrg} 12791ab64890Smrg 12801ab64890Smrgvoid _XRead16( 12811ab64890Smrg Display *dpy, 12821ab64890Smrg short *data, 12831ab64890Smrg long len) 12841ab64890Smrg{ 12851ab64890Smrg char packbuffer[PACKBUFFERSIZE]; 12861ab64890Smrg unsigned nunits = PACKBUFFERSIZE >> 1; 12871ab64890Smrg 12881ab64890Smrg for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 12891ab64890Smrg _doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer); 12901ab64890Smrg } 12911ab64890Smrg if (len) _doXRead16 (dpy, data, len, packbuffer); 12921ab64890Smrg} 12931ab64890Smrg 12941ab64890Smrgvoid _XRead16Pad( 12951ab64890Smrg Display *dpy, 12961ab64890Smrg short *data, 12971ab64890Smrg long size) 12981ab64890Smrg{ 12991ab64890Smrg int slop = (size & 3); 13001ab64890Smrg short slopbuf[3]; 13011ab64890Smrg 13021ab64890Smrg _XRead16 (dpy, data, size); 13031ab64890Smrg if (slop > 0) { 13041ab64890Smrg _XRead16 (dpy, slopbuf, 4 - slop); 13051ab64890Smrg } 13061ab64890Smrg} 13071ab64890Smrg#endif /* WORD64 */ 13081ab64890Smrg 13091ab64890Smrg 13101ab64890Smrg#if !USE_XCB 13111ab64890Smrg/* 13121ab64890Smrg * _XReadPad - Read bytes from the socket taking into account incomplete 13131ab64890Smrg * reads. If the number of bytes is not 0 mod 4, read additional pad 13141ab64890Smrg * bytes. This routine may have to be reworked if int < long. 13151ab64890Smrg */ 13161ab64890Smrgvoid _XReadPad( 13171ab64890Smrg register Display *dpy, 13181ab64890Smrg register char *data, 13191ab64890Smrg register long size) 13201ab64890Smrg{ 13211ab64890Smrg register long bytes_read; 13221ab64890Smrg struct iovec iov[2]; 13231ab64890Smrg char pad[3]; 13241ab64890Smrg#ifdef XTHREADS 13251ab64890Smrg int original_size; 13261ab64890Smrg#endif 13271ab64890Smrg 13281ab64890Smrg if ((dpy->flags & XlibDisplayIOError) || size == 0) return; 13291ab64890Smrg iov[0].iov_len = (int)size; 13301ab64890Smrg iov[0].iov_base = data; 133161b2299dSmrg /* 13321ab64890Smrg * The following hack is used to provide 32 bit long-word 13331ab64890Smrg * aligned padding. The [1] vector is of length 0, 1, 2, or 3, 13341ab64890Smrg * whatever is needed. 13351ab64890Smrg */ 13361ab64890Smrg 13371ab64890Smrg iov[1].iov_len = -size & 3; 13381ab64890Smrg iov[1].iov_base = pad; 13391ab64890Smrg size += iov[1].iov_len; 13401ab64890Smrg#ifdef XTHREADS 13411ab64890Smrg original_size = size; 13421ab64890Smrg#endif 13431ab64890Smrg ESET(0); 13441ab64890Smrg while ((bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2)) != size) { 13451ab64890Smrg 13461ab64890Smrg if (bytes_read > 0) { 13471ab64890Smrg size -= bytes_read; 13481ab64890Smrg if (iov[0].iov_len < bytes_read) { 13491ab64890Smrg int pad_bytes_read = bytes_read - iov[0].iov_len; 13501ab64890Smrg iov[1].iov_len -= pad_bytes_read; 13511ab64890Smrg iov[1].iov_base = 13521ab64890Smrg (char *)iov[1].iov_base + pad_bytes_read; 13531ab64890Smrg iov[0].iov_len = 0; 13541ab64890Smrg } 13551ab64890Smrg else { 13561ab64890Smrg iov[0].iov_len -= bytes_read; 13571ab64890Smrg iov[0].iov_base = (char *)iov[0].iov_base + bytes_read; 13581ab64890Smrg } 13591ab64890Smrg } 13601ab64890Smrg else if (ETEST()) { 13611ab64890Smrg _XWaitForReadable(dpy); 13621ab64890Smrg ESET(0); 13631ab64890Smrg } 13641ab64890Smrg#ifdef SUNSYSV 13651ab64890Smrg else if (ECHECK(0)) { 13661ab64890Smrg _XWaitForReadable(dpy); 13671ab64890Smrg } 13681ab64890Smrg#endif 13691ab64890Smrg else if (bytes_read == 0) { 13701ab64890Smrg /* Read failed because of end of file! */ 13711ab64890Smrg ESET(EPIPE); 13721ab64890Smrg _XIOError(dpy); 13731ab64890Smrg } 137461b2299dSmrg 13751ab64890Smrg else /* bytes_read is less than 0; presumably -1 */ { 13761ab64890Smrg /* If it's a system call interrupt, it's not an error. */ 13771ab64890Smrg if (!ECHECK(EINTR)) 13781ab64890Smrg _XIOError(dpy); 13791ab64890Smrg } 13801ab64890Smrg } 13811ab64890Smrg#ifdef XTHREADS 13821ab64890Smrg if (dpy->lock && dpy->lock->reply_bytes_left > 0) 13831ab64890Smrg { 13841ab64890Smrg dpy->lock->reply_bytes_left -= original_size; 13851ab64890Smrg if (dpy->lock->reply_bytes_left == 0) { 13861ab64890Smrg dpy->flags &= ~XlibDisplayReply; 13871ab64890Smrg UnlockNextReplyReader(dpy); 13881ab64890Smrg } 13891ab64890Smrg } 13901ab64890Smrg#endif /* XTHREADS*/ 13911ab64890Smrg} 13921ab64890Smrg 13931ab64890Smrg/* 13941ab64890Smrg * _XSend - Flush the buffer and send the client data. 32 bit word aligned 13951ab64890Smrg * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. 13961ab64890Smrg * This routine may have to be reworked if int < long; 13971ab64890Smrg */ 13981ab64890Smrgvoid 13991ab64890Smrg_XSend ( 14001ab64890Smrg register Display *dpy, 14011ab64890Smrg _Xconst char *data, 14021ab64890Smrg register long size) 14031ab64890Smrg{ 14041ab64890Smrg struct iovec iov[3]; 14051ab64890Smrg static char const pad[3] = {0, 0, 0}; 14061ab64890Smrg /* XText8 and XText16 require that the padding bytes be zero! */ 14071ab64890Smrg 14081ab64890Smrg long skip, dbufsize, padsize, total, todo; 14091ab64890Smrg _XExtension *ext; 14101ab64890Smrg 14111ab64890Smrg if (!size || (dpy->flags & XlibDisplayIOError)) return; 14121ab64890Smrg dbufsize = dpy->bufptr - dpy->buffer; 14131ab64890Smrg#ifdef XTHREADS 14141ab64890Smrg dpy->flags |= XlibDisplayWriting; 14151ab64890Smrg /* make sure no one else can put in data */ 14161ab64890Smrg dpy->bufptr = dpy->bufmax; 14171ab64890Smrg#endif 14181ab64890Smrg padsize = -size & 3; 14191ab64890Smrg for (ext = dpy->flushes; ext; ext = ext->next_flush) { 14201ab64890Smrg (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, dbufsize); 14211ab64890Smrg (*ext->before_flush)(dpy, &ext->codes, (char *)data, size); 14221ab64890Smrg if (padsize) 14231ab64890Smrg (*ext->before_flush)(dpy, &ext->codes, pad, padsize); 14241ab64890Smrg } 14251ab64890Smrg skip = 0; 14261ab64890Smrg todo = total = dbufsize + size + padsize; 14271ab64890Smrg 14281ab64890Smrg /* 14291ab64890Smrg * There are 3 pieces that may need to be written out: 14301ab64890Smrg * 14311ab64890Smrg * o whatever is in the display buffer 14321ab64890Smrg * o the data passed in by the user 14331ab64890Smrg * o any padding needed to 32bit align the whole mess 14341ab64890Smrg * 14351ab64890Smrg * This loop looks at all 3 pieces each time through. It uses skip 14361ab64890Smrg * to figure out whether or not a given piece is needed. 14371ab64890Smrg */ 14381ab64890Smrg while (total) { 14391ab64890Smrg long before = skip; /* amount of whole thing written */ 14401ab64890Smrg long remain = todo; /* amount to try this time, <= total */ 14411ab64890Smrg int i = 0; 14421ab64890Smrg long len; 14431ab64890Smrg 14441ab64890Smrg /* You could be very general here and have "in" and "out" iovecs 14451ab64890Smrg * and write a loop without using a macro, but what the heck. This 14461ab64890Smrg * translates to: 14471ab64890Smrg * 14481ab64890Smrg * how much of this piece is new? 14491ab64890Smrg * if more new then we are trying this time, clamp 14501ab64890Smrg * if nothing new 14511ab64890Smrg * then bump down amount already written, for next piece 14521ab64890Smrg * else put new stuff in iovec, will need all of next piece 14531ab64890Smrg * 14541ab64890Smrg * Note that todo had better be at least 1 or else we'll end up 14551ab64890Smrg * writing 0 iovecs. 14561ab64890Smrg */ 14571ab64890Smrg#define InsertIOV(pointer, length) \ 14581ab64890Smrg len = (length) - before; \ 14591ab64890Smrg if (len > remain) \ 14601ab64890Smrg len = remain; \ 14611ab64890Smrg if (len <= 0) { \ 14621ab64890Smrg before = (-len); \ 14631ab64890Smrg } else { \ 14641ab64890Smrg iov[i].iov_len = len; \ 14651ab64890Smrg iov[i].iov_base = (pointer) + before; \ 14661ab64890Smrg i++; \ 14671ab64890Smrg remain -= len; \ 14681ab64890Smrg before = 0; \ 14691ab64890Smrg } 14701ab64890Smrg 14711ab64890Smrg InsertIOV (dpy->buffer, dbufsize) 14721ab64890Smrg InsertIOV ((char *)data, size) 14731ab64890Smrg InsertIOV ((char *)pad, padsize) 147461b2299dSmrg 14751ab64890Smrg ESET(0); 14761ab64890Smrg if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) { 14771ab64890Smrg skip += len; 14781ab64890Smrg total -= len; 14791ab64890Smrg todo = total; 14801ab64890Smrg } else if (ETEST()) { 14811ab64890Smrg _XWaitForWritable(dpy 14821ab64890Smrg#ifdef XTHREADS 14831ab64890Smrg , NULL 14841ab64890Smrg#endif 14851ab64890Smrg ); 14861ab64890Smrg#ifdef SUNSYSV 14871ab64890Smrg } else if (ECHECK(0)) { 14881ab64890Smrg _XWaitForWritable(dpy 14891ab64890Smrg#ifdef XTHREADS 14901ab64890Smrg , NULL 14911ab64890Smrg#endif 14921ab64890Smrg ); 14931ab64890Smrg#endif 14941ab64890Smrg#ifdef ESZTEST 14951ab64890Smrg } else if (ESZTEST()) { 149661b2299dSmrg if (todo > 1) 14971ab64890Smrg todo >>= 1; 14981ab64890Smrg else { 14991ab64890Smrg _XWaitForWritable(dpy 15001ab64890Smrg#ifdef XTHREADS 15011ab64890Smrg , NULL 15021ab64890Smrg#endif 15031ab64890Smrg ); 15041ab64890Smrg } 15051ab64890Smrg#endif 15061ab64890Smrg } else if (!ECHECK(EINTR)) { 15071ab64890Smrg _XIOError(dpy); 15081ab64890Smrg } 15091ab64890Smrg } 15101ab64890Smrg dpy->last_req = (char *) & _dummy_request; 15111ab64890Smrg _XSetSeqSyncFunction(dpy); 15121ab64890Smrg dpy->bufptr = dpy->buffer; 15131ab64890Smrg#ifdef XTHREADS 15141ab64890Smrg dpy->flags &= ~XlibDisplayWriting; 15151ab64890Smrg#endif 15161ab64890Smrg return; 15171ab64890Smrg} 15181ab64890Smrg 15191ab64890Smrgstatic void 15201ab64890Smrg_XGetMiscCode( 15211ab64890Smrg register Display *dpy) 15221ab64890Smrg{ 15231ab64890Smrg xQueryExtensionReply qrep; 15241ab64890Smrg register xQueryExtensionReq *qreq; 15251ab64890Smrg xXCMiscGetVersionReply vrep; 15261ab64890Smrg register xXCMiscGetVersionReq *vreq; 15271ab64890Smrg 15281ab64890Smrg if (dpy->xcmisc_opcode) 15291ab64890Smrg return; 15301ab64890Smrg GetReq(QueryExtension, qreq); 15311ab64890Smrg qreq->nbytes = sizeof(XCMiscExtensionName) - 1; 15321ab64890Smrg qreq->length += (qreq->nbytes+(unsigned)3)>>2; 15331ab64890Smrg _XSend(dpy, XCMiscExtensionName, (long)qreq->nbytes); 15341ab64890Smrg if (!_XReply (dpy, (xReply *)&qrep, 0, xTrue)) 15351ab64890Smrg dpy->xcmisc_opcode = -1; 15361ab64890Smrg else { 15371ab64890Smrg GetReq(XCMiscGetVersion, vreq); 15381ab64890Smrg vreq->reqType = qrep.major_opcode; 15391ab64890Smrg vreq->miscReqType = X_XCMiscGetVersion; 15401ab64890Smrg vreq->majorVersion = XCMiscMajorVersion; 15411ab64890Smrg vreq->minorVersion = XCMiscMinorVersion; 15421ab64890Smrg if (!_XReply (dpy, (xReply *)&vrep, 0, xTrue)) 15431ab64890Smrg dpy->xcmisc_opcode = -1; 15441ab64890Smrg else 15451ab64890Smrg dpy->xcmisc_opcode = qrep.major_opcode; 15461ab64890Smrg } 15471ab64890Smrg} 15481ab64890Smrg 154988de56ccSmrgvoid 15501ab64890Smrg_XIDHandler( 15511ab64890Smrg register Display *dpy) 15521ab64890Smrg{ 15531ab64890Smrg xXCMiscGetXIDRangeReply grep; 15541ab64890Smrg register xXCMiscGetXIDRangeReq *greq; 15551ab64890Smrg 155661b2299dSmrg if (dpy->resource_max == dpy->resource_mask + 1) { 155761b2299dSmrg _XGetMiscCode(dpy); 155861b2299dSmrg if (dpy->xcmisc_opcode > 0) { 155961b2299dSmrg GetReq(XCMiscGetXIDRange, greq); 156061b2299dSmrg greq->reqType = dpy->xcmisc_opcode; 156161b2299dSmrg greq->miscReqType = X_XCMiscGetXIDRange; 156261b2299dSmrg if (_XReply (dpy, (xReply *)&grep, 0, xTrue) && grep.count) { 156361b2299dSmrg dpy->resource_id = ((grep.start_id - dpy->resource_base) >> 156461b2299dSmrg dpy->resource_shift); 156561b2299dSmrg dpy->resource_max = dpy->resource_id; 156661b2299dSmrg if (grep.count > 5) 156761b2299dSmrg dpy->resource_max += grep.count - 6; 156861b2299dSmrg dpy->resource_max <<= dpy->resource_shift; 156961b2299dSmrg } 157088de56ccSmrg sync_while_locked(dpy); 15711ab64890Smrg } 15721ab64890Smrg } 15731ab64890Smrg} 15741ab64890Smrg 15751ab64890Smrg/* 15761ab64890Smrg * _XAllocID - resource ID allocation routine. 15771ab64890Smrg */ 15781ab64890SmrgXID _XAllocID( 15791ab64890Smrg register Display *dpy) 15801ab64890Smrg{ 15811ab64890Smrg XID id; 15821ab64890Smrg 15831ab64890Smrg id = dpy->resource_id << dpy->resource_shift; 15841ab64890Smrg if (id >= dpy->resource_max) { 158561b2299dSmrg _XSetPrivSyncFunction(dpy); 15861ab64890Smrg dpy->resource_max = dpy->resource_mask + 1; 15871ab64890Smrg } 15881ab64890Smrg if (id <= dpy->resource_mask) { 15891ab64890Smrg dpy->resource_id++; 15901ab64890Smrg return (dpy->resource_base + id); 15911ab64890Smrg } 15921ab64890Smrg if (id != 0x10000000) { 15931ab64890Smrg (void) fprintf(stderr, 15941ab64890Smrg "Xlib: resource ID allocation space exhausted!\n"); 15951ab64890Smrg id = 0x10000000; 15961ab64890Smrg dpy->resource_id = id >> dpy->resource_shift; 15971ab64890Smrg } 15981ab64890Smrg return id; 15991ab64890Smrg} 16001ab64890Smrg 16011ab64890Smrg/* 16021ab64890Smrg * _XAllocIDs - multiple resource ID allocation routine. 16031ab64890Smrg */ 16041ab64890Smrgvoid _XAllocIDs( 16051ab64890Smrg register Display *dpy, 16061ab64890Smrg XID *ids, 16071ab64890Smrg int count) 16081ab64890Smrg{ 16091ab64890Smrg XID id; 16101ab64890Smrg int i; 16111ab64890Smrg xXCMiscGetXIDListReply grep; 16121ab64890Smrg register xXCMiscGetXIDListReq *greq; 16131ab64890Smrg 16141ab64890Smrg id = dpy->resource_id << dpy->resource_shift; 16151ab64890Smrg if (dpy->resource_max <= dpy->resource_mask && 16161ab64890Smrg id <= dpy->resource_mask && 16171ab64890Smrg (dpy->resource_max - id) > ((count - 1) << dpy->resource_shift)) { 16181ab64890Smrg id += dpy->resource_base; 16191ab64890Smrg for (i = 0; i < count; i++) { 16201ab64890Smrg ids[i] = id; 16211ab64890Smrg id += (1 << dpy->resource_shift); 16221ab64890Smrg dpy->resource_id++; 16231ab64890Smrg } 16241ab64890Smrg return; 16251ab64890Smrg } 16261ab64890Smrg grep.count = 0; 16271ab64890Smrg _XGetMiscCode(dpy); 16281ab64890Smrg if (dpy->xcmisc_opcode > 0) { 16291ab64890Smrg GetReq(XCMiscGetXIDList, greq); 16301ab64890Smrg greq->reqType = dpy->xcmisc_opcode; 16311ab64890Smrg greq->miscReqType = X_XCMiscGetXIDList; 16321ab64890Smrg greq->count = count; 16331ab64890Smrg if (_XReply(dpy, (xReply *)&grep, 0, xFalse) && grep.count) { 16341ab64890Smrg _XRead32(dpy, (long *) ids, 4L * (long) (grep.count)); 16351ab64890Smrg for (i = 0; i < grep.count; i++) { 16361ab64890Smrg id = (ids[i] - dpy->resource_base) >> dpy->resource_shift; 16371ab64890Smrg if (id >= dpy->resource_id) 16381ab64890Smrg dpy->resource_id = id; 16391ab64890Smrg } 16401ab64890Smrg if (id >= dpy->resource_max) { 164161b2299dSmrg _XSetPrivSyncFunction(dpy); 16421ab64890Smrg dpy->resource_max = dpy->resource_mask + 1; 16431ab64890Smrg } 16441ab64890Smrg } 16451ab64890Smrg } 16461ab64890Smrg for (i = grep.count; i < count; i++) 16471ab64890Smrg ids[i] = XAllocID(dpy); 16481ab64890Smrg} 16491ab64890Smrg#endif /* !USE_XCB */ 16501ab64890Smrg 16511ab64890Smrg/* 16521ab64890Smrg * The hard part about this is that we only get 16 bits from a reply. 16531ab64890Smrg * We have three values that will march along, with the following invariant: 16541ab64890Smrg * dpy->last_request_read <= rep->sequenceNumber <= dpy->request 16551ab64890Smrg * We have to keep 16561ab64890Smrg * dpy->request - dpy->last_request_read < 2^16 16571ab64890Smrg * or else we won't know for sure what value to use in events. We do this 16581ab64890Smrg * by forcing syncs when we get close. 16591ab64890Smrg */ 16601ab64890Smrg 16611ab64890Smrgunsigned long 16621ab64890Smrg_XSetLastRequestRead( 16631ab64890Smrg register Display *dpy, 16641ab64890Smrg register xGenericReply *rep) 16651ab64890Smrg{ 16661ab64890Smrg register unsigned long newseq, lastseq; 16671ab64890Smrg 16681ab64890Smrg lastseq = dpy->last_request_read; 16691ab64890Smrg /* 16701ab64890Smrg * KeymapNotify has no sequence number, but is always guaranteed 16711ab64890Smrg * to immediately follow another event, except when generated via 16721ab64890Smrg * SendEvent (hmmm). 16731ab64890Smrg */ 16741ab64890Smrg if ((rep->type & 0x7f) == KeymapNotify) 16751ab64890Smrg return(lastseq); 16761ab64890Smrg 16771ab64890Smrg newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber; 16781ab64890Smrg 16791ab64890Smrg if (newseq < lastseq) { 16801ab64890Smrg newseq += 0x10000; 16811ab64890Smrg if (newseq > dpy->request) { 168261b2299dSmrg (void) fprintf (stderr, 16831ab64890Smrg "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", 168461b2299dSmrg newseq, dpy->request, 16851ab64890Smrg (unsigned int) rep->type); 16861ab64890Smrg newseq -= 0x10000; 16871ab64890Smrg } 16881ab64890Smrg } 16891ab64890Smrg 16901ab64890Smrg dpy->last_request_read = newseq; 16911ab64890Smrg return(newseq); 16921ab64890Smrg} 16931ab64890Smrg 16941ab64890Smrg#if !USE_XCB 16951ab64890Smrg/* 16961ab64890Smrg * _XReply - Wait for a reply packet and copy its contents into the 16971ab64890Smrg * specified rep. Meanwhile we must handle error and event packets that 16981ab64890Smrg * we may encounter. 16991ab64890Smrg */ 17001ab64890SmrgStatus 17011ab64890Smrg_XReply ( 17021ab64890Smrg register Display *dpy, 17031ab64890Smrg register xReply *rep, 17041ab64890Smrg int extra, /* number of 32-bit words expected after the reply */ 17051ab64890Smrg Bool discard) /* should I discard data following "extra" words? */ 17061ab64890Smrg{ 17071ab64890Smrg /* Pull out the serial number now, so that (currently illegal) requests 17081ab64890Smrg * generated by an error handler don't confuse us. 17091ab64890Smrg */ 17101ab64890Smrg unsigned long cur_request = dpy->request; 17111ab64890Smrg#ifdef XTHREADS 17121ab64890Smrg struct _XCVList *cvl; 17131ab64890Smrg#endif 17141ab64890Smrg 17151ab64890Smrg if (dpy->flags & XlibDisplayIOError) 17161ab64890Smrg return 0; 17171ab64890Smrg 17181ab64890Smrg#ifdef XTHREADS 17191ab64890Smrg /* create our condition variable and append to list */ 17201ab64890Smrg cvl = QueueReplyReaderLock(dpy); 17211ab64890Smrg if (cvl) { 17221ab64890Smrg cvl->buf = rep; 17231ab64890Smrg if (dpy->lock->reply_awaiters == cvl && !dpy->lock->event_awaiters) 17241ab64890Smrg dpy->lock->reply_first = True; 17251ab64890Smrg } 17261ab64890Smrg 17271ab64890Smrg#ifdef XTHREADS_DEBUG 17281ab64890Smrg printf("_XReply called in thread %x, adding %x to cvl\n", 17291ab64890Smrg XThread_Self(), cvl); 17301ab64890Smrg#endif 17311ab64890Smrg 17321ab64890Smrg _XFlushInt(dpy, cvl ? cvl->cv : NULL); 17331ab64890Smrg /* if it is not our turn to read a reply off the wire, 17341ab64890Smrg * wait til we're at head of list. if there is an event waiter, 17351ab64890Smrg * and our reply hasn't been read, they'll be in select and will 17361ab64890Smrg * hand control back to us next. 17371ab64890Smrg */ 17381ab64890Smrg if(dpy->lock && 17391ab64890Smrg (dpy->lock->reply_awaiters != cvl || !dpy->lock->reply_first)) { 17401ab64890Smrg ConditionWait(dpy, cvl->cv); 17411ab64890Smrg } 17421ab64890Smrg dpy->flags |= XlibDisplayReply; 17431ab64890Smrg#else /* XTHREADS else */ 17441ab64890Smrg _XFlush(dpy); 17451ab64890Smrg#endif 17461ab64890Smrg 17471ab64890Smrg for (;;) { 17481ab64890Smrg#ifdef XTHREADS 17491ab64890Smrg /* Did another thread's _XReadEvents get our reply by accident? */ 17501ab64890Smrg if (!dpy->lock || !dpy->lock->reply_was_read) 17511ab64890Smrg#endif 17521ab64890Smrg (void) _XRead(dpy, (char *)rep, (long)SIZEOF(xReply)); 17531ab64890Smrg#ifdef XTHREADS 17541ab64890Smrg if (dpy->lock) 17551ab64890Smrg dpy->lock->reply_was_read = False; 17561ab64890Smrg#endif 17571ab64890Smrg 17581ab64890Smrg switch ((int)rep->generic.type) { 17591ab64890Smrg 17601ab64890Smrg case X_Reply: 17611ab64890Smrg /* Reply received. Fast update for synchronous replies, 17621ab64890Smrg * but deal with multiple outstanding replies. 17631ab64890Smrg */ 17641ab64890Smrg if (rep->generic.sequenceNumber == (cur_request & 0xffff)) 17651ab64890Smrg dpy->last_request_read = cur_request; 17661ab64890Smrg else { 17671ab64890Smrg int pend = SIZEOF(xReply); 17681ab64890Smrg if (_XAsyncReply(dpy, rep, (char *)rep, &pend, False) 17691ab64890Smrg != (char *)rep) 17701ab64890Smrg continue; 17711ab64890Smrg } 17721ab64890Smrg if (extra <= rep->generic.length) { 17731ab64890Smrg if (extra > 0) 177461b2299dSmrg /* 17751ab64890Smrg * Read the extra data into storage immediately 177661b2299dSmrg * following the GenericReply structure. 17771ab64890Smrg */ 17781ab64890Smrg (void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)), 17791ab64890Smrg ((long)extra) << 2); 17801ab64890Smrg if (discard) { 17811ab64890Smrg if (extra < rep->generic.length) 17821ab64890Smrg _XEatData(dpy, (rep->generic.length - extra) << 2); 17831ab64890Smrg } 17841ab64890Smrg#ifdef XTHREADS 17851ab64890Smrg if (dpy->lock) { 17861ab64890Smrg if (discard) { 17871ab64890Smrg dpy->lock->reply_bytes_left = 0; 17881ab64890Smrg } else { 17891ab64890Smrg dpy->lock->reply_bytes_left = 17901ab64890Smrg (rep->generic.length - extra) << 2; 17911ab64890Smrg } 17921ab64890Smrg if (dpy->lock->reply_bytes_left == 0) { 17931ab64890Smrg dpy->flags &= ~XlibDisplayReply; 17941ab64890Smrg UnlockNextReplyReader(dpy); 17951ab64890Smrg } 17961ab64890Smrg } else 17971ab64890Smrg dpy->flags &= ~XlibDisplayReply; 17981ab64890Smrg#endif 17991ab64890Smrg return 1; 18001ab64890Smrg } 180161b2299dSmrg /* 18021ab64890Smrg *if we get here, then extra > rep->generic.length--meaning we 180361b2299dSmrg * read a reply that's shorter than we expected. This is an 18041ab64890Smrg * error, but we still need to figure out how to handle it... 18051ab64890Smrg */ 18061ab64890Smrg (void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)), 18071ab64890Smrg ((long) rep->generic.length) << 2); 18081ab64890Smrg dpy->flags &= ~XlibDisplayReply; 18091ab64890Smrg UnlockNextReplyReader(dpy); 18101ab64890Smrg _XIOError (dpy); 18111ab64890Smrg return (0); 18121ab64890Smrg 18131ab64890Smrg case X_Error: 18141ab64890Smrg { 18151ab64890Smrg register _XExtension *ext; 18161ab64890Smrg register Bool ret = False; 18171ab64890Smrg int ret_code; 18181ab64890Smrg xError *err = (xError *) rep; 18191ab64890Smrg unsigned long serial; 18201ab64890Smrg 18211ab64890Smrg dpy->flags &= ~XlibDisplayReply; 18221ab64890Smrg serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); 18231ab64890Smrg if (serial == cur_request) 18241ab64890Smrg /* do not die on "no such font", "can't allocate", 18251ab64890Smrg "can't grab" failures */ 18261ab64890Smrg switch ((int)err->errorCode) { 18271ab64890Smrg case BadName: 18281ab64890Smrg switch (err->majorCode) { 18291ab64890Smrg case X_LookupColor: 18301ab64890Smrg case X_AllocNamedColor: 18311ab64890Smrg UnlockNextReplyReader(dpy); 18321ab64890Smrg return(0); 18331ab64890Smrg } 18341ab64890Smrg break; 18351ab64890Smrg case BadFont: 18361ab64890Smrg if (err->majorCode == X_QueryFont) { 18371ab64890Smrg UnlockNextReplyReader(dpy); 18381ab64890Smrg return (0); 18391ab64890Smrg } 18401ab64890Smrg break; 18411ab64890Smrg case BadAlloc: 18421ab64890Smrg case BadAccess: 18431ab64890Smrg UnlockNextReplyReader(dpy); 18441ab64890Smrg return (0); 18451ab64890Smrg } 184661b2299dSmrg /* 18471ab64890Smrg * we better see if there is an extension who may 18481ab64890Smrg * want to suppress the error. 18491ab64890Smrg */ 18501ab64890Smrg for (ext = dpy->ext_procs; !ret && ext; ext = ext->next) { 185161b2299dSmrg if (ext->error) 18521ab64890Smrg ret = (*ext->error)(dpy, err, &ext->codes, &ret_code); 18531ab64890Smrg } 18541ab64890Smrg if (!ret) { 18551ab64890Smrg _XError(dpy, err); 18561ab64890Smrg ret_code = 0; 18571ab64890Smrg } 18581ab64890Smrg if (serial == cur_request) { 18591ab64890Smrg UnlockNextReplyReader(dpy); 18601ab64890Smrg return(ret_code); 18611ab64890Smrg } 18621ab64890Smrg 18631ab64890Smrg } /* case X_Error */ 18641ab64890Smrg break; 18651ab64890Smrg default: 18661ab64890Smrg _XEnq(dpy, (xEvent *) rep); 18671ab64890Smrg#ifdef XTHREADS 18681ab64890Smrg if (dpy->lock && dpy->lock->event_awaiters) 18691ab64890Smrg ConditionSignal(dpy, dpy->lock->event_awaiters->cv); 18701ab64890Smrg#endif 18711ab64890Smrg break; 18721ab64890Smrg } 18731ab64890Smrg } 187461b2299dSmrg} 18751ab64890Smrg 18761ab64890Smrgstatic char * 18771ab64890Smrg_XAsyncReply( 18781ab64890Smrg Display *dpy, 18791ab64890Smrg register xReply *rep, 18801ab64890Smrg char *buf, 18811ab64890Smrg register int *lenp, 18821ab64890Smrg Bool discard) 18831ab64890Smrg{ 18841ab64890Smrg register _XAsyncHandler *async, *next; 18851ab64890Smrg register int len; 18861ab64890Smrg register Bool consumed = False; 18871ab64890Smrg char *nbuf; 18881ab64890Smrg 18891ab64890Smrg (void) _XSetLastRequestRead(dpy, &rep->generic); 18901ab64890Smrg len = SIZEOF(xReply) + (rep->generic.length << 2); 18911ab64890Smrg if (len < SIZEOF(xReply)) { 18921ab64890Smrg _XIOError (dpy); 18931ab64890Smrg buf += *lenp; 18941ab64890Smrg *lenp = 0; 18951ab64890Smrg return buf; 18961ab64890Smrg } 189761b2299dSmrg 18981ab64890Smrg for (async = dpy->async_handlers; async; async = next) { 18991ab64890Smrg next = async->next; 19001ab64890Smrg if ((consumed = (*async->handler)(dpy, rep, buf, *lenp, async->data))) 19011ab64890Smrg break; 19021ab64890Smrg } 19031ab64890Smrg if (!consumed) { 19041ab64890Smrg if (!discard) 19051ab64890Smrg return buf; 190661b2299dSmrg (void) fprintf(stderr, 19071ab64890Smrg "Xlib: unexpected async reply (sequence 0x%lx)!\n", 19081ab64890Smrg dpy->last_request_read); 19091ab64890Smrg#ifdef XTHREADS 19101ab64890Smrg#ifdef XTHREADS_DEBUG 19111ab64890Smrg printf("thread %x, unexpected async reply\n", XThread_Self()); 19121ab64890Smrg#endif 19131ab64890Smrg#endif 19141ab64890Smrg if (len > *lenp) 19151ab64890Smrg _XEatData(dpy, len - *lenp); 19161ab64890Smrg } 19171ab64890Smrg if (len < SIZEOF(xReply)) 19181ab64890Smrg { 19191ab64890Smrg _XIOError (dpy); 19201ab64890Smrg buf += *lenp; 19211ab64890Smrg *lenp = 0; 19221ab64890Smrg return buf; 19231ab64890Smrg } 19241ab64890Smrg if (len >= *lenp) { 19251ab64890Smrg buf += *lenp; 19261ab64890Smrg *lenp = 0; 19271ab64890Smrg return buf; 19281ab64890Smrg } 19291ab64890Smrg *lenp -= len; 19301ab64890Smrg buf += len; 19311ab64890Smrg len = *lenp; 19321ab64890Smrg nbuf = buf; 19331ab64890Smrg while (len > SIZEOF(xReply)) { 19341ab64890Smrg if (*buf == X_Reply) 19351ab64890Smrg return nbuf; 19361ab64890Smrg buf += SIZEOF(xReply); 19371ab64890Smrg len -= SIZEOF(xReply); 19381ab64890Smrg } 19391ab64890Smrg if (len > 0 && len < SIZEOF(xReply)) { 19401ab64890Smrg buf = nbuf; 19411ab64890Smrg len = SIZEOF(xReply) - len; 19421ab64890Smrg nbuf -= len; 19431ab64890Smrg memmove(nbuf, buf, *lenp); 19441ab64890Smrg (void) _XRead(dpy, nbuf + *lenp, (long)len); 19451ab64890Smrg *lenp += len; 19461ab64890Smrg } 19471ab64890Smrg return nbuf; 19481ab64890Smrg} 19491ab64890Smrg#endif /* !USE_XCB */ 19501ab64890Smrg 19511ab64890Smrg/* 19521ab64890Smrg * Support for internal connections, such as an IM might use. 19531ab64890Smrg * By Stephen Gildea, X Consortium, September 1993 19541ab64890Smrg */ 19551ab64890Smrg 19561ab64890Smrg/* _XRegisterInternalConnection 19571ab64890Smrg * Each IM (or Xlib extension) that opens a file descriptor that Xlib should 19581ab64890Smrg * include in its select/poll mask must call this function to register the 19591ab64890Smrg * fd with Xlib. Any XConnectionWatchProc registered by XAddConnectionWatch 19601ab64890Smrg * will also be called. 19611ab64890Smrg * 19621ab64890Smrg * Whenever Xlib detects input available on fd, it will call callback 19631ab64890Smrg * with call_data to process it. If non-Xlib code calls select/poll 19641ab64890Smrg * and detects input available, it must call XProcessInternalConnection, 19651ab64890Smrg * which will call the associated callback. 19661ab64890Smrg * 19671ab64890Smrg * Non-Xlib code can learn about these additional fds by calling 19681ab64890Smrg * XInternalConnectionNumbers or, more typically, by registering 19691ab64890Smrg * a XConnectionWatchProc with XAddConnectionWatch 19701ab64890Smrg * to be called when fds are registered or unregistered. 19711ab64890Smrg * 19721ab64890Smrg * Returns True if registration succeeded, False if not, typically 19731ab64890Smrg * because could not allocate memory. 19741ab64890Smrg * Assumes Display locked when called. 19751ab64890Smrg */ 19761ab64890SmrgStatus 19771ab64890Smrg_XRegisterInternalConnection( 19781ab64890Smrg Display* dpy, 19791ab64890Smrg int fd, 19801ab64890Smrg _XInternalConnectionProc callback, 19811ab64890Smrg XPointer call_data 19821ab64890Smrg) 19831ab64890Smrg{ 19841ab64890Smrg struct _XConnectionInfo *new_conni, **iptr; 19851ab64890Smrg struct _XConnWatchInfo *watchers; 19861ab64890Smrg XPointer *wd; 19871ab64890Smrg 19881ab64890Smrg new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo)); 19891ab64890Smrg if (!new_conni) 19901ab64890Smrg return 0; 19911ab64890Smrg new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer)); 19921ab64890Smrg if (!new_conni->watch_data) { 19931ab64890Smrg Xfree(new_conni); 19941ab64890Smrg return 0; 19951ab64890Smrg } 19961ab64890Smrg new_conni->fd = fd; 19971ab64890Smrg new_conni->read_callback = callback; 19981ab64890Smrg new_conni->call_data = call_data; 19991ab64890Smrg new_conni->next = NULL; 20001ab64890Smrg /* link new structure onto end of list */ 20011ab64890Smrg for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next) 20021ab64890Smrg ; 20031ab64890Smrg *iptr = new_conni; 20041ab64890Smrg dpy->im_fd_length++; 20051ab64890Smrg _XPollfdCacheAdd(dpy, fd); 20061ab64890Smrg 20071ab64890Smrg for (watchers=dpy->conn_watchers, wd=new_conni->watch_data; 20081ab64890Smrg watchers; 20091ab64890Smrg watchers=watchers->next, wd++) { 20101ab64890Smrg *wd = NULL; /* for cleanliness */ 20111ab64890Smrg (*watchers->fn) (dpy, watchers->client_data, fd, True, wd); 20121ab64890Smrg } 20131ab64890Smrg 20141ab64890Smrg return 1; 20151ab64890Smrg} 20161ab64890Smrg 20171ab64890Smrg/* _XUnregisterInternalConnection 20181ab64890Smrg * Each IM (or Xlib extension) that closes a file descriptor previously 20191ab64890Smrg * registered with _XRegisterInternalConnection must call this function. 20201ab64890Smrg * Any XConnectionWatchProc registered by XAddConnectionWatch 20211ab64890Smrg * will also be called. 20221ab64890Smrg * 20231ab64890Smrg * Assumes Display locked when called. 20241ab64890Smrg */ 20251ab64890Smrgvoid 20261ab64890Smrg_XUnregisterInternalConnection( 20271ab64890Smrg Display* dpy, 20281ab64890Smrg int fd 20291ab64890Smrg) 20301ab64890Smrg{ 20311ab64890Smrg struct _XConnectionInfo *info_list, **prev; 20321ab64890Smrg struct _XConnWatchInfo *watch; 20331ab64890Smrg XPointer *wd; 20341ab64890Smrg 20351ab64890Smrg for (prev = &dpy->im_fd_info; (info_list = *prev); 20361ab64890Smrg prev = &info_list->next) { 20371ab64890Smrg if (info_list->fd == fd) { 20381ab64890Smrg *prev = info_list->next; 20391ab64890Smrg dpy->im_fd_length--; 20401ab64890Smrg for (watch=dpy->conn_watchers, wd=info_list->watch_data; 20411ab64890Smrg watch; 20421ab64890Smrg watch=watch->next, wd++) { 20431ab64890Smrg (*watch->fn) (dpy, watch->client_data, fd, False, wd); 20441ab64890Smrg } 20451ab64890Smrg if (info_list->watch_data) 20461ab64890Smrg Xfree (info_list->watch_data); 20471ab64890Smrg Xfree (info_list); 20481ab64890Smrg break; 20491ab64890Smrg } 20501ab64890Smrg } 20511ab64890Smrg _XPollfdCacheDel(dpy, fd); 20521ab64890Smrg} 20531ab64890Smrg 20541ab64890Smrg/* XInternalConnectionNumbers 20551ab64890Smrg * Returns an array of fds and an array of corresponding call data. 20561ab64890Smrg * Typically a XConnectionWatchProc registered with XAddConnectionWatch 20571ab64890Smrg * will be used instead of this function to discover 20581ab64890Smrg * additional fds to include in the select/poll mask. 20591ab64890Smrg * 20601ab64890Smrg * The list is allocated with Xmalloc and should be freed by the caller 20611ab64890Smrg * with Xfree; 20621ab64890Smrg */ 20631ab64890SmrgStatus 20641ab64890SmrgXInternalConnectionNumbers( 20651ab64890Smrg Display *dpy, 20661ab64890Smrg int **fd_return, 20671ab64890Smrg int *count_return 20681ab64890Smrg) 20691ab64890Smrg{ 20701ab64890Smrg int count; 20711ab64890Smrg struct _XConnectionInfo *info_list; 20721ab64890Smrg int *fd_list; 20731ab64890Smrg 20741ab64890Smrg LockDisplay(dpy); 20751ab64890Smrg count = 0; 20761ab64890Smrg for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) 20771ab64890Smrg count++; 20781ab64890Smrg fd_list = (int*) Xmalloc (count * sizeof(int)); 20791ab64890Smrg if (!fd_list) { 20801ab64890Smrg UnlockDisplay(dpy); 20811ab64890Smrg return 0; 20821ab64890Smrg } 20831ab64890Smrg count = 0; 20841ab64890Smrg for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 20851ab64890Smrg fd_list[count] = info_list->fd; 20861ab64890Smrg count++; 20871ab64890Smrg } 20881ab64890Smrg UnlockDisplay(dpy); 20891ab64890Smrg 20901ab64890Smrg *fd_return = fd_list; 20911ab64890Smrg *count_return = count; 20921ab64890Smrg return 1; 20931ab64890Smrg} 20941ab64890Smrg 20951ab64890Smrgvoid _XProcessInternalConnection( 20961ab64890Smrg Display *dpy, 20971ab64890Smrg struct _XConnectionInfo *conn_info) 20981ab64890Smrg{ 20991ab64890Smrg dpy->flags |= XlibDisplayProcConni; 21001ab64890Smrg#if defined(XTHREADS) && !USE_XCB 21011ab64890Smrg if (dpy->lock) { 21021ab64890Smrg /* check cache to avoid call to thread_self */ 21031ab64890Smrg if (xthread_have_id(dpy->lock->reading_thread)) 21041ab64890Smrg dpy->lock->conni_thread = dpy->lock->reading_thread; 21051ab64890Smrg else 21061ab64890Smrg dpy->lock->conni_thread = XThread_Self(); 21071ab64890Smrg } 21081ab64890Smrg#endif /* XTHREADS && !USE_XCB */ 21091ab64890Smrg UnlockDisplay(dpy); 21101ab64890Smrg (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data); 21111ab64890Smrg LockDisplay(dpy); 21121ab64890Smrg#if defined(XTHREADS) && !USE_XCB 21131ab64890Smrg if (dpy->lock) 21141ab64890Smrg xthread_clear_id(dpy->lock->conni_thread); 21151ab64890Smrg#endif /* XTHREADS && !USE_XCB */ 21161ab64890Smrg dpy->flags &= ~XlibDisplayProcConni; 21171ab64890Smrg} 21181ab64890Smrg 21191ab64890Smrg/* XProcessInternalConnection 21201ab64890Smrg * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection 21211ab64890Smrg * for this fd. 21221ab64890Smrg * The Display is NOT locked during the call. 21231ab64890Smrg */ 21241ab64890Smrgvoid 21251ab64890SmrgXProcessInternalConnection( 21261ab64890Smrg Display* dpy, 21271ab64890Smrg int fd 21281ab64890Smrg) 21291ab64890Smrg{ 21301ab64890Smrg struct _XConnectionInfo *info_list; 21311ab64890Smrg 21321ab64890Smrg LockDisplay(dpy); 21331ab64890Smrg for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 21341ab64890Smrg if (info_list->fd == fd) { 21351ab64890Smrg _XProcessInternalConnection(dpy, info_list); 21361ab64890Smrg break; 21371ab64890Smrg } 21381ab64890Smrg } 21391ab64890Smrg UnlockDisplay(dpy); 21401ab64890Smrg} 21411ab64890Smrg 21421ab64890Smrg/* XAddConnectionWatch 21431ab64890Smrg * Register a callback to be called whenever _XRegisterInternalConnection 21441ab64890Smrg * or _XUnregisterInternalConnection is called. 21451ab64890Smrg * Callbacks are called with the Display locked. 21461ab64890Smrg * If any connections are already registered, the callback is immediately 21471ab64890Smrg * called for each of them. 21481ab64890Smrg */ 21491ab64890SmrgStatus 21501ab64890SmrgXAddConnectionWatch( 21511ab64890Smrg Display* dpy, 21521ab64890Smrg XConnectionWatchProc callback, 21531ab64890Smrg XPointer client_data 21541ab64890Smrg) 21551ab64890Smrg{ 21561ab64890Smrg struct _XConnWatchInfo *new_watcher, **wptr; 21571ab64890Smrg struct _XConnectionInfo *info_list; 21581ab64890Smrg XPointer *wd_array; 21591ab64890Smrg 21601ab64890Smrg LockDisplay(dpy); 21611ab64890Smrg 21621ab64890Smrg /* allocate new watch data */ 21631ab64890Smrg for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 21641ab64890Smrg wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data, 21651ab64890Smrg (dpy->watcher_count + 1) * 21661ab64890Smrg sizeof(XPointer)); 21671ab64890Smrg if (!wd_array) { 21681ab64890Smrg UnlockDisplay(dpy); 21691ab64890Smrg return 0; 21701ab64890Smrg } 21711ab64890Smrg wd_array[dpy->watcher_count] = NULL; /* for cleanliness */ 21721ab64890Smrg } 21731ab64890Smrg 21741ab64890Smrg new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo)); 21751ab64890Smrg if (!new_watcher) { 21761ab64890Smrg UnlockDisplay(dpy); 21771ab64890Smrg return 0; 21781ab64890Smrg } 21791ab64890Smrg new_watcher->fn = callback; 21801ab64890Smrg new_watcher->client_data = client_data; 21811ab64890Smrg new_watcher->next = NULL; 21821ab64890Smrg 21831ab64890Smrg /* link new structure onto end of list */ 21841ab64890Smrg for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next) 21851ab64890Smrg ; 21861ab64890Smrg *wptr = new_watcher; 21871ab64890Smrg dpy->watcher_count++; 21881ab64890Smrg 21891ab64890Smrg /* call new watcher on all currently registered fds */ 21901ab64890Smrg for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { 21911ab64890Smrg (*callback) (dpy, client_data, info_list->fd, True, 21921ab64890Smrg info_list->watch_data + dpy->watcher_count - 1); 21931ab64890Smrg } 21941ab64890Smrg 21951ab64890Smrg UnlockDisplay(dpy); 21961ab64890Smrg return 1; 21971ab64890Smrg} 21981ab64890Smrg 21991ab64890Smrg/* XRemoveConnectionWatch 22001ab64890Smrg * Unregister a callback registered by XAddConnectionWatch. 22011ab64890Smrg * Both callback and client_data must match what was passed to 22021ab64890Smrg * XAddConnectionWatch. 220361b2299dSmrg */ 22041ab64890Smrgvoid 22051ab64890SmrgXRemoveConnectionWatch( 22061ab64890Smrg Display* dpy, 22071ab64890Smrg XConnectionWatchProc callback, 22081ab64890Smrg XPointer client_data 22091ab64890Smrg) 22101ab64890Smrg{ 22111ab64890Smrg struct _XConnWatchInfo *watch; 22121ab64890Smrg struct _XConnWatchInfo *previous = NULL; 22131ab64890Smrg struct _XConnectionInfo *conni; 22141ab64890Smrg int counter = 0; 22151ab64890Smrg 22161ab64890Smrg LockDisplay(dpy); 22171ab64890Smrg for (watch=dpy->conn_watchers; watch; watch=watch->next) { 22181ab64890Smrg if (watch->fn == callback && watch->client_data == client_data) { 22191ab64890Smrg if (previous) 22201ab64890Smrg previous->next = watch->next; 22211ab64890Smrg else 22221ab64890Smrg dpy->conn_watchers = watch->next; 22231ab64890Smrg Xfree (watch); 22241ab64890Smrg dpy->watcher_count--; 22251ab64890Smrg /* remove our watch_data for each connection */ 22261ab64890Smrg for (conni=dpy->im_fd_info; conni; conni=conni->next) { 22271ab64890Smrg /* don't bother realloc'ing; these arrays are small anyway */ 22281ab64890Smrg /* overlapping */ 22291ab64890Smrg memmove(conni->watch_data+counter, 22301ab64890Smrg conni->watch_data+counter+1, 22311ab64890Smrg dpy->watcher_count - counter); 22321ab64890Smrg } 22331ab64890Smrg break; 22341ab64890Smrg } 22351ab64890Smrg previous = watch; 22361ab64890Smrg counter++; 22371ab64890Smrg } 22381ab64890Smrg UnlockDisplay(dpy); 22391ab64890Smrg} 22401ab64890Smrg 22411ab64890Smrg/* end of internal connections support */ 22421ab64890Smrg 22431ab64890Smrg 22441ab64890Smrg#if !USE_XCB 22451ab64890Smrg/* Read and discard "n" 8-bit bytes of data */ 22461ab64890Smrg 22471ab64890Smrgvoid _XEatData( 22481ab64890Smrg Display *dpy, 22491ab64890Smrg register unsigned long n) 22501ab64890Smrg{ 22511ab64890Smrg#define SCRATCHSIZE 2048 22521ab64890Smrg char buf[SCRATCHSIZE]; 22531ab64890Smrg 22541ab64890Smrg while (n > 0) { 22551ab64890Smrg register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n; 22561ab64890Smrg (void) _XRead (dpy, buf, bytes_read); 22571ab64890Smrg n -= bytes_read; 22581ab64890Smrg } 22591ab64890Smrg#undef SCRATCHSIZE 22601ab64890Smrg} 22611ab64890Smrg#endif /* !USE_XCB */ 22621ab64890Smrg 2263b4ee4795Smrg/* Cookie jar implementation 2264b4ee4795Smrg dpy->cookiejar is a linked list. _XEnq receives the events but leaves 2265b4ee4795Smrg them in the normal EQ. _XStoreEvent returns the cookie event (minus 2266b4ee4795Smrg data pointer) and adds it to the cookiejar. _XDeq just removes 2267b4ee4795Smrg the entry like any other event but resets the data pointer for 2268b4ee4795Smrg cookie events (to avoid double-free, the memory is re-used by Xlib). 2269b4ee4795Smrg 2270b4ee4795Smrg _XFetchEventCookie (called from XGetEventData) removes a cookie from the 2271b4ee4795Smrg jar. _XFreeEventCookies removes all unclaimed cookies from the jar 2272b4ee4795Smrg (called by XNextEvent). 2273b4ee4795Smrg 2274b4ee4795Smrg _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the 2275b4ee4795Smrg normal EQ. 2276b4ee4795Smrg */ 2277b4ee4795Smrg 2278b4ee4795Smrg#include "utlist.h" 2279b4ee4795Smrgstruct stored_event { 2280b4ee4795Smrg XGenericEventCookie ev; 2281b4ee4795Smrg struct stored_event *prev; 2282b4ee4795Smrg struct stored_event *next; 2283b4ee4795Smrg}; 2284b4ee4795Smrg 2285b4ee4795SmrgBool 2286b4ee4795Smrg_XIsEventCookie(Display *dpy, XEvent *ev) 2287b4ee4795Smrg{ 2288b4ee4795Smrg return (ev->xcookie.type == GenericEvent && 2289b4ee4795Smrg dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL); 2290b4ee4795Smrg} 2291b4ee4795Smrg 2292b4ee4795Smrg/** 2293b4ee4795Smrg * Free all events in the event list. 2294b4ee4795Smrg */ 2295b4ee4795Smrgvoid 2296b4ee4795Smrg_XFreeEventCookies(Display *dpy) 2297b4ee4795Smrg{ 2298b4ee4795Smrg struct stored_event **head, *e, *tmp; 2299b4ee4795Smrg 2300b4ee4795Smrg if (!dpy->cookiejar) 2301b4ee4795Smrg return; 2302b4ee4795Smrg 2303b4ee4795Smrg head = (struct stored_event**)&dpy->cookiejar; 2304b4ee4795Smrg 2305b4ee4795Smrg DL_FOREACH_SAFE(*head, e, tmp) { 2306b4ee4795Smrg XFree(e->ev.data); 2307b4ee4795Smrg XFree(e); 2308b4ee4795Smrg if (dpy->cookiejar == e) 2309b4ee4795Smrg dpy->cookiejar = NULL; 2310b4ee4795Smrg } 2311b4ee4795Smrg} 2312b4ee4795Smrg 2313b4ee4795Smrg/** 2314b4ee4795Smrg * Add an event to the display's event list. This event must be freed on the 2315b4ee4795Smrg * next call to XNextEvent(). 2316b4ee4795Smrg */ 2317b4ee4795Smrgvoid 2318b4ee4795Smrg_XStoreEventCookie(Display *dpy, XEvent *event) 2319b4ee4795Smrg{ 2320b4ee4795Smrg XGenericEventCookie* cookie = &event->xcookie; 2321b4ee4795Smrg struct stored_event **head, *add; 2322b4ee4795Smrg 2323b4ee4795Smrg if (!_XIsEventCookie(dpy, event)) 2324b4ee4795Smrg return; 2325b4ee4795Smrg 2326b4ee4795Smrg head = (struct stored_event**)(&dpy->cookiejar); 2327b4ee4795Smrg 2328b4ee4795Smrg add = Xmalloc(sizeof(struct stored_event)); 2329b4ee4795Smrg if (!add) { 2330b4ee4795Smrg ESET(ENOMEM); 2331b4ee4795Smrg _XIOError(dpy); 2332b4ee4795Smrg } 2333b4ee4795Smrg add->ev = *cookie; 2334b4ee4795Smrg DL_APPEND(*head, add); 2335b4ee4795Smrg cookie->data = NULL; /* don't return data yet, must be claimed */ 2336b4ee4795Smrg} 2337b4ee4795Smrg 2338b4ee4795Smrg/** 2339b4ee4795Smrg * Return the event with the given cookie and remove it from the list. 2340b4ee4795Smrg */ 2341b4ee4795SmrgBool 2342b4ee4795Smrg_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev) 2343b4ee4795Smrg{ 2344b4ee4795Smrg Bool ret = False; 2345b4ee4795Smrg struct stored_event **head, *event; 2346b4ee4795Smrg head = (struct stored_event**)&dpy->cookiejar; 2347b4ee4795Smrg 2348b4ee4795Smrg if (!_XIsEventCookie(dpy, (XEvent*)ev)) 2349b4ee4795Smrg return ret; 2350b4ee4795Smrg 2351b4ee4795Smrg DL_FOREACH(*head, event) { 2352b4ee4795Smrg if (event->ev.cookie == ev->cookie && 2353b4ee4795Smrg event->ev.extension == ev->extension && 2354b4ee4795Smrg event->ev.evtype == ev->evtype) { 2355b4ee4795Smrg *ev = event->ev; 2356b4ee4795Smrg DL_DELETE(*head, event); 2357b4ee4795Smrg Xfree(event); 2358b4ee4795Smrg ret = True; 2359b4ee4795Smrg break; 2360b4ee4795Smrg } 2361b4ee4795Smrg } 2362b4ee4795Smrg 2363b4ee4795Smrg return ret; 2364b4ee4795Smrg} 2365b4ee4795Smrg 2366b4ee4795SmrgBool 2367b4ee4795Smrg_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) 2368b4ee4795Smrg{ 2369b4ee4795Smrg Bool ret = False; 2370b4ee4795Smrg int extension; 2371b4ee4795Smrg 2372b4ee4795Smrg if (!_XIsEventCookie(dpy, (XEvent*)in) || !out) 2373b4ee4795Smrg return ret; 2374b4ee4795Smrg 2375b4ee4795Smrg extension = in->extension & 0x7F; 2376b4ee4795Smrg 2377b4ee4795Smrg if (!dpy->generic_event_copy_vec[extension]) 2378b4ee4795Smrg return ret; 2379b4ee4795Smrg 2380b4ee4795Smrg ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out)); 2381b4ee4795Smrg out->cookie = ret ? ++dpy->next_cookie : 0; 2382b4ee4795Smrg return ret; 2383b4ee4795Smrg} 2384b4ee4795Smrg 23851ab64890Smrg 23861ab64890Smrg/* 23871ab64890Smrg * _XEnq - Place event packets on the display's queue. 23881ab64890Smrg * note that no squishing of move events in V11, since there 23891ab64890Smrg * is pointer motion hints.... 23901ab64890Smrg */ 23911ab64890Smrgvoid _XEnq( 23921ab64890Smrg register Display *dpy, 23931ab64890Smrg register xEvent *event) 23941ab64890Smrg{ 23951ab64890Smrg register _XQEvent *qelt; 2396b4ee4795Smrg int type, extension; 23971ab64890Smrg 23981ab64890Smrg if ((qelt = dpy->qfree)) { 23991ab64890Smrg /* If dpy->qfree is non-NULL do this, else malloc a new one. */ 24001ab64890Smrg dpy->qfree = qelt->next; 24011ab64890Smrg } 240261b2299dSmrg else if ((qelt = 24031ab64890Smrg (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { 24041ab64890Smrg /* Malloc call failed! */ 24051ab64890Smrg ESET(ENOMEM); 24061ab64890Smrg _XIOError(dpy); 24071ab64890Smrg } 24081ab64890Smrg qelt->next = NULL; 2409b4ee4795Smrg 2410b4ee4795Smrg type = event->u.u.type & 0177; 2411b4ee4795Smrg extension = ((xGenericEvent*)event)->extension; 2412b4ee4795Smrg /* If an extension has registerd a generic_event_vec handler, then 2413b4ee4795Smrg * it can handle event cookies. Otherwise, proceed with the normal 2414b4ee4795Smrg * event handlers. 2415b4ee4795Smrg * 2416b4ee4795Smrg * If the generic_event_vec is called, qelt->event is a event cookie 2417b4ee4795Smrg * with the data pointer and the "free" pointer set. Data pointer is 2418b4ee4795Smrg * some memory allocated by the extension. 2419b4ee4795Smrg */ 2420b4ee4795Smrg if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) { 2421b4ee4795Smrg XGenericEventCookie *cookie = &qelt->event.xcookie; 2422b4ee4795Smrg (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event); 2423b4ee4795Smrg cookie->cookie = ++dpy->next_cookie; 2424b4ee4795Smrg 2425b4ee4795Smrg qelt->qserial_num = dpy->next_event_serial_num++; 2426b4ee4795Smrg if (dpy->tail) dpy->tail->next = qelt; 2427b4ee4795Smrg else dpy->head = qelt; 2428b4ee4795Smrg 2429b4ee4795Smrg dpy->tail = qelt; 2430b4ee4795Smrg dpy->qlen++; 2431b4ee4795Smrg } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) { 24321ab64890Smrg qelt->qserial_num = dpy->next_event_serial_num++; 24331ab64890Smrg if (dpy->tail) dpy->tail->next = qelt; 24341ab64890Smrg else dpy->head = qelt; 243561b2299dSmrg 24361ab64890Smrg dpy->tail = qelt; 24371ab64890Smrg dpy->qlen++; 24381ab64890Smrg } else { 24391ab64890Smrg /* ignored, or stashed away for many-to-one compression */ 24401ab64890Smrg qelt->next = dpy->qfree; 24411ab64890Smrg dpy->qfree = qelt; 24421ab64890Smrg } 24431ab64890Smrg} 24441ab64890Smrg 24451ab64890Smrg/* 24461ab64890Smrg * _XDeq - Remove event packet from the display's queue. 24471ab64890Smrg */ 24481ab64890Smrgvoid _XDeq( 24491ab64890Smrg register Display *dpy, 24501ab64890Smrg register _XQEvent *prev, /* element before qelt */ 24511ab64890Smrg register _XQEvent *qelt) /* element to be unlinked */ 24521ab64890Smrg{ 24531ab64890Smrg if (prev) { 24541ab64890Smrg if ((prev->next = qelt->next) == NULL) 24551ab64890Smrg dpy->tail = prev; 24561ab64890Smrg } else { 24571ab64890Smrg /* no prev, so removing first elt */ 24581ab64890Smrg if ((dpy->head = qelt->next) == NULL) 24591ab64890Smrg dpy->tail = NULL; 24601ab64890Smrg } 24611ab64890Smrg qelt->qserial_num = 0; 24621ab64890Smrg qelt->next = dpy->qfree; 24631ab64890Smrg dpy->qfree = qelt; 24641ab64890Smrg dpy->qlen--; 2465b4ee4795Smrg 2466b4ee4795Smrg if (_XIsEventCookie(dpy, &qelt->event)) { 2467b4ee4795Smrg XGenericEventCookie* cookie = &qelt->event.xcookie; 2468b4ee4795Smrg /* dpy->qfree is re-used, reset memory to avoid double free on 2469b4ee4795Smrg * _XFreeDisplayStructure */ 2470b4ee4795Smrg cookie->data = NULL; 2471b4ee4795Smrg } 24721ab64890Smrg} 24731ab64890Smrg 24741ab64890Smrg/* 24751ab64890Smrg * EventToWire in separate file in that often not needed. 24761ab64890Smrg */ 24771ab64890Smrg 24781ab64890Smrg/*ARGSUSED*/ 24791ab64890SmrgBool 24801ab64890Smrg_XUnknownWireEvent( 24811ab64890Smrg register Display *dpy, /* pointer to display structure */ 24821ab64890Smrg register XEvent *re, /* pointer to where event should be reformatted */ 24831ab64890Smrg register xEvent *event) /* wire protocol event */ 24841ab64890Smrg{ 24851ab64890Smrg#ifdef notdef 248661b2299dSmrg (void) fprintf(stderr, 24871ab64890Smrg "Xlib: unhandled wire event! event number = %d, display = %x\n.", 24881ab64890Smrg event->u.u.type, dpy); 24891ab64890Smrg#endif 24901ab64890Smrg return(False); 24911ab64890Smrg} 24921ab64890Smrg 2493b4ee4795SmrgBool 2494b4ee4795Smrg_XUnknownWireEventCookie( 2495b4ee4795Smrg Display *dpy, /* pointer to display structure */ 2496b4ee4795Smrg XGenericEventCookie *re, /* pointer to where event should be reformatted */ 2497b4ee4795Smrg xEvent *event) /* wire protocol event */ 2498b4ee4795Smrg{ 2499b4ee4795Smrg#ifdef notdef 2500b4ee4795Smrg fprintf(stderr, 2501b4ee4795Smrg "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.", 2502b4ee4795Smrg ((xGenericEvent*)event)->extension, dpy); 2503b4ee4795Smrg#endif 2504b4ee4795Smrg return(False); 2505b4ee4795Smrg} 2506b4ee4795Smrg 2507b4ee4795SmrgBool 2508b4ee4795Smrg_XUnknownCopyEventCookie( 2509b4ee4795Smrg Display *dpy, /* pointer to display structure */ 2510b4ee4795Smrg XGenericEventCookie *in, /* source */ 2511b4ee4795Smrg XGenericEventCookie *out) /* destination */ 2512b4ee4795Smrg{ 2513b4ee4795Smrg#ifdef notdef 2514b4ee4795Smrg fprintf(stderr, 2515b4ee4795Smrg "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.", 2516b4ee4795Smrg in->extension, dpy); 2517b4ee4795Smrg#endif 2518b4ee4795Smrg return(False); 2519b4ee4795Smrg} 2520b4ee4795Smrg 25211ab64890Smrg/*ARGSUSED*/ 25221ab64890SmrgStatus 25231ab64890Smrg_XUnknownNativeEvent( 25241ab64890Smrg register Display *dpy, /* pointer to display structure */ 25251ab64890Smrg register XEvent *re, /* pointer to where event should be reformatted */ 25261ab64890Smrg register xEvent *event) /* wire protocol event */ 25271ab64890Smrg{ 25281ab64890Smrg#ifdef notdef 252961b2299dSmrg (void) fprintf(stderr, 25301ab64890Smrg "Xlib: unhandled native event! event number = %d, display = %x\n.", 25311ab64890Smrg re->type, dpy); 25321ab64890Smrg#endif 25331ab64890Smrg return(0); 25341ab64890Smrg} 25351ab64890Smrg/* 25361ab64890Smrg * reformat a wire event into an XEvent structure of the right type. 25371ab64890Smrg */ 25381ab64890SmrgBool 25391ab64890Smrg_XWireToEvent( 25401ab64890Smrg register Display *dpy, /* pointer to display structure */ 25411ab64890Smrg register XEvent *re, /* pointer to where event should be reformatted */ 25421ab64890Smrg register xEvent *event) /* wire protocol event */ 25431ab64890Smrg{ 25441ab64890Smrg 25451ab64890Smrg re->type = event->u.u.type & 0x7f; 25461ab64890Smrg ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy, 25471ab64890Smrg (xGenericReply *)event); 25481ab64890Smrg ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); 25491ab64890Smrg ((XAnyEvent *)re)->display = dpy; 255061b2299dSmrg 25511ab64890Smrg /* Ignore the leading bit of the event type since it is set when a 25521ab64890Smrg client sends an event rather than the server. */ 25531ab64890Smrg 25541ab64890Smrg switch (event-> u.u.type & 0177) { 25551ab64890Smrg case KeyPress: 25561ab64890Smrg case KeyRelease: 25571ab64890Smrg { 25581ab64890Smrg register XKeyEvent *ev = (XKeyEvent*) re; 25591ab64890Smrg ev->root = event->u.keyButtonPointer.root; 25601ab64890Smrg ev->window = event->u.keyButtonPointer.event; 25611ab64890Smrg ev->subwindow = event->u.keyButtonPointer.child; 25621ab64890Smrg ev->time = event->u.keyButtonPointer.time; 25631ab64890Smrg ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 25641ab64890Smrg ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 25651ab64890Smrg ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 25661ab64890Smrg ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 25671ab64890Smrg ev->state = event->u.keyButtonPointer.state; 25681ab64890Smrg ev->same_screen = event->u.keyButtonPointer.sameScreen; 25691ab64890Smrg ev->keycode = event->u.u.detail; 25701ab64890Smrg } 25711ab64890Smrg break; 25721ab64890Smrg case ButtonPress: 25731ab64890Smrg case ButtonRelease: 25741ab64890Smrg { 25751ab64890Smrg register XButtonEvent *ev = (XButtonEvent *) re; 25761ab64890Smrg ev->root = event->u.keyButtonPointer.root; 25771ab64890Smrg ev->window = event->u.keyButtonPointer.event; 25781ab64890Smrg ev->subwindow = event->u.keyButtonPointer.child; 25791ab64890Smrg ev->time = event->u.keyButtonPointer.time; 25801ab64890Smrg ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 25811ab64890Smrg ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 25821ab64890Smrg ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 25831ab64890Smrg ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 25841ab64890Smrg ev->state = event->u.keyButtonPointer.state; 25851ab64890Smrg ev->same_screen = event->u.keyButtonPointer.sameScreen; 25861ab64890Smrg ev->button = event->u.u.detail; 25871ab64890Smrg } 25881ab64890Smrg break; 25891ab64890Smrg case MotionNotify: 25901ab64890Smrg { 25911ab64890Smrg register XMotionEvent *ev = (XMotionEvent *)re; 25921ab64890Smrg ev->root = event->u.keyButtonPointer.root; 25931ab64890Smrg ev->window = event->u.keyButtonPointer.event; 25941ab64890Smrg ev->subwindow = event->u.keyButtonPointer.child; 25951ab64890Smrg ev->time = event->u.keyButtonPointer.time; 25961ab64890Smrg ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); 25971ab64890Smrg ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); 25981ab64890Smrg ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); 25991ab64890Smrg ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); 26001ab64890Smrg ev->state = event->u.keyButtonPointer.state; 26011ab64890Smrg ev->same_screen = event->u.keyButtonPointer.sameScreen; 26021ab64890Smrg ev->is_hint = event->u.u.detail; 26031ab64890Smrg } 26041ab64890Smrg break; 26051ab64890Smrg case EnterNotify: 26061ab64890Smrg case LeaveNotify: 26071ab64890Smrg { 26081ab64890Smrg register XCrossingEvent *ev = (XCrossingEvent *) re; 26091ab64890Smrg ev->root = event->u.enterLeave.root; 26101ab64890Smrg ev->window = event->u.enterLeave.event; 26111ab64890Smrg ev->subwindow = event->u.enterLeave.child; 26121ab64890Smrg ev->time = event->u.enterLeave.time; 26131ab64890Smrg ev->x = cvtINT16toInt(event->u.enterLeave.eventX); 26141ab64890Smrg ev->y = cvtINT16toInt(event->u.enterLeave.eventY); 26151ab64890Smrg ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX); 26161ab64890Smrg ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY); 26171ab64890Smrg ev->state = event->u.enterLeave.state; 26181ab64890Smrg ev->mode = event->u.enterLeave.mode; 261961b2299dSmrg ev->same_screen = (event->u.enterLeave.flags & 26201ab64890Smrg ELFlagSameScreen) && True; 26211ab64890Smrg ev->focus = (event->u.enterLeave.flags & 26221ab64890Smrg ELFlagFocus) && True; 26231ab64890Smrg ev->detail = event->u.u.detail; 26241ab64890Smrg } 26251ab64890Smrg break; 26261ab64890Smrg case FocusIn: 26271ab64890Smrg case FocusOut: 26281ab64890Smrg { 26291ab64890Smrg register XFocusChangeEvent *ev = (XFocusChangeEvent *) re; 26301ab64890Smrg ev->window = event->u.focus.window; 26311ab64890Smrg ev->mode = event->u.focus.mode; 26321ab64890Smrg ev->detail = event->u.u.detail; 26331ab64890Smrg } 26341ab64890Smrg break; 26351ab64890Smrg case KeymapNotify: 26361ab64890Smrg { 26371ab64890Smrg register XKeymapEvent *ev = (XKeymapEvent *) re; 26381ab64890Smrg ev->window = None; 26391ab64890Smrg memcpy(&ev->key_vector[1], 26401ab64890Smrg (char *)((xKeymapEvent *) event)->map, 26411ab64890Smrg sizeof (((xKeymapEvent *) event)->map)); 26421ab64890Smrg } 26431ab64890Smrg break; 26441ab64890Smrg case Expose: 26451ab64890Smrg { 26461ab64890Smrg register XExposeEvent *ev = (XExposeEvent *) re; 26471ab64890Smrg ev->window = event->u.expose.window; 26481ab64890Smrg ev->x = event->u.expose.x; 26491ab64890Smrg ev->y = event->u.expose.y; 26501ab64890Smrg ev->width = event->u.expose.width; 26511ab64890Smrg ev->height = event->u.expose.height; 26521ab64890Smrg ev->count = event->u.expose.count; 26531ab64890Smrg } 26541ab64890Smrg break; 26551ab64890Smrg case GraphicsExpose: 26561ab64890Smrg { 26571ab64890Smrg register XGraphicsExposeEvent *ev = 26581ab64890Smrg (XGraphicsExposeEvent *) re; 26591ab64890Smrg ev->drawable = event->u.graphicsExposure.drawable; 26601ab64890Smrg ev->x = event->u.graphicsExposure.x; 26611ab64890Smrg ev->y = event->u.graphicsExposure.y; 26621ab64890Smrg ev->width = event->u.graphicsExposure.width; 26631ab64890Smrg ev->height = event->u.graphicsExposure.height; 26641ab64890Smrg ev->count = event->u.graphicsExposure.count; 26651ab64890Smrg ev->major_code = event->u.graphicsExposure.majorEvent; 26661ab64890Smrg ev->minor_code = event->u.graphicsExposure.minorEvent; 26671ab64890Smrg } 26681ab64890Smrg break; 26691ab64890Smrg case NoExpose: 26701ab64890Smrg { 26711ab64890Smrg register XNoExposeEvent *ev = (XNoExposeEvent *) re; 26721ab64890Smrg ev->drawable = event->u.noExposure.drawable; 26731ab64890Smrg ev->major_code = event->u.noExposure.majorEvent; 26741ab64890Smrg ev->minor_code = event->u.noExposure.minorEvent; 26751ab64890Smrg } 26761ab64890Smrg break; 26771ab64890Smrg case VisibilityNotify: 26781ab64890Smrg { 26791ab64890Smrg register XVisibilityEvent *ev = (XVisibilityEvent *) re; 26801ab64890Smrg ev->window = event->u.visibility.window; 26811ab64890Smrg ev->state = event->u.visibility.state; 26821ab64890Smrg } 26831ab64890Smrg break; 26841ab64890Smrg case CreateNotify: 26851ab64890Smrg { 26861ab64890Smrg register XCreateWindowEvent *ev = 26871ab64890Smrg (XCreateWindowEvent *) re; 26881ab64890Smrg ev->window = event->u.createNotify.window; 26891ab64890Smrg ev->parent = event->u.createNotify.parent; 26901ab64890Smrg ev->x = cvtINT16toInt(event->u.createNotify.x); 26911ab64890Smrg ev->y = cvtINT16toInt(event->u.createNotify.y); 26921ab64890Smrg ev->width = event->u.createNotify.width; 26931ab64890Smrg ev->height = event->u.createNotify.height; 26941ab64890Smrg ev->border_width = event->u.createNotify.borderWidth; 26951ab64890Smrg ev->override_redirect = event->u.createNotify.override; 26961ab64890Smrg } 26971ab64890Smrg break; 26981ab64890Smrg case DestroyNotify: 26991ab64890Smrg { 27001ab64890Smrg register XDestroyWindowEvent *ev = 27011ab64890Smrg (XDestroyWindowEvent *) re; 27021ab64890Smrg ev->window = event->u.destroyNotify.window; 27031ab64890Smrg ev->event = event->u.destroyNotify.event; 27041ab64890Smrg } 27051ab64890Smrg break; 27061ab64890Smrg case UnmapNotify: 27071ab64890Smrg { 27081ab64890Smrg register XUnmapEvent *ev = (XUnmapEvent *) re; 27091ab64890Smrg ev->window = event->u.unmapNotify.window; 27101ab64890Smrg ev->event = event->u.unmapNotify.event; 27111ab64890Smrg ev->from_configure = event->u.unmapNotify.fromConfigure; 27121ab64890Smrg } 27131ab64890Smrg break; 27141ab64890Smrg case MapNotify: 27151ab64890Smrg { 27161ab64890Smrg register XMapEvent *ev = (XMapEvent *) re; 27171ab64890Smrg ev->window = event->u.mapNotify.window; 27181ab64890Smrg ev->event = event->u.mapNotify.event; 27191ab64890Smrg ev->override_redirect = event->u.mapNotify.override; 27201ab64890Smrg } 27211ab64890Smrg break; 27221ab64890Smrg case MapRequest: 27231ab64890Smrg { 27241ab64890Smrg register XMapRequestEvent *ev = (XMapRequestEvent *) re; 27251ab64890Smrg ev->window = event->u.mapRequest.window; 27261ab64890Smrg ev->parent = event->u.mapRequest.parent; 27271ab64890Smrg } 27281ab64890Smrg break; 27291ab64890Smrg case ReparentNotify: 27301ab64890Smrg { 27311ab64890Smrg register XReparentEvent *ev = (XReparentEvent *) re; 27321ab64890Smrg ev->event = event->u.reparent.event; 27331ab64890Smrg ev->window = event->u.reparent.window; 27341ab64890Smrg ev->parent = event->u.reparent.parent; 27351ab64890Smrg ev->x = cvtINT16toInt(event->u.reparent.x); 27361ab64890Smrg ev->y = cvtINT16toInt(event->u.reparent.y); 27371ab64890Smrg ev->override_redirect = event->u.reparent.override; 27381ab64890Smrg } 27391ab64890Smrg break; 27401ab64890Smrg case ConfigureNotify: 27411ab64890Smrg { 27421ab64890Smrg register XConfigureEvent *ev = (XConfigureEvent *) re; 27431ab64890Smrg ev->event = event->u.configureNotify.event; 27441ab64890Smrg ev->window = event->u.configureNotify.window; 27451ab64890Smrg ev->above = event->u.configureNotify.aboveSibling; 27461ab64890Smrg ev->x = cvtINT16toInt(event->u.configureNotify.x); 27471ab64890Smrg ev->y = cvtINT16toInt(event->u.configureNotify.y); 27481ab64890Smrg ev->width = event->u.configureNotify.width; 27491ab64890Smrg ev->height = event->u.configureNotify.height; 27501ab64890Smrg ev->border_width = event->u.configureNotify.borderWidth; 27511ab64890Smrg ev->override_redirect = event->u.configureNotify.override; 27521ab64890Smrg } 27531ab64890Smrg break; 27541ab64890Smrg case ConfigureRequest: 27551ab64890Smrg { 27561ab64890Smrg register XConfigureRequestEvent *ev = 27571ab64890Smrg (XConfigureRequestEvent *) re; 27581ab64890Smrg ev->window = event->u.configureRequest.window; 27591ab64890Smrg ev->parent = event->u.configureRequest.parent; 27601ab64890Smrg ev->above = event->u.configureRequest.sibling; 27611ab64890Smrg ev->x = cvtINT16toInt(event->u.configureRequest.x); 27621ab64890Smrg ev->y = cvtINT16toInt(event->u.configureRequest.y); 27631ab64890Smrg ev->width = event->u.configureRequest.width; 27641ab64890Smrg ev->height = event->u.configureRequest.height; 27651ab64890Smrg ev->border_width = event->u.configureRequest.borderWidth; 27661ab64890Smrg ev->value_mask = event->u.configureRequest.valueMask; 27671ab64890Smrg ev->detail = event->u.u.detail; 27681ab64890Smrg } 27691ab64890Smrg break; 27701ab64890Smrg case GravityNotify: 27711ab64890Smrg { 27721ab64890Smrg register XGravityEvent *ev = (XGravityEvent *) re; 27731ab64890Smrg ev->window = event->u.gravity.window; 27741ab64890Smrg ev->event = event->u.gravity.event; 27751ab64890Smrg ev->x = cvtINT16toInt(event->u.gravity.x); 27761ab64890Smrg ev->y = cvtINT16toInt(event->u.gravity.y); 27771ab64890Smrg } 27781ab64890Smrg break; 27791ab64890Smrg case ResizeRequest: 27801ab64890Smrg { 27811ab64890Smrg register XResizeRequestEvent *ev = 27821ab64890Smrg (XResizeRequestEvent *) re; 27831ab64890Smrg ev->window = event->u.resizeRequest.window; 27841ab64890Smrg ev->width = event->u.resizeRequest.width; 27851ab64890Smrg ev->height = event->u.resizeRequest.height; 27861ab64890Smrg } 27871ab64890Smrg break; 27881ab64890Smrg case CirculateNotify: 27891ab64890Smrg { 27901ab64890Smrg register XCirculateEvent *ev = (XCirculateEvent *) re; 27911ab64890Smrg ev->window = event->u.circulate.window; 27921ab64890Smrg ev->event = event->u.circulate.event; 27931ab64890Smrg ev->place = event->u.circulate.place; 27941ab64890Smrg } 27951ab64890Smrg break; 27961ab64890Smrg case CirculateRequest: 27971ab64890Smrg { 27981ab64890Smrg register XCirculateRequestEvent *ev = 27991ab64890Smrg (XCirculateRequestEvent *) re; 28001ab64890Smrg ev->window = event->u.circulate.window; 28011ab64890Smrg ev->parent = event->u.circulate.event; 28021ab64890Smrg ev->place = event->u.circulate.place; 28031ab64890Smrg } 28041ab64890Smrg break; 28051ab64890Smrg case PropertyNotify: 28061ab64890Smrg { 28071ab64890Smrg register XPropertyEvent *ev = (XPropertyEvent *) re; 28081ab64890Smrg ev->window = event->u.property.window; 28091ab64890Smrg ev->atom = event->u.property.atom; 28101ab64890Smrg ev->time = event->u.property.time; 28111ab64890Smrg ev->state = event->u.property.state; 28121ab64890Smrg } 28131ab64890Smrg break; 28141ab64890Smrg case SelectionClear: 28151ab64890Smrg { 28161ab64890Smrg register XSelectionClearEvent *ev = 28171ab64890Smrg (XSelectionClearEvent *) re; 28181ab64890Smrg ev->window = event->u.selectionClear.window; 28191ab64890Smrg ev->selection = event->u.selectionClear.atom; 28201ab64890Smrg ev->time = event->u.selectionClear.time; 28211ab64890Smrg } 28221ab64890Smrg break; 28231ab64890Smrg case SelectionRequest: 28241ab64890Smrg { 28251ab64890Smrg register XSelectionRequestEvent *ev = 28261ab64890Smrg (XSelectionRequestEvent *) re; 28271ab64890Smrg ev->owner = event->u.selectionRequest.owner; 28281ab64890Smrg ev->requestor = event->u.selectionRequest.requestor; 28291ab64890Smrg ev->selection = event->u.selectionRequest.selection; 28301ab64890Smrg ev->target = event->u.selectionRequest.target; 28311ab64890Smrg ev->property = event->u.selectionRequest.property; 28321ab64890Smrg ev->time = event->u.selectionRequest.time; 28331ab64890Smrg } 28341ab64890Smrg break; 28351ab64890Smrg case SelectionNotify: 28361ab64890Smrg { 28371ab64890Smrg register XSelectionEvent *ev = (XSelectionEvent *) re; 28381ab64890Smrg ev->requestor = event->u.selectionNotify.requestor; 28391ab64890Smrg ev->selection = event->u.selectionNotify.selection; 28401ab64890Smrg ev->target = event->u.selectionNotify.target; 28411ab64890Smrg ev->property = event->u.selectionNotify.property; 28421ab64890Smrg ev->time = event->u.selectionNotify.time; 28431ab64890Smrg } 28441ab64890Smrg break; 28451ab64890Smrg case ColormapNotify: 28461ab64890Smrg { 28471ab64890Smrg register XColormapEvent *ev = (XColormapEvent *) re; 28481ab64890Smrg ev->window = event->u.colormap.window; 28491ab64890Smrg ev->colormap = event->u.colormap.colormap; 28501ab64890Smrg ev->new = event->u.colormap.new; 28511ab64890Smrg ev->state = event->u.colormap.state; 28521ab64890Smrg } 28531ab64890Smrg break; 28541ab64890Smrg case ClientMessage: 28551ab64890Smrg { 28561ab64890Smrg register int i; 285761b2299dSmrg register XClientMessageEvent *ev 28581ab64890Smrg = (XClientMessageEvent *) re; 28591ab64890Smrg ev->window = event->u.clientMessage.window; 28601ab64890Smrg ev->format = event->u.u.detail; 28611ab64890Smrg switch (ev->format) { 286261b2299dSmrg case 8: 28631ab64890Smrg ev->message_type = event->u.clientMessage.u.b.type; 286461b2299dSmrg for (i = 0; i < 20; i++) 28651ab64890Smrg ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; 28661ab64890Smrg break; 28671ab64890Smrg case 16: 28681ab64890Smrg ev->message_type = event->u.clientMessage.u.s.type; 28691ab64890Smrg ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0); 28701ab64890Smrg ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1); 28711ab64890Smrg ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2); 28721ab64890Smrg ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3); 28731ab64890Smrg ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4); 28741ab64890Smrg ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5); 28751ab64890Smrg ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6); 28761ab64890Smrg ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7); 28771ab64890Smrg ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8); 28781ab64890Smrg ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9); 28791ab64890Smrg break; 28801ab64890Smrg case 32: 28811ab64890Smrg ev->message_type = event->u.clientMessage.u.l.type; 28821ab64890Smrg ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0); 28831ab64890Smrg ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1); 28841ab64890Smrg ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2); 28851ab64890Smrg ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3); 28861ab64890Smrg ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4); 28871ab64890Smrg break; 28881ab64890Smrg default: /* XXX should never occur */ 28891ab64890Smrg break; 28901ab64890Smrg } 28911ab64890Smrg } 28921ab64890Smrg break; 28931ab64890Smrg case MappingNotify: 28941ab64890Smrg { 28951ab64890Smrg register XMappingEvent *ev = (XMappingEvent *)re; 28961ab64890Smrg ev->window = 0; 28971ab64890Smrg ev->first_keycode = event->u.mappingNotify.firstKeyCode; 28981ab64890Smrg ev->request = event->u.mappingNotify.request; 28991ab64890Smrg ev->count = event->u.mappingNotify.count; 29001ab64890Smrg } 29011ab64890Smrg break; 29021ab64890Smrg default: 29031ab64890Smrg return(_XUnknownWireEvent(dpy, re, event)); 29041ab64890Smrg } 29051ab64890Smrg return(True); 29061ab64890Smrg} 29071ab64890Smrg 29081ab64890Smrg 29091ab64890Smrg/* 291061b2299dSmrg * _XDefaultIOError - Default fatal system error reporting routine. Called 29111ab64890Smrg * when an X internal system error is encountered. 29121ab64890Smrg */ 29131ab64890Smrgint _XDefaultIOError( 29141ab64890Smrg Display *dpy) 29151ab64890Smrg{ 29161ab64890Smrg if (ECHECK(EPIPE)) { 29171ab64890Smrg (void) fprintf (stderr, 29181ab64890Smrg "X connection to %s broken (explicit kill or server shutdown).\r\n", 29191ab64890Smrg DisplayString (dpy)); 29201ab64890Smrg } else { 292161b2299dSmrg (void) fprintf (stderr, 29221ab64890Smrg "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", 29231ab64890Smrg#ifdef WIN32 29241ab64890Smrg WSAGetLastError(), strerror(WSAGetLastError()), 29251ab64890Smrg#else 29261ab64890Smrg errno, strerror (errno), 29271ab64890Smrg#endif 29281ab64890Smrg DisplayString (dpy)); 292961b2299dSmrg (void) fprintf (stderr, 29301ab64890Smrg " after %lu requests (%lu known processed) with %d events remaining.\r\n", 29311ab64890Smrg NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), 29321ab64890Smrg QLength(dpy)); 29331ab64890Smrg 29341ab64890Smrg } 29351ab64890Smrg exit(1); 29361ab64890Smrg return(0); /* dummy - function should never return */ 29371ab64890Smrg} 29381ab64890Smrg 29391ab64890Smrg 29401ab64890Smrgstatic int _XPrintDefaultError( 29411ab64890Smrg Display *dpy, 29421ab64890Smrg XErrorEvent *event, 29431ab64890Smrg FILE *fp) 29441ab64890Smrg{ 29451ab64890Smrg char buffer[BUFSIZ]; 29461ab64890Smrg char mesg[BUFSIZ]; 29471ab64890Smrg char number[32]; 29481ab64890Smrg const char *mtype = "XlibMessage"; 29491ab64890Smrg register _XExtension *ext = (_XExtension *)NULL; 29501ab64890Smrg _XExtension *bext = (_XExtension *)NULL; 29511ab64890Smrg XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); 29521ab64890Smrg XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); 29531ab64890Smrg (void) fprintf(fp, "%s: %s\n ", mesg, buffer); 295461b2299dSmrg XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", 29551ab64890Smrg mesg, BUFSIZ); 29561ab64890Smrg (void) fprintf(fp, mesg, event->request_code); 29571ab64890Smrg if (event->request_code < 128) { 29581ab64890Smrg sprintf(number, "%d", event->request_code); 29591ab64890Smrg XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); 29601ab64890Smrg } else { 29611ab64890Smrg for (ext = dpy->ext_procs; 29621ab64890Smrg ext && (ext->codes.major_opcode != event->request_code); 29631ab64890Smrg ext = ext->next) 29641ab64890Smrg ; 29651ab64890Smrg if (ext) 29661ab64890Smrg strcpy(buffer, ext->name); 29671ab64890Smrg else 29681ab64890Smrg buffer[0] = '\0'; 29691ab64890Smrg } 29701ab64890Smrg (void) fprintf(fp, " (%s)\n", buffer); 29711ab64890Smrg if (event->request_code >= 128) { 29721ab64890Smrg XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", 29731ab64890Smrg mesg, BUFSIZ); 29741ab64890Smrg fputs(" ", fp); 29751ab64890Smrg (void) fprintf(fp, mesg, event->minor_code); 29761ab64890Smrg if (ext) { 29771ab64890Smrg sprintf(mesg, "%s.%d", ext->name, event->minor_code); 29781ab64890Smrg XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); 29791ab64890Smrg (void) fprintf(fp, " (%s)", buffer); 29801ab64890Smrg } 29811ab64890Smrg fputs("\n", fp); 29821ab64890Smrg } 29831ab64890Smrg if (event->error_code >= 128) { 29841ab64890Smrg /* kludge, try to find the extension that caused it */ 29851ab64890Smrg buffer[0] = '\0'; 29861ab64890Smrg for (ext = dpy->ext_procs; ext; ext = ext->next) { 298761b2299dSmrg if (ext->error_string) 29881ab64890Smrg (*ext->error_string)(dpy, event->error_code, &ext->codes, 29891ab64890Smrg buffer, BUFSIZ); 29901ab64890Smrg if (buffer[0]) { 29911ab64890Smrg bext = ext; 29921ab64890Smrg break; 29931ab64890Smrg } 29941ab64890Smrg if (ext->codes.first_error && 29951ab64890Smrg ext->codes.first_error < (int)event->error_code && 29961ab64890Smrg (!bext || ext->codes.first_error > bext->codes.first_error)) 29971ab64890Smrg bext = ext; 299861b2299dSmrg } 29991ab64890Smrg if (bext) 30001ab64890Smrg sprintf(buffer, "%s.%d", bext->name, 30011ab64890Smrg event->error_code - bext->codes.first_error); 30021ab64890Smrg else 30031ab64890Smrg strcpy(buffer, "Value"); 30041ab64890Smrg XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); 30051ab64890Smrg if (mesg[0]) { 30061ab64890Smrg fputs(" ", fp); 30071ab64890Smrg (void) fprintf(fp, mesg, event->resourceid); 30081ab64890Smrg fputs("\n", fp); 30091ab64890Smrg } 30101ab64890Smrg /* let extensions try to print the values */ 30111ab64890Smrg for (ext = dpy->ext_procs; ext; ext = ext->next) { 30121ab64890Smrg if (ext->error_values) 30131ab64890Smrg (*ext->error_values)(dpy, event, fp); 30141ab64890Smrg } 30151ab64890Smrg } else if ((event->error_code == BadWindow) || 30161ab64890Smrg (event->error_code == BadPixmap) || 30171ab64890Smrg (event->error_code == BadCursor) || 30181ab64890Smrg (event->error_code == BadFont) || 30191ab64890Smrg (event->error_code == BadDrawable) || 30201ab64890Smrg (event->error_code == BadColor) || 30211ab64890Smrg (event->error_code == BadGC) || 30221ab64890Smrg (event->error_code == BadIDChoice) || 30231ab64890Smrg (event->error_code == BadValue) || 30241ab64890Smrg (event->error_code == BadAtom)) { 30251ab64890Smrg if (event->error_code == BadValue) 30261ab64890Smrg XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", 30271ab64890Smrg mesg, BUFSIZ); 30281ab64890Smrg else if (event->error_code == BadAtom) 30291ab64890Smrg XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", 30301ab64890Smrg mesg, BUFSIZ); 30311ab64890Smrg else 30321ab64890Smrg XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", 30331ab64890Smrg mesg, BUFSIZ); 30341ab64890Smrg fputs(" ", fp); 30351ab64890Smrg (void) fprintf(fp, mesg, event->resourceid); 30361ab64890Smrg fputs("\n", fp); 30371ab64890Smrg } 303861b2299dSmrg XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", 30391ab64890Smrg mesg, BUFSIZ); 30401ab64890Smrg fputs(" ", fp); 30411ab64890Smrg (void) fprintf(fp, mesg, event->serial); 30421ab64890Smrg XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", 30431ab64890Smrg mesg, BUFSIZ); 30441ab64890Smrg fputs("\n ", fp); 30451ab64890Smrg (void) fprintf(fp, mesg, dpy->request); 30461ab64890Smrg fputs("\n", fp); 30471ab64890Smrg if (event->error_code == BadImplementation) return 0; 30481ab64890Smrg return 1; 30491ab64890Smrg} 30501ab64890Smrg 30511ab64890Smrgint _XDefaultError( 30521ab64890Smrg Display *dpy, 30531ab64890Smrg XErrorEvent *event) 30541ab64890Smrg{ 30551ab64890Smrg if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0; 30561ab64890Smrg exit(1); 30571ab64890Smrg /*NOTREACHED*/ 30581ab64890Smrg} 30591ab64890Smrg 30601ab64890Smrg/*ARGSUSED*/ 306161b2299dSmrgBool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) 30621ab64890Smrg{ 30631ab64890Smrg return True; 30641ab64890Smrg} 30651ab64890Smrg 30661ab64890Smrg/* 30671ab64890Smrg * _XError - upcall internal or user protocol error handler 30681ab64890Smrg */ 30691ab64890Smrgint _XError ( 30701ab64890Smrg Display *dpy, 30711ab64890Smrg register xError *rep) 30721ab64890Smrg{ 307361b2299dSmrg /* 30741ab64890Smrg * X_Error packet encountered! We need to unpack the error before 30751ab64890Smrg * giving it to the user. 30761ab64890Smrg */ 30771ab64890Smrg XEvent event; /* make it a large event */ 30781ab64890Smrg register _XAsyncHandler *async, *next; 30791ab64890Smrg 30801ab64890Smrg event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); 30811ab64890Smrg 30821ab64890Smrg for (async = dpy->async_handlers; async; async = next) { 30831ab64890Smrg next = async->next; 30841ab64890Smrg if ((*async->handler)(dpy, (xReply *)rep, 30851ab64890Smrg (char *)rep, SIZEOF(xError), async->data)) 30861ab64890Smrg return 0; 30871ab64890Smrg } 30881ab64890Smrg 30891ab64890Smrg event.xerror.display = dpy; 30901ab64890Smrg event.xerror.type = X_Error; 30911ab64890Smrg event.xerror.resourceid = rep->resourceID; 30921ab64890Smrg event.xerror.error_code = rep->errorCode; 30931ab64890Smrg event.xerror.request_code = rep->majorCode; 30941ab64890Smrg event.xerror.minor_code = rep->minorCode; 30951ab64890Smrg if (dpy->error_vec && 30961ab64890Smrg !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep)) 30971ab64890Smrg return 0; 30981ab64890Smrg if (_XErrorFunction != NULL) { 30991ab64890Smrg int rtn_val; 31001ab64890Smrg#if defined(XTHREADS) && !USE_XCB 31011ab64890Smrg if (dpy->lock) 31021ab64890Smrg (*dpy->lock->user_lock_display)(dpy); 31031ab64890Smrg UnlockDisplay(dpy); 31041ab64890Smrg#endif /* XTHREADS && !USE_XCB */ 31051ab64890Smrg rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ 31061ab64890Smrg#if defined(XTHREADS) && !USE_XCB 31071ab64890Smrg LockDisplay(dpy); 31081ab64890Smrg if (dpy->lock) 31091ab64890Smrg (*dpy->lock->user_unlock_display)(dpy); 31101ab64890Smrg#endif /* XTHREADS && !USE_XCB */ 31111ab64890Smrg return rtn_val; 31121ab64890Smrg } else { 31131ab64890Smrg return _XDefaultError(dpy, (XErrorEvent *)&event); 31141ab64890Smrg } 31151ab64890Smrg} 311661b2299dSmrg 31171ab64890Smrg/* 31181ab64890Smrg * _XIOError - call user connection error handler and exit 31191ab64890Smrg */ 31201ab64890Smrgint 31211ab64890Smrg_XIOError ( 31221ab64890Smrg Display *dpy) 31231ab64890Smrg{ 31241ab64890Smrg dpy->flags |= XlibDisplayIOError; 31251ab64890Smrg#ifdef WIN32 31261ab64890Smrg errno = WSAGetLastError(); 31271ab64890Smrg#endif 31281ab64890Smrg 31291ab64890Smrg /* This assumes that the thread calling exit will call any atexit handlers. 31301ab64890Smrg * If this does not hold, then an alternate solution would involve 31311ab64890Smrg * registering an atexit handler to take over the lock, which would only 31321ab64890Smrg * assume that the same thread calls all the atexit handlers. */ 31331ab64890Smrg#ifdef XTHREADS 31341ab64890Smrg if (dpy->lock) 31351ab64890Smrg (*dpy->lock->user_lock_display)(dpy); 31361ab64890Smrg#endif 31371ab64890Smrg UnlockDisplay(dpy); 31381ab64890Smrg 31391ab64890Smrg if (_XIOErrorFunction != NULL) 31401ab64890Smrg (*_XIOErrorFunction)(dpy); 31411ab64890Smrg else 31421ab64890Smrg _XDefaultIOError(dpy); 31431ab64890Smrg exit (1); 31441ab64890Smrg return 0; 31451ab64890Smrg} 31461ab64890Smrg 31471ab64890Smrg 31481ab64890Smrg/* 31491ab64890Smrg * This routine can be used to (cheaply) get some memory within a single 31501ab64890Smrg * Xlib routine for scratch space. A single buffer is reused each time 31511ab64890Smrg * if possible. To be MT safe, you can only call this between a call to 31521ab64890Smrg * GetReq* and a call to Data* or _XSend*, or in a context when the thread 31531ab64890Smrg * is guaranteed to not unlock the display. 31541ab64890Smrg */ 31551ab64890Smrgchar *_XAllocScratch( 31561ab64890Smrg register Display *dpy, 31571ab64890Smrg unsigned long nbytes) 31581ab64890Smrg{ 31591ab64890Smrg if (nbytes > dpy->scratch_length) { 31601ab64890Smrg if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer); 31611ab64890Smrg if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes))) 31621ab64890Smrg dpy->scratch_length = nbytes; 31631ab64890Smrg else dpy->scratch_length = 0; 31641ab64890Smrg } 31651ab64890Smrg return (dpy->scratch_buffer); 31661ab64890Smrg} 31671ab64890Smrg 31681ab64890Smrg/* 31691ab64890Smrg * Scratch space allocator you can call any time, multiple times, and be 31701ab64890Smrg * MT safe, but you must hand the buffer back with _XFreeTemp. 31711ab64890Smrg */ 31721ab64890Smrgchar *_XAllocTemp( 31731ab64890Smrg register Display *dpy, 31741ab64890Smrg unsigned long nbytes) 31751ab64890Smrg{ 31761ab64890Smrg char *buf; 31771ab64890Smrg 31781ab64890Smrg buf = _XAllocScratch(dpy, nbytes); 31791ab64890Smrg dpy->scratch_buffer = NULL; 31801ab64890Smrg dpy->scratch_length = 0; 31811ab64890Smrg return buf; 31821ab64890Smrg} 31831ab64890Smrg 31841ab64890Smrgvoid _XFreeTemp( 31851ab64890Smrg register Display *dpy, 31861ab64890Smrg char *buf, 31871ab64890Smrg unsigned long nbytes) 31881ab64890Smrg{ 31891ab64890Smrg if (dpy->scratch_buffer) 31901ab64890Smrg Xfree(dpy->scratch_buffer); 31911ab64890Smrg dpy->scratch_buffer = buf; 31921ab64890Smrg dpy->scratch_length = nbytes; 31931ab64890Smrg} 31941ab64890Smrg 31951ab64890Smrg/* 31961ab64890Smrg * Given a visual id, find the visual structure for this id on this display. 31971ab64890Smrg */ 31981ab64890SmrgVisual *_XVIDtoVisual( 31991ab64890Smrg Display *dpy, 32001ab64890Smrg VisualID id) 32011ab64890Smrg{ 32021ab64890Smrg register int i, j, k; 32031ab64890Smrg register Screen *sp; 32041ab64890Smrg register Depth *dp; 32051ab64890Smrg register Visual *vp; 32061ab64890Smrg for (i = 0; i < dpy->nscreens; i++) { 32071ab64890Smrg sp = &dpy->screens[i]; 32081ab64890Smrg for (j = 0; j < sp->ndepths; j++) { 32091ab64890Smrg dp = &sp->depths[j]; 32101ab64890Smrg /* if nvisuals == 0 then visuals will be NULL */ 32111ab64890Smrg for (k = 0; k < dp->nvisuals; k++) { 32121ab64890Smrg vp = &dp->visuals[k]; 32131ab64890Smrg if (vp->visualid == id) return (vp); 32141ab64890Smrg } 32151ab64890Smrg } 32161ab64890Smrg } 32171ab64890Smrg return (NULL); 32181ab64890Smrg} 32191ab64890Smrg 32201ab64890Smrgint 32211ab64890SmrgXFree (void *data) 32221ab64890Smrg{ 32231ab64890Smrg Xfree (data); 32241ab64890Smrg return 1; 32251ab64890Smrg} 32261ab64890Smrg 32271ab64890Smrg#ifdef _XNEEDBCOPYFUNC 32281ab64890Smrgvoid _Xbcopy(b1, b2, length) 32291ab64890Smrg register char *b1, *b2; 32301ab64890Smrg register length; 32311ab64890Smrg{ 32321ab64890Smrg if (b1 < b2) { 32331ab64890Smrg b2 += length; 32341ab64890Smrg b1 += length; 32351ab64890Smrg while (length--) 32361ab64890Smrg *--b2 = *--b1; 32371ab64890Smrg } else { 32381ab64890Smrg while (length--) 32391ab64890Smrg *b2++ = *b1++; 32401ab64890Smrg } 32411ab64890Smrg} 32421ab64890Smrg#endif 32431ab64890Smrg 32441ab64890Smrg#ifdef DataRoutineIsProcedure 32451ab64890Smrgvoid Data( 32461ab64890Smrg Display *dpy, 32471ab64890Smrg char *data, 32481ab64890Smrg long len) 32491ab64890Smrg{ 32501ab64890Smrg if (dpy->bufptr + (len) <= dpy->bufmax) { 32511ab64890Smrg memcpy(dpy->bufptr, data, (int)len); 32521ab64890Smrg dpy->bufptr += ((len) + 3) & ~3; 32531ab64890Smrg } else { 32541ab64890Smrg _XSend(dpy, data, len); 32551ab64890Smrg } 32561ab64890Smrg} 32571ab64890Smrg#endif /* DataRoutineIsProcedure */ 32581ab64890Smrg 32591ab64890Smrg 32601ab64890Smrg#ifdef LONG64 32611ab64890Smrgint 32621ab64890Smrg_XData32( 32631ab64890Smrg Display *dpy, 32641ab64890Smrg register long *data, 32651ab64890Smrg unsigned len) 32661ab64890Smrg{ 32671ab64890Smrg register int *buf; 32681ab64890Smrg register long i; 32691ab64890Smrg 32701ab64890Smrg while (len) { 32711ab64890Smrg buf = (int *)dpy->bufptr; 32721ab64890Smrg i = dpy->bufmax - (char *)buf; 32731ab64890Smrg if (!i) { 32741ab64890Smrg _XFlush(dpy); 32751ab64890Smrg continue; 32761ab64890Smrg } 32771ab64890Smrg if (len < i) 32781ab64890Smrg i = len; 32791ab64890Smrg dpy->bufptr = (char *)buf + i; 32801ab64890Smrg len -= i; 32811ab64890Smrg i >>= 2; 32821ab64890Smrg while (--i >= 0) 32831ab64890Smrg *buf++ = *data++; 32841ab64890Smrg } 32851ab64890Smrg return 0; 32861ab64890Smrg} 32871ab64890Smrg#endif /* LONG64 */ 32881ab64890Smrg 32891ab64890Smrg#ifdef WORD64 32901ab64890Smrg 32911ab64890Smrg/* 329261b2299dSmrg * XXX This is a *really* stupid way of doing this. It should just use 32931ab64890Smrg * dpy->bufptr directly, taking into account where in the word it is. 32941ab64890Smrg */ 32951ab64890Smrg 32961ab64890Smrg/* 32971ab64890Smrg * Data16 - Place 16 bit data in the buffer. 32981ab64890Smrg * 32991ab64890Smrg * "dpy" is a pointer to a Display. 33001ab64890Smrg * "data" is a pointer to the data. 33011ab64890Smrg * "len" is the length in bytes of the data. 33021ab64890Smrg */ 33031ab64890Smrg 33041ab64890Smrgstatic doData16( 33051ab64890Smrg register Display *dpy, 33061ab64890Smrg short *data, 33071ab64890Smrg unsigned len, 33081ab64890Smrg char *packbuffer) 33091ab64890Smrg{ 33101ab64890Smrg long *lp,*lpack; 33111ab64890Smrg long i, nwords,bits; 33121ab64890Smrg long mask16 = 0x000000000000ffff; 33131ab64890Smrg 33141ab64890Smrg lp = (long *)data; 33151ab64890Smrg lpack = (long *)packbuffer; 33161ab64890Smrg 33171ab64890Smrg/* nwords is the number of 16 bit values to be packed, 33181ab64890Smrg * the low order 16 bits of each word will be packed 33191ab64890Smrg * into 64 bit words 33201ab64890Smrg */ 33211ab64890Smrg nwords = len >> 1; 33221ab64890Smrg bits = 48; 33231ab64890Smrg 33241ab64890Smrg for(i=0;i<nwords;i++){ 33251ab64890Smrg if (bits == 48) *lpack = 0; 33261ab64890Smrg *lpack ^= (*lp & mask16) << bits; 33271ab64890Smrg bits -= 16 ; 33281ab64890Smrg lp++; 33291ab64890Smrg if(bits < 0){ 33301ab64890Smrg lpack++; 33311ab64890Smrg bits = 48; 33321ab64890Smrg } 33331ab64890Smrg } 33341ab64890Smrg Data(dpy, packbuffer, len); 33351ab64890Smrg} 33361ab64890Smrg 33371ab64890Smrg_XData16 ( 33381ab64890Smrg Display *dpy, 33391ab64890Smrg short *data, 33401ab64890Smrg unsigned len) 33411ab64890Smrg{ 33421ab64890Smrg char packbuffer[PACKBUFFERSIZE]; 33431ab64890Smrg unsigned nunits = PACKBUFFERSIZE >> 1; 33441ab64890Smrg 33451ab64890Smrg for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 33461ab64890Smrg doData16 (dpy, data, PACKBUFFERSIZE, packbuffer); 33471ab64890Smrg } 33481ab64890Smrg if (len) doData16 (dpy, data, len, packbuffer); 33491ab64890Smrg} 33501ab64890Smrg 33511ab64890Smrg/* 33521ab64890Smrg * Data32 - Place 32 bit data in the buffer. 33531ab64890Smrg * 33541ab64890Smrg * "dpy" is a pointer to a Display. 33551ab64890Smrg * "data" is a pointer to the data. 33561ab64890Smrg * "len" is the length in bytes of the data. 33571ab64890Smrg */ 33581ab64890Smrg 33591ab64890Smrgstatic doData32( 33601ab64890Smrg register Display *dpy 33611ab64890Smrg long *data, 33621ab64890Smrg unsigned len, 33631ab64890Smrg char *packbuffer) 33641ab64890Smrg{ 33651ab64890Smrg long *lp,*lpack; 33661ab64890Smrg long i,bits,nwords; 33671ab64890Smrg long mask32 = 0x00000000ffffffff; 33681ab64890Smrg 33691ab64890Smrg lpack = (long *) packbuffer; 33701ab64890Smrg lp = data; 33711ab64890Smrg 33721ab64890Smrg/* nwords is the number of 32 bit values to be packed 33731ab64890Smrg * the low order 32 bits of each word will be packed 33741ab64890Smrg * into 64 bit words 33751ab64890Smrg */ 33761ab64890Smrg nwords = len >> 2; 33771ab64890Smrg bits = 32; 33781ab64890Smrg 33791ab64890Smrg for(i=0;i<nwords;i++){ 33801ab64890Smrg if (bits == 32) *lpack = 0; 33811ab64890Smrg *lpack ^= (*lp & mask32) << bits; 33821ab64890Smrg bits = bits ^32; 33831ab64890Smrg lp++; 33841ab64890Smrg if(bits) 33851ab64890Smrg lpack++; 33861ab64890Smrg } 33871ab64890Smrg Data(dpy, packbuffer, len); 33881ab64890Smrg} 33891ab64890Smrg 33901ab64890Smrgvoid _XData32( 33911ab64890Smrg Display *dpy, 33921ab64890Smrg long *data, 339361b2299dSmrg unsigned len) 33941ab64890Smrg{ 33951ab64890Smrg char packbuffer[PACKBUFFERSIZE]; 33961ab64890Smrg unsigned nunits = PACKBUFFERSIZE >> 2; 33971ab64890Smrg 33981ab64890Smrg for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { 33991ab64890Smrg doData32 (dpy, data, PACKBUFFERSIZE, packbuffer); 34001ab64890Smrg } 34011ab64890Smrg if (len) doData32 (dpy, data, len, packbuffer); 34021ab64890Smrg} 34031ab64890Smrg 34041ab64890Smrg#endif /* WORD64 */ 34051ab64890Smrg 34061ab64890Smrg 34071ab64890Smrg/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. 34081ab64890Smrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file. 34091ab64890Smrg * 34101ab64890Smrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have 34111ab64890Smrg * to have sufficient information for interfacing to the network, 34121ab64890Smrg * and so, you may be better off using gethostname (if it exists). 34131ab64890Smrg */ 34141ab64890Smrg 34152e9c7c8cSmrg#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4) 34161ab64890Smrg#define NEED_UTSNAME 34171ab64890Smrg#include <sys/utsname.h> 341888de56ccSmrg#else 341988de56ccSmrg#ifdef HAVE_UNISTD_H 342088de56ccSmrg#include <unistd.h> 342188de56ccSmrg#endif 34221ab64890Smrg#endif 34231ab64890Smrg 34241ab64890Smrg/* 34251ab64890Smrg * _XGetHostname - similar to gethostname but allows special processing. 34261ab64890Smrg */ 34271ab64890Smrgint _XGetHostname ( 34281ab64890Smrg char *buf, 34291ab64890Smrg int maxlen) 34301ab64890Smrg{ 34311ab64890Smrg int len; 34321ab64890Smrg 34331ab64890Smrg#ifdef NEED_UTSNAME 34341ab64890Smrg struct utsname name; 34351ab64890Smrg 34361ab64890Smrg if (maxlen <= 0 || buf == NULL) 34371ab64890Smrg return 0; 34381ab64890Smrg 34391ab64890Smrg uname (&name); 34401ab64890Smrg len = strlen (name.nodename); 34411ab64890Smrg if (len >= maxlen) len = maxlen - 1; 34421ab64890Smrg strncpy (buf, name.nodename, len); 34431ab64890Smrg buf[len] = '\0'; 34441ab64890Smrg#else 34451ab64890Smrg if (maxlen <= 0 || buf == NULL) 34461ab64890Smrg return 0; 34471ab64890Smrg 34481ab64890Smrg buf[0] = '\0'; 34491ab64890Smrg (void) gethostname (buf, maxlen); 34501ab64890Smrg buf [maxlen - 1] = '\0'; 34511ab64890Smrg len = strlen(buf); 34521ab64890Smrg#endif /* NEED_UTSNAME */ 34531ab64890Smrg return len; 34541ab64890Smrg} 34551ab64890Smrg 34561ab64890Smrg 34571ab64890Smrg/* 34581ab64890Smrg * _XScreenOfWindow - get the Screen of a given window 34591ab64890Smrg */ 34601ab64890Smrg 346161b2299dSmrgScreen *_XScreenOfWindow(Display *dpy, Window w) 34621ab64890Smrg{ 34631ab64890Smrg register int i; 34641ab64890Smrg Window root; 34651ab64890Smrg int x, y; /* dummy variables */ 34661ab64890Smrg unsigned int width, height, bw, depth; /* dummy variables */ 34671ab64890Smrg 34681ab64890Smrg if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, 34691ab64890Smrg &bw, &depth) == False) { 34702e9c7c8cSmrg return NULL; 34711ab64890Smrg } 34721ab64890Smrg for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ 34731ab64890Smrg if (root == RootWindow (dpy, i)) { 34741ab64890Smrg return ScreenOfDisplay (dpy, i); 34751ab64890Smrg } 34761ab64890Smrg } 34771ab64890Smrg return NULL; 34781ab64890Smrg} 34791ab64890Smrg 34801ab64890Smrg 34811ab64890Smrg#if defined(WIN32) 34821ab64890Smrg 34831ab64890Smrg/* 34841ab64890Smrg * These functions are intended to be used internally to Xlib only. 34851ab64890Smrg * These functions will always prefix the path with a DOS drive in the 34861ab64890Smrg * form "<drive-letter>:". As such, these functions are only suitable 34871ab64890Smrg * for use by Xlib function that supply a root-based path to some 34881ab64890Smrg * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will 34891ab64890Smrg * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir". 34901ab64890Smrg */ 34911ab64890Smrg 34921ab64890Smrgstatic int access_file (path, pathbuf, len_pathbuf, pathret) 34931ab64890Smrg char* path; 34941ab64890Smrg char* pathbuf; 34951ab64890Smrg int len_pathbuf; 34961ab64890Smrg char** pathret; 34971ab64890Smrg{ 34981ab64890Smrg if (access (path, F_OK) == 0) { 34991ab64890Smrg if (strlen (path) < len_pathbuf) 35001ab64890Smrg *pathret = pathbuf; 35011ab64890Smrg else 35021ab64890Smrg *pathret = Xmalloc (strlen (path) + 1); 35031ab64890Smrg if (*pathret) { 35041ab64890Smrg strcpy (*pathret, path); 35051ab64890Smrg return 1; 35061ab64890Smrg } 35071ab64890Smrg } 35081ab64890Smrg return 0; 35091ab64890Smrg} 35101ab64890Smrg 35111ab64890Smrgstatic int AccessFile (path, pathbuf, len_pathbuf, pathret) 35121ab64890Smrg char* path; 35131ab64890Smrg char* pathbuf; 35141ab64890Smrg int len_pathbuf; 35151ab64890Smrg char** pathret; 35161ab64890Smrg{ 35171ab64890Smrg unsigned long drives; 35181ab64890Smrg int i, len; 35191ab64890Smrg char* drive; 35201ab64890Smrg char buf[MAX_PATH]; 35211ab64890Smrg char* bufp; 35221ab64890Smrg 35231ab64890Smrg /* just try the "raw" name first and see if it works */ 35241ab64890Smrg if (access_file (path, pathbuf, len_pathbuf, pathret)) 35251ab64890Smrg return 1; 35261ab64890Smrg 35271ab64890Smrg /* try the places set in the environment */ 35281ab64890Smrg drive = getenv ("_XBASEDRIVE"); 35291ab64890Smrg#ifdef __UNIXOS2__ 35301ab64890Smrg if (!drive) 35311ab64890Smrg drive = getenv ("X11ROOT"); 35321ab64890Smrg#endif 35331ab64890Smrg if (!drive) 35341ab64890Smrg drive = "C:"; 35351ab64890Smrg len = strlen (drive) + strlen (path); 35361ab64890Smrg if (len < MAX_PATH) bufp = buf; 35371ab64890Smrg else bufp = Xmalloc (len + 1); 35381ab64890Smrg strcpy (bufp, drive); 35391ab64890Smrg strcat (bufp, path); 35401ab64890Smrg if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 35411ab64890Smrg if (bufp != buf) Xfree (bufp); 35421ab64890Smrg return 1; 35431ab64890Smrg } 35441ab64890Smrg 354561b2299dSmrg#ifndef __UNIXOS2__ 35461ab64890Smrg /* one last place to look */ 35471ab64890Smrg drive = getenv ("HOMEDRIVE"); 35481ab64890Smrg if (drive) { 35491ab64890Smrg len = strlen (drive) + strlen (path); 35501ab64890Smrg if (len < MAX_PATH) bufp = buf; 35511ab64890Smrg else bufp = Xmalloc (len + 1); 35521ab64890Smrg strcpy (bufp, drive); 35531ab64890Smrg strcat (bufp, path); 35541ab64890Smrg if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 35551ab64890Smrg if (bufp != buf) Xfree (bufp); 35561ab64890Smrg return 1; 35571ab64890Smrg } 35581ab64890Smrg } 35591ab64890Smrg 35601ab64890Smrg /* tried everywhere else, go fishing */ 35611ab64890Smrg#define C_DRIVE ('C' - 'A') 35621ab64890Smrg#define Z_DRIVE ('Z' - 'A') 35631ab64890Smrg /* does OS/2 (with or with gcc-emx) have getdrives? */ 35641ab64890Smrg drives = _getdrives (); 35651ab64890Smrg for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ 35661ab64890Smrg if ((1 << i) & drives) { 35671ab64890Smrg len = 2 + strlen (path); 35681ab64890Smrg if (len < MAX_PATH) bufp = buf; 35691ab64890Smrg else bufp = Xmalloc (len + 1); 35701ab64890Smrg *bufp = 'A' + i; 35711ab64890Smrg *(bufp + 1) = ':'; 35721ab64890Smrg *(bufp + 2) = '\0'; 35731ab64890Smrg strcat (bufp, path); 35741ab64890Smrg if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { 35751ab64890Smrg if (bufp != buf) Xfree (bufp); 35761ab64890Smrg return 1; 35771ab64890Smrg } 35781ab64890Smrg } 35791ab64890Smrg } 35801ab64890Smrg#endif 35811ab64890Smrg return 0; 35821ab64890Smrg} 35831ab64890Smrg 35841ab64890Smrgint _XOpenFile(path, flags) 35851ab64890Smrg _Xconst char* path; 35861ab64890Smrg int flags; 35871ab64890Smrg{ 35881ab64890Smrg char buf[MAX_PATH]; 35891ab64890Smrg char* bufp = NULL; 35901ab64890Smrg int ret = -1; 35911ab64890Smrg UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 35921ab64890Smrg 35931ab64890Smrg if (AccessFile (path, buf, MAX_PATH, &bufp)) 35941ab64890Smrg ret = open (bufp, flags); 35951ab64890Smrg 35961ab64890Smrg (void) SetErrorMode (olderror); 35971ab64890Smrg 35981ab64890Smrg if (bufp != buf) Xfree (bufp); 35991ab64890Smrg 36001ab64890Smrg return ret; 36011ab64890Smrg} 36021ab64890Smrg 36031ab64890Smrgint _XOpenFileMode(path, flags, mode) 36041ab64890Smrg _Xconst char* path; 36051ab64890Smrg int flags; 36061ab64890Smrg mode_t mode; 36071ab64890Smrg{ 36081ab64890Smrg char buf[MAX_PATH]; 36091ab64890Smrg char* bufp = NULL; 36101ab64890Smrg int ret = -1; 36111ab64890Smrg UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 36121ab64890Smrg 36131ab64890Smrg if (AccessFile (path, buf, MAX_PATH, &bufp)) 36141ab64890Smrg ret = open (bufp, flags, mode); 36151ab64890Smrg 36161ab64890Smrg (void) SetErrorMode (olderror); 36171ab64890Smrg 36181ab64890Smrg if (bufp != buf) Xfree (bufp); 36191ab64890Smrg 36201ab64890Smrg return ret; 36211ab64890Smrg} 36221ab64890Smrg 36231ab64890Smrgvoid* _XFopenFile(path, mode) 36241ab64890Smrg _Xconst char* path; 36251ab64890Smrg _Xconst char* mode; 36261ab64890Smrg{ 36271ab64890Smrg char buf[MAX_PATH]; 36281ab64890Smrg char* bufp = NULL; 36291ab64890Smrg void* ret = NULL; 36301ab64890Smrg UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 36311ab64890Smrg 36321ab64890Smrg if (AccessFile (path, buf, MAX_PATH, &bufp)) 36331ab64890Smrg ret = fopen (bufp, mode); 36341ab64890Smrg 36351ab64890Smrg (void) SetErrorMode (olderror); 36361ab64890Smrg 36371ab64890Smrg if (bufp != buf) Xfree (bufp); 36381ab64890Smrg 36391ab64890Smrg return ret; 36401ab64890Smrg} 36411ab64890Smrg 36421ab64890Smrgint _XAccessFile(path) 36431ab64890Smrg _Xconst char* path; 36441ab64890Smrg{ 36451ab64890Smrg char buf[MAX_PATH]; 36461ab64890Smrg char* bufp; 36471ab64890Smrg int ret = -1; 36481ab64890Smrg UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); 36491ab64890Smrg 36501ab64890Smrg ret = AccessFile (path, buf, MAX_PATH, &bufp); 36511ab64890Smrg 36521ab64890Smrg (void) SetErrorMode (olderror); 36531ab64890Smrg 36541ab64890Smrg if (bufp != buf) Xfree (bufp); 36551ab64890Smrg 36561ab64890Smrg return ret; 36571ab64890Smrg} 36581ab64890Smrg 36591ab64890Smrg#endif 36601ab64890Smrg 36611ab64890Smrg#ifdef WIN32 36621ab64890Smrg#undef _Xdebug 36631ab64890Smrgint _Xdebug = 0; 36641ab64890Smrgint *_Xdebug_p = &_Xdebug; 36651ab64890Smrgvoid (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn; 36661ab64890Smrgvoid (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn; 36671ab64890Smrgvoid (**_XLockMutex_fn_p)(LockInfoPtr 36681ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 36691ab64890Smrg , char * /* file */ 36701ab64890Smrg , int /* line */ 36711ab64890Smrg#endif 36721ab64890Smrg ) = &_XLockMutex_fn; 36731ab64890Smrgvoid (**_XUnlockMutex_fn_p)(LockInfoPtr 36741ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 36751ab64890Smrg , char * /* file */ 36761ab64890Smrg , int /* line */ 36771ab64890Smrg#endif 36781ab64890Smrg ) = &_XUnlockMutex_fn; 36791ab64890SmrgLockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock; 36801ab64890Smrg#endif 3681