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