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