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