diff options
Diffstat (limited to 'nx-X11/lib/X11/XlibInt.c')
-rw-r--r-- | nx-X11/lib/X11/XlibInt.c | 4199 |
1 files changed, 0 insertions, 4199 deletions
diff --git a/nx-X11/lib/X11/XlibInt.c b/nx-X11/lib/X11/XlibInt.c deleted file mode 100644 index 5afc65149..000000000 --- a/nx-X11/lib/X11/XlibInt.c +++ /dev/null @@ -1,4199 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */ -/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/ -/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */ -/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* nx-X11, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -/* - -Copyright 1985, 1986, 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - -*/ - -/* - * XlibInt.c - Internal support routines for the C subroutine - * interface library (Xlib) to the X Window System Protocol V11.0. - */ - -#ifdef WIN32 -#define _XLIBINT_ -#endif -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "Xlibint.h" -#include "Xprivate.h" -#include <nx-X11/Xpoll.h> -#if !USE_XCB -#include <nx-X11/Xtrans/Xtrans.h> -#include <nx-X11/extensions/xcmiscstr.h> -#endif /* !USE_XCB */ -#include <assert.h> -#include <stdio.h> -#ifdef WIN32 -#include <direct.h> -#endif - -#ifdef XTHREADS -#include "locking.h" - -/* these pointers get initialized by XInitThreads */ -LockInfoPtr _Xglobal_lock = NULL; -void (*_XCreateMutex_fn)(LockInfoPtr) = NULL; -/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */ -void (*_XFreeMutex_fn)(LockInfoPtr) = NULL; -void (*_XLockMutex_fn)( - LockInfoPtr /* lock */ -#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) - , char * /* file */ - , int /* line */ -#endif - ) = NULL; -void (*_XUnlockMutex_fn)( - LockInfoPtr /* lock */ -#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) - , char * /* file */ - , int /* line */ -#endif - ) = NULL; -xthread_t (*_Xthread_self_fn)(void) = NULL; - -#define XThread_Self() ((*_Xthread_self_fn)()) - -#if !USE_XCB -#define UnlockNextReplyReader(d) if ((d)->lock) \ - (*(d)->lock->pop_reader)((d),&(d)->lock->reply_awaiters,&(d)->lock->reply_awaiters_tail) - -#define QueueReplyReaderLock(d) ((d)->lock ? \ - (*(d)->lock->push_reader)(d,&(d)->lock->reply_awaiters_tail) : NULL) -#define QueueEventReaderLock(d) ((d)->lock ? \ - (*(d)->lock->push_reader)(d,&(d)->lock->event_awaiters_tail) : NULL) -#endif /* !USE_XCB */ - -#else /* XTHREADS else */ - -#if !USE_XCB -#define UnlockNextReplyReader(d) -#define UnlockNextEventReader(d) -#endif /* !USE_XCB */ - -#endif /* XTHREADS else */ - -#ifdef NX_TRANS_SOCKET - -#include <nx/NX.h> -#include <nx/NXvars.h> - -static struct timeval retry; - -/* - * From Xtranssock.c. Presently the congestion state - * is reported by the proxy to the application, by - * invoking the callback directly. The function will - * be possibly used in the future, to be able to track - * the bandwidth usage even when the NX transport is - * not running. Note that in this sample implementation - * the congestion state is checked very often and can - * be surely optimized. - */ - -#ifdef NX_TRANS_CHANGE -extern int _X11TransSocketCongestionChange(XtransConnInfo, int *); -#endif - -#endif /* #ifdef NX_TRANS_SOCKET */ - -/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX - * systems are broken and return EWOULDBLOCK when they should return EAGAIN - */ -#ifdef WIN32 -#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) -#else -#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */ -#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) -#else -#if defined(EAGAIN) && defined(EWOULDBLOCK) -#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) -#else -#ifdef EAGAIN -#define ETEST() (errno == EAGAIN) -#else -#define ETEST() (errno == EWOULDBLOCK) -#endif /* EAGAIN */ -#endif /* EAGAIN && EWOULDBLOCK */ -#endif /* __CYGWIN__ */ -#endif /* WIN32 */ - -#ifdef WIN32 -#define ECHECK(err) (WSAGetLastError() == err) -#define ESET(val) WSASetLastError(val) -#else -#define ECHECK(err) (errno == err) -#define ESET(val) errno = val -#endif - -#if defined(LOCALCONN) || defined(LACHMAN) -#ifdef EMSGSIZE -#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE)) -#else -#define ESZTEST() ECHECK(ERANGE) -#endif -#else -#ifdef EMSGSIZE -#define ESZTEST() ECHECK(EMSGSIZE) -#endif -#endif - -#if !USE_XCB - -#define STARTITERATE(tpvar,type,start,endcond) \ - for (tpvar = (type *) (start); endcond; ) -#define ITERPTR(tpvar) (char *)tpvar -#define RESETITERPTR(tpvar,type,start) tpvar = (type *) (start) -#define INCITERPTR(tpvar,type) tpvar++ -#define ENDITERATE - - -typedef union { - xReply rep; - char buf[BUFSIZE]; -} _XAlignedBuffer; - -static char *_XAsyncReply( - Display *dpy, - register xReply *rep, - char *buf, - register int *lenp, - Bool discard); -#endif /* !USE_XCB */ - -/* - * The following routines are internal routines used by Xlib for protocol - * packet transmission and reception. - * - * _XIOError(Display *) will be called if any sort of system call error occurs. - * This is assumed to be a fatal condition, i.e., XIOError should not return. - * - * _XError(Display *, xError *) will be called whenever an X_Error event is - * received. This is not assumed to be a fatal condition, i.e., it is - * acceptable for this procedure to return. However, XError should NOT - * perform any operations (directly or indirectly) on the DISPLAY. - * - * Routines declared with a return type of 'Status' return 0 on failure, - * and non 0 on success. Routines with no declared return type don't - * return anything. Whenever possible routines that create objects return - * the object they have created. - */ - -#if !USE_XCB -static xReq _dummy_request = { - 0, 0, 0 -}; - -#ifdef NX_TRANS_SOCKET - -/* - * Replace the standard Select with a version giving NX a - * chance to check its own descriptors. This doesn't cover - * the cases where the system is using poll or when system- - * specific defines override the Select definition (OS/2). - */ - -int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) -{ -#ifdef NX_TRANS_TEST - fprintf(stderr, "_XSelect: Called with [%d][%p][%p][%p][%p].\n", - maxfds, (void *) readfds, (void *) writefds, (void *) exceptfds, - (void *) timeout); -#endif - - if (NXTransRunning(NX_FD_ANY)) - { - fd_set t_readfds, t_writefds; - struct timeval t_timeout; - - int n, r, e; - -#ifdef NX_TRANS_TEST - - if (exceptfds != NULL) - { - fprintf(stderr, "_XSelect: WARNING! Can't handle exception fds in select.\n"); - } - -#endif - - if (readfds == NULL) - { - FD_ZERO(&t_readfds); - - readfds = &t_readfds; - } - - if (writefds == NULL) - { - FD_ZERO(&t_writefds); - - writefds = &t_writefds; - } - - if (timeout == NULL) - { - t_timeout.tv_sec = 10; - t_timeout.tv_usec = 0; - - timeout = &t_timeout; - } - - n = maxfds; - - /* - * If the transport is gone avoid - * sleeping until the timeout. - */ - - if (NXTransPrepare(&n, readfds, writefds, timeout) != 0) - { - NXTransSelect(&r, &e, &n, readfds, writefds, timeout); - - NXTransExecute(&r, &e, &n, readfds, writefds, timeout); - - errno = e; - - return r; - } - else - { - return 0; - } - } - else - { - return select(maxfds, readfds, writefds, exceptfds, timeout); - } -} - -#else /* #ifdef NX_TRANS_SOCKET */ - -int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) -{ - return select(maxfds, readfds, writefds, exceptfds, timeout); -} - -#endif /* #ifdef NX_TRANS_SOCKET */ - -/* - * This is an OS dependent routine which: - * 1) returns as soon as the connection can be written on.... - * 2) if the connection can be read, must enqueue events and handle errors, - * until the connection is writable. - */ -static void -_XWaitForWritable( - Display *dpy -#ifdef XTHREADS - , - xcondition_t cv /* our reading condition variable */ -#endif - ) -{ -#ifdef USE_POLL - struct pollfd filedes; -#else - fd_set r_mask; - fd_set w_mask; -#endif - int nfound; - -#ifdef NX_TRANS_SOCKET -#if defined(NX_TRANS_CHANGE) - int congestion; -#endif - if (_XGetIOError(dpy)) { - return; - } -#endif - -#ifdef USE_POLL - filedes.fd = dpy->fd; - filedes.events = 0; -#else - FD_ZERO(&r_mask); - FD_ZERO(&w_mask); -#endif - - for (;;) { -#ifdef XTHREADS - /* We allow only one thread at a time to read, to minimize - passing of read data between threads. - Now, who is it? If there is a non-NULL reply_awaiters and - we (i.e., our cv) are not at the head of it, then whoever - is at the head is the reader, and we don't read. - Otherwise there is no reply_awaiters or we are at the - head, having just appended ourselves. - In this case, if there is a event_awaiters, then whoever - is at the head of it got there before we did, and they are the - reader. - - Last cases: no event_awaiters and we are at the head of - reply_awaiters or reply_awaiters is NULL: we are the reader, - since there is obviously no one else involved. - - XXX - what if cv is NULL and someone else comes along after - us while we are waiting? - */ - - if (!dpy->lock || - (!dpy->lock->event_awaiters && - (!dpy->lock->reply_awaiters || - dpy->lock->reply_awaiters->cv == cv))) -#endif - -#ifndef NX_TRANS_SOCKET -#ifdef USE_POLL - filedes.events = POLLIN; - filedes.events |= POLLOUT; -#else - FD_SET(dpy->fd, &r_mask); - FD_SET(dpy->fd, &w_mask); -#endif -#endif /* #ifndef NX_TRANS_SOCKET */ - - do { -#ifdef NX_TRANS_SOCKET - /* - * Give a chance to the registered client to perform - * any needed operation before entering the select. - */ - -#ifdef NX_TRANS_TEST - fprintf(stderr, "_XWaitForWritable: WAIT! Waiting for the display to become writable.\n"); -#endif - NXTransFlush(dpy->fd); - - if (_NXDisplayBlockFunction != NULL) { - (*_NXDisplayBlockFunction)(dpy, NXBlockWrite); - } - - /* - * Need to set again the descriptors as we could have - * run multiple selects before having the possibility - * to read or write to the X connection. - */ - -#ifdef USE_POLL - filedes.events = POLLIN; - filedes.events |= POLLOUT; -#else - FD_SET(dpy->fd, &r_mask); - FD_SET(dpy->fd, &w_mask); -#endif -#endif /* #ifdef NX_TRANS_SOCKET */ - UnlockDisplay(dpy); -#ifdef USE_POLL -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XWaitForWritable: Calling poll().\n"); -#endif - nfound = poll (&filedes, 1, -1); -#else /* USE_POLL */ -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XWaitForWritable: Calling select() after [%ld] ms.\n", - NXTransTime()); -#endif /* defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) */ -#ifdef NX_TRANS_SOCKET - /* - * Give a chance to the callback to detect - * the failure of the display even if we - * miss the interrupt inside the select. - */ - - if (_NXDisplayErrorFunction != NULL) { - retry.tv_sec = 5; - retry.tv_usec = 0; - nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, &retry); - } else { - nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL); - } -#else /* NX_TRANS_SOCKET */ - nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL); -#endif /* NX_TRANS_SOCKET */ -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XWaitForWritable: Out of select() with [%d] after [%ld] ms.\n", - nfound, NXTransTime()); - - if (FD_ISSET(dpy->fd, &r_mask)) - { - BytesReadable_t pend; - - _X11TransBytesReadable(dpy->trans_conn, &pend); - - fprintf(stderr, "_XWaitForWritable: Descriptor [%d] is ready with [%ld] bytes to read.\n", - dpy->fd, pend); - } - - if (FD_ISSET(dpy->fd, &w_mask)) - { - fprintf(stderr, "_XWaitForWritable: Descriptor [%d] has become writable.\n\n", - dpy->fd); - } -#endif /* defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) */ -#endif /* USE_POLL */ - InternalLockDisplay(dpy, cv != NULL); -#ifdef NX_TRANS_SOCKET -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - if (_NXDisplayCongestionFunction != NULL && - _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { - (*_NXDisplayCongestionFunction)(dpy, congestion); - } -#endif /* defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) */ - if (nfound <= 0) { - if ((nfound == -1 && !(ECHECK(EINTR) || ETEST())) || - (_NXDisplayErrorFunction != NULL && - (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { - _XIOError(dpy); - return; - } - } -#else /* NX_TRANS_SOCKET */ - if (nfound < 0 && !(ECHECK(EINTR) || ETEST())) - _XIOError(dpy); -#endif /* NX_TRANS_SOCKET */ - } while (nfound <= 0); - - if ( -#ifdef USE_POLL - filedes.revents & POLLIN -#else /* USE_POLL */ - FD_ISSET(dpy->fd, &r_mask) -#endif /* USE_POLL */ - ) - { - _XAlignedBuffer buf; - BytesReadable_t pend; - register int len; - register xReply *rep; - - /* find out how much data can be read */ - if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) -#ifdef NX_TRANS_SOCKET - { - _XIOError(dpy); - - return; - } -#else /* NX_TRANS_SOCKET */ - _XIOError(dpy); -#endif /* NX_TRANS_SOCKET */ - len = pend; - - /* must read at least one xEvent; if none is pending, then - we'll just block waiting for it */ - if (len < SIZEOF(xReply) -#ifdef XTHREADS - || dpy->async_handlers -#endif - ) - len = SIZEOF(xReply); - - /* but we won't read more than the max buffer size */ - if (len > BUFSIZE) len = BUFSIZE; - - /* round down to an integral number of XReps */ - len = (len / SIZEOF(xReply)) * SIZEOF(xReply); - - (void) _XRead (dpy, buf.buf, (long) len); - - STARTITERATE(rep,xReply,buf.buf,len > 0) { - if (rep->generic.type == X_Reply) { - int tmp = len; - RESETITERPTR(rep,xReply, - _XAsyncReply (dpy, rep, - ITERPTR(rep), &tmp, True)); - len = tmp; - pend = len; - } else { - if (rep->generic.type == X_Error) - _XError (dpy, (xError *)rep); - else /* must be an event packet */ - _XEnq (dpy, (xEvent *)rep); - INCITERPTR(rep,xReply); - len -= SIZEOF(xReply); - } - } ENDITERATE -#ifdef XTHREADS - if (dpy->lock && dpy->lock->event_awaiters) - ConditionSignal(dpy, dpy->lock->event_awaiters->cv); -#endif - } -#ifdef USE_POLL - if (filedes.revents & (POLLOUT|POLLHUP|POLLERR)) -#else - if (FD_ISSET(dpy->fd, &w_mask)) -#endif - { -#ifdef XTHREADS - if (dpy->lock) { - ConditionBroadcast(dpy, dpy->lock->writers); - } -#endif - return; - } - } -} -#endif /* !USE_XCB */ - - -#define POLLFD_CACHE_SIZE 5 - -/* initialize the struct array passed to poll() below */ -Bool _XPollfdCacheInit( - Display *dpy) -{ -#ifdef USE_POLL - struct pollfd *pfp; - - pfp = Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd)); - if (!pfp) - return False; - pfp[0].fd = dpy->fd; - pfp[0].events = POLLIN; - - dpy->filedes = (XPointer)pfp; -#endif - return True; -} - -void _XPollfdCacheAdd( - Display *dpy, - int fd) -{ -#ifdef USE_POLL - struct pollfd *pfp = (struct pollfd *)dpy->filedes; - - if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { - pfp[dpy->im_fd_length].fd = fd; - pfp[dpy->im_fd_length].events = POLLIN; - } -#endif -} - -/* ARGSUSED */ -void _XPollfdCacheDel( - Display *dpy, - int fd) /* not used */ -{ -#ifdef USE_POLL - struct pollfd *pfp = (struct pollfd *)dpy->filedes; - struct _XConnectionInfo *conni; - - /* just recalculate whole list */ - if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) { - int loc = 1; - for (conni = dpy->im_fd_info; conni; conni=conni->next) { - pfp[loc].fd = conni->fd; - pfp[loc].events = POLLIN; - loc++; - } - } -#endif -} - -#if !USE_XCB -/* returns True iff there is an event in the queue newer than serial_num */ - -static Bool -_XNewerQueuedEvent( - Display *dpy, - int serial_num) -{ - _XQEvent *qev; - - if (dpy->next_event_serial_num == serial_num) - return False; - - qev = dpy->head; - while (qev) { - if (qev->qserial_num >= serial_num) { - return True; - } - qev = qev->next; - } - return False; -} - -static int -_XWaitForReadable( - Display *dpy) -{ - int result; - int fd = dpy->fd; - struct _XConnectionInfo *ilist; - register int saved_event_serial = 0; - int in_read_events = 0; - register Bool did_proc_conni = False; -#ifdef USE_POLL - struct pollfd *filedes; -#else - fd_set r_mask; - int highest_fd = fd; -#endif - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - int congestion; -#endif -#ifdef NX_TRANS_SOCKET - if (_XGetIOError(dpy)) { - return -1; - } -#endif - -#ifdef USE_POLL - if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE - && !(dpy->flags & XlibDisplayProcConni)) { - /* XXX - this fallback is gross */ - int i; - - filedes = (struct pollfd *)Xmalloc(dpy->im_fd_length * sizeof(struct pollfd)); - filedes[0].fd = fd; - filedes[0].events = POLLIN; - for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) { - filedes[i].fd = ilist->fd; - filedes[i].events = POLLIN; - } - } else { - filedes = (struct pollfd *)dpy->filedes; - } -#else /* USE_POLL */ - FD_ZERO(&r_mask); -#endif /* USE_POLL */ - for (;;) { -#ifndef USE_POLL - FD_SET(fd, &r_mask); - if (!(dpy->flags & XlibDisplayProcConni)) - for (ilist=dpy->im_fd_info; ilist; ilist=ilist->next) { - FD_SET(ilist->fd, &r_mask); - if (ilist->fd > highest_fd) - highest_fd = ilist->fd; - } -#endif /* USE_POLL */ - UnlockDisplay(dpy); -#ifdef USE_POLL -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XWaitForReadable: Calling poll().\n"); -#endif - result = poll(filedes, - (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length, - -1); -#else /* USE_POLL */ -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XWaitForReadable: Calling select().\n"); -#endif -#ifdef NX_TRANS_SOCKET - /* - * Give a chance to the registered application - * to perform any needed operation. - */ - -#ifdef NX_TRANS_TEST - fprintf(stderr, "_XWaitForReadable: WAIT! Waiting for the display to become readable.\n"); -#endif - NXTransFlush(dpy->fd); - - if (_NXDisplayBlockFunction != NULL) { - (*_NXDisplayBlockFunction)(dpy, NXBlockRead); - } - - if (_NXDisplayErrorFunction != NULL) { - retry.tv_sec = 5; - retry.tv_usec = 0; - result = Select(highest_fd + 1, &r_mask, NULL, NULL, &retry); - } else { - result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL); - } -#else /* NX_TRANS_SOCKET */ - result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL); -#endif /* NX_TRANS_SOCKET */ -#endif /* USE_POLL */ -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XWaitForReadable: Out of select with result [%d] and errno [%d].\n", - result, (result < 0 ? errno : 0)); -#endif - InternalLockDisplay(dpy, dpy->flags & XlibDisplayReply); -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - if (_NXDisplayCongestionFunction != NULL && - _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { - (*_NXDisplayCongestionFunction)(dpy, congestion); - } -#endif -#ifdef NX_TRANS_SOCKET - if (result <= 0) { - if ((result == -1 && !(ECHECK(EINTR) || ETEST())) || - (_NXDisplayErrorFunction != NULL && - (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { - _XIOError(dpy); - return -1; - } - continue; - } -#else - if (result == -1 && !(ECHECK(EINTR) || ETEST())) _XIOError(dpy); - if (result <= 0) - continue; -#endif -#ifdef USE_POLL - if (filedes[0].revents & (POLLIN|POLLHUP|POLLERR)) -#else - if (FD_ISSET(fd, &r_mask)) -#endif - break; - if (!(dpy->flags & XlibDisplayProcConni)) { - int i; - - saved_event_serial = dpy->next_event_serial_num; - /* dpy flags can be clobbered by internal connection callback */ - in_read_events = dpy->flags & XlibDisplayReadEvents; - for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) { -#ifdef USE_POLL - if (filedes[i].revents & POLLIN) -#else - if (FD_ISSET(ilist->fd, &r_mask)) -#endif - { - _XProcessInternalConnection(dpy, ilist); - did_proc_conni = True; - } - } -#ifdef USE_POLL - if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE) - Xfree(filedes); -#endif - } - if (did_proc_conni) { - /* some internal connection callback might have done an - XPutBackEvent. We notice it here and if we needed an event, - we can return all the way. */ - if (_XNewerQueuedEvent(dpy, saved_event_serial) - && (in_read_events -#ifdef XTHREADS - || (dpy->lock && dpy->lock->event_awaiters) -#endif - )) - return -2; - did_proc_conni = False; - } - } -#ifdef XTHREADS -#ifdef XTHREADS_DEBUG - printf("thread %x _XWaitForReadable returning\n", XThread_Self()); -#endif -#endif - return 0; -} -#endif /* !USE_XCB */ - -static int sync_hazard(Display *dpy) -{ - unsigned long span = dpy->request - dpy->last_request_read; - unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10); - return span >= 65535 - hazard - 10; -} - -static -void sync_while_locked(Display *dpy) -{ -#ifdef XTHREADS - if (dpy->lock) - (*dpy->lock->user_lock_display)(dpy); -#endif - UnlockDisplay(dpy); - SyncHandle(); - InternalLockDisplay(dpy, /* don't skip user locks */ 0); -#ifdef XTHREADS - if (dpy->lock) - (*dpy->lock->user_unlock_display)(dpy); -#endif -} - -void _XSeqSyncFunction( - register Display *dpy) -{ - xGetInputFocusReply rep; - _X_UNUSED register xReq *req; - -#ifdef NX_TRANS_SOCKET -#ifdef NX_TRANS_DEBUG - fprintf(stderr, "_XSeqSyncFunction: Going to synchronize the display.\n"); -#endif - - if (dpy->flags & XlibDisplayIOError) - { -#ifdef NX_TRANS_DEBUG - fprintf(stderr, "_XSeqSyncFunction: Returning 0 with I/O error detected.\n"); -#endif - return; - } -#endif /* NX_TRANS_SOCKET */ - if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) { - GetEmptyReq(GetInputFocus, req); - (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); - sync_while_locked(dpy); - } else if (sync_hazard(dpy)) - _XSetPrivSyncFunction(dpy); -} - -/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */ -static int -_XPrivSyncFunction (Display *dpy) -{ -#ifdef XTHREADS - assert(!dpy->lock_fns); -#endif - assert(dpy->synchandler == _XPrivSyncFunction); - assert((dpy->flags & XlibDisplayPrivSync) != 0); - dpy->synchandler = dpy->savedsynchandler; - dpy->savedsynchandler = NULL; - dpy->flags &= ~XlibDisplayPrivSync; - if(dpy->synchandler) - dpy->synchandler(dpy); - _XIDHandler(dpy); - _XSeqSyncFunction(dpy); - return 0; -} - -void _XSetPrivSyncFunction(Display *dpy) -{ -#ifdef XTHREADS - if (dpy->lock_fns) - return; -#endif - if (!(dpy->flags & XlibDisplayPrivSync)) { - dpy->savedsynchandler = dpy->synchandler; - dpy->synchandler = _XPrivSyncFunction; - dpy->flags |= XlibDisplayPrivSync; - } -} - -void _XSetSeqSyncFunction(Display *dpy) -{ - if (sync_hazard(dpy)) - _XSetPrivSyncFunction (dpy); -} - -#if !USE_XCB -#ifdef XTHREADS -static void _XFlushInt( - register Display *dpy, - register xcondition_t cv); -#endif - -/* - * _XFlush - Flush the X request buffer. If the buffer is empty, no - * action is taken. This routine correctly handles incremental writes. - * This routine may have to be reworked if int < long. - */ -void _XFlush( - register Display *dpy) -{ -#ifdef XTHREADS - /* With multi-threading we introduce an internal routine to which - we can pass a condition variable to do locking correctly. */ - - _XFlushInt(dpy, NULL); -} - -/* _XFlushInt - Internal version of _XFlush used to do multi-threaded - * locking correctly. - */ - -static void _XFlushInt( - register Display *dpy, - register xcondition_t cv) -{ -#endif /* XTHREADS*/ - register long size, todo; - register int write_stat; - register char *bufindex; - _XExtension *ext; -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - int congestion; -#endif - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XFlushInt: Entering flush with [%d] bytes to write.\n", - (dpy->bufptr - dpy->buffer)); -#endif - /* This fix resets the bufptr to the front of the buffer so - * additional appends to the bufptr will not corrupt memory. Since - * the server is down, these appends are no-op's anyway but - * callers of _XFlush() are not verifying this before they call it. - */ - if (dpy->flags & XlibDisplayIOError) - { -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XFlushInt: Returning with I/O error detected.\n"); -#endif - dpy->bufptr = dpy->buffer; - dpy->last_req = (char *)&_dummy_request; - return; - } - -#ifdef XTHREADS -#ifdef NX_TRANS_SOCKET - while (dpy->flags & XlibDisplayWriting) { - if (_XGetIOError(dpy)) { - return; - } -#else - while (dpy->flags & XlibDisplayWriting) { -#endif - if (dpy->lock) { - ConditionWait(dpy, dpy->lock->writers); - } else { - _XWaitForWritable (dpy, cv); - } - } -#endif - size = todo = dpy->bufptr - dpy->buffer; - if (!size) return; -#ifdef XTHREADS - dpy->flags |= XlibDisplayWriting; - /* make sure no one else can put in data */ - dpy->bufptr = dpy->bufmax; -#endif - for (ext = dpy->flushes; ext; ext = ext->next_flush) - (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, size); - bufindex = dpy->buffer; - /* - * While write has not written the entire buffer, keep looping - * until the entire buffer is written. bufindex will be - * incremented and size decremented as buffer is written out. - */ - while (size) { - ESET(0); - write_stat = _X11TransWrite(dpy->trans_conn, - bufindex, (int) todo); - if (write_stat >= 0) { -#ifdef NX_TRANS_SOCKET - if (_NXDisplayWriteFunction != NULL) { - (*_NXDisplayWriteFunction)(dpy, write_stat); - } -#ifdef NX_TRANS_CHANGE - if (_NXDisplayCongestionFunction != NULL && - _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { - (*_NXDisplayCongestionFunction)(dpy, congestion); - } -#endif -#endif - size -= write_stat; - todo = size; - bufindex += write_stat; - } else if (ETEST()) { - _XWaitForWritable(dpy -#ifdef XTHREADS - , cv -#endif - ); -#ifdef SUNSYSV - } else if (ECHECK(0)) { - _XWaitForWritable(dpy -#ifdef XTHREADS - , cv -#endif - ); -#endif -#ifdef ESZTEST - } else if (ESZTEST()) { - if (todo > 1) - todo >>= 1; - else { - _XWaitForWritable(dpy -#ifdef XTHREADS - , cv -#endif - ); - } -#endif -#ifdef NX_TRANS_SOCKET - } else if (!ECHECK(EINTR) || - (_NXDisplayErrorFunction != NULL && - (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { - _XIOError(dpy); - return; - } -#else - } else if (!ECHECK(EINTR)) { - /* Write failed! */ - /* errno set by write system call. */ - _XIOError(dpy); - } -#endif -#ifdef NX_TRANS_SOCKET - if (_XGetIOError(dpy)) { - return; - } -#endif - } - dpy->last_req = (char *)&_dummy_request; - _XSetSeqSyncFunction(dpy); - dpy->bufptr = dpy->buffer; -#ifdef XTHREADS - dpy->flags &= ~XlibDisplayWriting; -#endif -} - -int -_XEventsQueued( - register Display *dpy, - int mode) -{ - register int len; - BytesReadable_t pend; - _XAlignedBuffer buf; - register xReply *rep; - char *read_buf; -#ifdef XTHREADS - int entry_event_serial_num; - struct _XCVList *cvl = NULL; - xthread_t self; - -#ifdef XTHREADS_DEBUG - printf("_XEventsQueued called in thread %x\n", XThread_Self()); -#endif -#endif /* XTHREADS*/ - - if (mode == QueuedAfterFlush) - { - _XFlush(dpy); - if (dpy->qlen) - return(dpy->qlen); - } -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - if (dpy->flags & XlibDisplayIOError) { - fprintf(stderr, "_XEventsQueued: Returning [%d] after display failure.\n", - dpy->qlen); - } -#endif - if (dpy->flags & XlibDisplayIOError) return(dpy->qlen); - -#ifdef XTHREADS - /* create our condition variable and append to list, - * unless we were called from within XProcessInternalConnection - * or XLockDisplay - */ - xthread_clear_id(self); - if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread) - || xthread_have_id (dpy->lock->locking_thread))) - /* some thread is in XProcessInternalConnection or XLockDisplay - so we have to see if we are it */ - self = XThread_Self(); - if (!xthread_have_id(self) - || (!xthread_equal(self, dpy->lock->conni_thread) - && !xthread_equal(self, dpy->lock->locking_thread))) { - /* In the multi-threaded case, if there is someone else - reading events, then there aren't any available, so - we just return. If we waited we would block. - */ - if (dpy->lock && dpy->lock->event_awaiters) - return dpy->qlen; - /* nobody here but us, so lock out any newcomers */ - cvl = QueueEventReaderLock(dpy); - } - - while (dpy->lock && cvl && dpy->lock->reply_first) { - /* note which events we have already seen so we'll know - if _XReply (in another thread) reads one */ - entry_event_serial_num = dpy->next_event_serial_num; - ConditionWait(dpy, cvl->cv); - /* did _XReply read an event we can return? */ - if (_XNewerQueuedEvent(dpy, entry_event_serial_num)) - { - UnlockNextEventReader(dpy); - return 0; - } - } -#endif /* XTHREADS*/ - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XEventsQueued: Checking bytes readable.\n"); -#endif - if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) -#ifdef NX_TRANS_SOCKET - { - _XIOError(dpy); - - return (dpy->qlen); - } -#else - _XIOError(dpy); -#endif -#ifdef XCONN_CHECK_FREQ - /* This is a crock, required because FIONREAD or equivalent is - * not guaranteed to detect a broken connection. - */ - if (!pend && !dpy->qlen && ++dpy->conn_checker >= XCONN_CHECK_FREQ) - { - int result; -#ifdef USE_POLL - struct pollfd filedes; -#else - fd_set r_mask; - static struct timeval zero_time; -#endif - - dpy->conn_checker = 0; -#ifdef USE_POLL -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XEventsQueued: Calling poll().\n"); -#endif - filedes.fd = dpy->fd; - filedes.events = POLLIN; - if ((result = poll(&filedes, 1, 0))) -#else -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XEventsQueued: Calling select().\n"); -#endif - FD_ZERO(&r_mask); - FD_SET(dpy->fd, &r_mask); - if ((result = Select(dpy->fd + 1, &r_mask, NULL, NULL, &zero_time))) -#endif - { - if (result > 0) - { - if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) -#ifdef NX_TRANS_SOCKET - { - _XIOError(dpy); - - return (dpy->qlen); - } -#else - _XIOError(dpy); -#endif - /* we should not get zero, if we do, force a read */ - if (!pend) - pend = SIZEOF(xReply); - } -#ifdef NX_TRANS_SOCKET - if (result <= 0) { - if ((result == -1 && !(ECHECK(EINTR) || ETEST())) || - (_NXDisplayErrorFunction != NULL && - (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { - _XIOError(dpy); - return (dpy->qlen); - } - } -#else - else if (result < 0 && !(ECHECK(EINTR) || ETEST())) -#endif - _XIOError(dpy); - } - } -#endif /* XCONN_CHECK_FREQ */ - if (!(len = pend)) { - /* _XFlush can enqueue events */ -#ifdef XTHREADS - if (cvl) -#endif - { - UnlockNextEventReader(dpy); - } -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XEventsQueued: Returning [%d].\n", dpy->qlen); -#endif - return(dpy->qlen); - } - /* Force a read if there is not enough data. Otherwise, - * a select() loop at a higher-level will spin undesirably, - * and we've seen at least one OS that appears to not update - * the result from FIONREAD once it has returned nonzero. - */ -#ifdef XTHREADS - if (dpy->lock && dpy->lock->reply_awaiters) { - read_buf = (char *)dpy->lock->reply_awaiters->buf; - len = SIZEOF(xReply); - } else -#endif /* XTHREADS*/ - { - read_buf = buf.buf; - - if (len < SIZEOF(xReply) -#ifdef XTHREADS - || dpy->async_handlers -#endif - ) - len = SIZEOF(xReply); - else if (len > BUFSIZE) - len = BUFSIZE; - len = (len / SIZEOF(xReply)) * SIZEOF(xReply); - } -#ifdef XCONN_CHECK_FREQ - dpy->conn_checker = 0; -#endif - - (void) _XRead (dpy, read_buf, (long) len); - -#ifdef NX_TRANS_SOCKET - if (_XGetIOError(dpy)) { - return(dpy->qlen); - } -#endif -#ifdef XTHREADS - /* what did we actually read: reply or event? */ - if (dpy->lock && dpy->lock->reply_awaiters) { - if (((xReply *)read_buf)->generic.type == X_Reply || - ((xReply *)read_buf)->generic.type == X_Error) - { - dpy->lock->reply_was_read = True; - dpy->lock->reply_first = True; - if (read_buf != (char *)dpy->lock->reply_awaiters->buf) - memcpy(dpy->lock->reply_awaiters->buf, read_buf, - len); - if (cvl) { - UnlockNextEventReader(dpy); - } - return(dpy->qlen); /* we read, so we can return */ - } else if (read_buf != buf.buf) - memcpy(buf.buf, read_buf, len); - } -#endif /* XTHREADS*/ - - STARTITERATE(rep,xReply,buf.buf,len > 0) { - if (rep->generic.type == X_Reply) { - int tmp = len; - RESETITERPTR(rep,xReply, - _XAsyncReply (dpy, rep, - ITERPTR(rep), &tmp, True)); - len = tmp; - pend = len; - } else { - if (rep->generic.type == X_Error) - _XError (dpy, (xError *)rep); - else /* must be an event packet */ - _XEnq (dpy, (xEvent *)rep); - INCITERPTR(rep,xReply); - len -= SIZEOF(xReply); - } - } ENDITERATE - -#ifdef XTHREADS - if (cvl) -#endif - { - UnlockNextEventReader(dpy); - } - return(dpy->qlen); -} - -/* _XReadEvents - Flush the output queue, - * then read as many events as possible (but at least 1) and enqueue them - */ -void _XReadEvents( - register Display *dpy) -{ - _XAlignedBuffer buf; - BytesReadable_t pend; - int len; - register xReply *rep; - Bool not_yet_flushed = True; - char *read_buf; - int i; - int entry_event_serial_num = dpy->next_event_serial_num; -#ifdef XTHREADS - struct _XCVList *cvl = NULL; - xthread_t self; - -#ifdef XTHREADS_DEBUG - printf("_XReadEvents called in thread %x\n", - XThread_Self()); -#endif - /* create our condition variable and append to list, - * unless we were called from within XProcessInternalConnection - * or XLockDisplay - */ - xthread_clear_id(self); - if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread) - || xthread_have_id (dpy->lock->locking_thread))) - /* some thread is in XProcessInternalConnection or XLockDisplay - so we have to see if we are it */ - self = XThread_Self(); - if (!xthread_have_id(self) - || (!xthread_equal(self, dpy->lock->conni_thread) - && !xthread_equal(self, dpy->lock->locking_thread))) - cvl = QueueEventReaderLock(dpy); -#endif /* XTHREADS */ - - do { -#ifdef XTHREADS - /* if it is not our turn to read an event off the wire, - wait til we're at head of list */ - if (dpy->lock && cvl && - (dpy->lock->event_awaiters != cvl || - dpy->lock->reply_first)) { - ConditionWait(dpy, cvl->cv); - continue; - } -#endif /* XTHREADS */ - /* find out how much data can be read */ - if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0) - { - _XIOError(dpy); -#ifdef NX_TRANS_SOCKET - return; -#endif - } - len = pend; - - /* must read at least one xEvent; if none is pending, then - we'll just flush and block waiting for it */ - if (len < SIZEOF(xEvent) -#ifdef XTHREADS - || dpy->async_handlers -#endif - ) { - len = SIZEOF(xEvent); - /* don't flush until the first time we would block */ - if (not_yet_flushed) { - _XFlush (dpy); - if (_XNewerQueuedEvent(dpy, entry_event_serial_num)) { - /* _XReply has read an event for us */ - goto got_event; - } - not_yet_flushed = False; - } - } - -#ifdef XTHREADS - /* If someone is waiting for a reply, gamble that - the reply will be the next thing on the wire - and read it into their buffer. */ - if (dpy->lock && dpy->lock->reply_awaiters) { - read_buf = (char *)dpy->lock->reply_awaiters->buf; - len = SIZEOF(xReply); - } else -#endif /* XTHREADS*/ - { - read_buf = buf.buf; - - /* but we won't read more than the max buffer size */ - if (len > BUFSIZE) - len = BUFSIZE; - - /* round down to an integral number of XReps */ - len = (len / SIZEOF(xEvent)) * SIZEOF(xEvent); - } - -#ifdef XTHREADS - if (xthread_have_id(self)) - /* save value we may have to stick in conni_thread */ - dpy->lock->reading_thread = self; -#endif /* XTHREADS */ - dpy->flags |= XlibDisplayReadEvents; - i = _XRead (dpy, read_buf, (long) len); - dpy->flags &= ~XlibDisplayReadEvents; -#ifdef NX_TRANS_SOCKET - if (dpy->flags & XlibDisplayIOError) - { -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XReadEvents: Returning with I/O error detected.\n"); -#endif - return; - } -#endif - if (i == -2) { - /* special flag from _XRead to say that internal connection has - done XPutBackEvent. Which we can use so we're done. */ - got_event: -#ifdef XTHREADS - if (dpy->lock && dpy->lock->lock_wait) { - if (dpy->lock->event_awaiters != cvl) - /* since it is not us, must be user lock thread */ - ConditionSignal(dpy, - dpy->lock->event_awaiters->cv); - (*dpy->lock->lock_wait)(dpy); - continue; - } -#endif - break; - } -#ifdef XTHREADS - if (xthread_have_id(self)) - xthread_clear_id(dpy->lock->reading_thread); - - /* what did we actually read: reply or event? */ - if (dpy->lock && dpy->lock->reply_awaiters) { - if (((xReply *)read_buf)->generic.type == X_Reply || - ((xReply *)read_buf)->generic.type == X_Error) - { - dpy->lock->reply_was_read = True; - dpy->lock->reply_first = True; - if (read_buf != (char *)dpy->lock->reply_awaiters->buf) - memcpy(dpy->lock->reply_awaiters->buf, - read_buf, len); - ConditionSignal(dpy, dpy->lock->reply_awaiters->cv); - continue; - } else if (read_buf != buf.buf) - memcpy(buf.buf, read_buf, len); - } -#endif /* XTHREADS */ - - STARTITERATE(rep,xReply,buf.buf,len > 0) { - if (rep->generic.type == X_Reply) { - RESETITERPTR(rep,xReply, - _XAsyncReply (dpy, rep, - ITERPTR(rep), &len, True)); - pend = len; - } else { - if (rep->generic.type == X_Error) - _XError (dpy, (xError *) rep); - else /* must be an event packet */ - { - if (rep->generic.type == GenericEvent) - { - int evlen; - evlen = (rep->generic.length << 2); - if (_XRead(dpy, &read_buf[len], evlen) == -2) - goto got_event; /* XXX: aargh! */ - } - - _XEnq (dpy, (xEvent *)rep); - } - INCITERPTR(rep,xReply); - len -= SIZEOF(xReply); - } - } ENDITERATE; - } while (!_XNewerQueuedEvent(dpy, entry_event_serial_num)); - - UnlockNextEventReader(dpy); -} - -/* - * _XRead - Read bytes from the socket taking into account incomplete - * reads. This routine may have to be reworked if int < long. - */ -int _XRead( - register Display *dpy, - register char *data, - register long size) -{ - register long bytes_read; -#ifdef XTHREADS - int original_size = size; -#endif -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - int congestion; -#endif - - if ((dpy->flags & XlibDisplayIOError) || size == 0) - return 0; - ESET(0); -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - while (1) { - /* - * Need to check the congestion state - * after the read so split the statement - * in multiple blocks. - */ - - bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size); - if (_NXDisplayCongestionFunction != NULL && - _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { - (*_NXDisplayCongestionFunction)(dpy, congestion); - } - if (bytes_read == size) { - break; - } -#else - while ((bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size)) - != size) { -#endif - - if (bytes_read > 0) { - size -= bytes_read; - data += bytes_read; - } - else if (ETEST()) { - if (_XWaitForReadable(dpy) == -2) - return -2; /* internal connection did XPutBackEvent */ - ESET(0); - } -#ifdef SUNSYSV - else if (ECHECK(0)) { - if (_XWaitForReadable(dpy) == -2) - return -2; /* internal connection did XPutBackEvent */ - } -#endif - else if (bytes_read == 0) { - /* Read failed because of end of file! */ - ESET(EPIPE); -#ifdef NX_TRANS_SOCKET - _XIOError(dpy); - - return -1; -#else - _XIOError(dpy); -#endif - } - - else /* bytes_read is less than 0; presumably -1 */ { - /* If it's a system call interrupt, it's not an error. */ -#ifdef NX_TRANS_SOCKET - if (!ECHECK(EINTR) || - (_NXDisplayErrorFunction != NULL && - (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { - _XIOError(dpy); - return -1; - } -#else - if (!ECHECK(EINTR)) - _XIOError(dpy); -#endif - } -#ifdef NX_TRANS_SOCKET - if (_XGetIOError(dpy)) { - return -1; - } -#endif - } -#ifdef XTHREADS - if (dpy->lock && dpy->lock->reply_bytes_left > 0) - { - dpy->lock->reply_bytes_left -= original_size; - if (dpy->lock->reply_bytes_left == 0) { - dpy->flags &= ~XlibDisplayReply; - UnlockNextReplyReader(dpy); - } - } -#endif /* XTHREADS*/ - return 0; -} -#endif /* !USE_XCB */ - -#ifdef LONG64 -void _XRead32( - Display *dpy, - register long *data, - long len) -{ - register int *buf; - register long i; - - if (len) { - (void) _XRead(dpy, (char *)data, len); - i = len >> 2; - buf = (int *)data + i; - data += i; - while (--i >= 0) - *--data = *--buf; - } -} -#endif /* LONG64 */ - - - -#if !USE_XCB -/* - * _XReadPad - Read bytes from the socket taking into account incomplete - * reads. If the number of bytes is not 0 mod 4, read additional pad - * bytes. This routine may have to be reworked if int < long. - */ -void _XReadPad( - register Display *dpy, - register char *data, - register long size) -{ - register long bytes_read; - struct iovec iov[2]; - char pad[3]; -#ifdef XTHREADS - int original_size; -#endif -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - int congestion; -#endif - - if ((dpy->flags & XlibDisplayIOError) || size == 0) return; - iov[0].iov_len = (int)size; - iov[0].iov_base = data; - /* - * The following hack is used to provide 32 bit long-word - * aligned padding. The [1] vector is of length 0, 1, 2, or 3, - * whatever is needed. - */ - - iov[1].iov_len = -size & 3; - iov[1].iov_base = pad; - size += iov[1].iov_len; -#ifdef XTHREADS - original_size = size; -#endif - ESET(0); -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - while (1) { - bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2); - if (_NXDisplayCongestionFunction != NULL && - _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { - (*_NXDisplayCongestionFunction)(dpy, congestion); - } - if (bytes_read == size) { - break; - } -#else - while ((bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2)) != size) { -#endif - - if (bytes_read > 0) { - size -= bytes_read; - if (iov[0].iov_len < bytes_read) { - int pad_bytes_read = bytes_read - iov[0].iov_len; - iov[1].iov_len -= pad_bytes_read; - iov[1].iov_base = - (char *)iov[1].iov_base + pad_bytes_read; - iov[0].iov_len = 0; - } - else { - iov[0].iov_len -= bytes_read; - iov[0].iov_base = (char *)iov[0].iov_base + bytes_read; - } - } - else if (ETEST()) { - _XWaitForReadable(dpy); - ESET(0); - } -#ifdef SUNSYSV - else if (ECHECK(0)) { - _XWaitForReadable(dpy); - } -#endif - else if (bytes_read == 0) { - /* Read failed because of end of file! */ - ESET(EPIPE); -#ifdef NX_TRANS_SOCKET - _XIOError(dpy); - - return; -#else - _XIOError(dpy); -#endif - } - - else /* bytes_read is less than 0; presumably -1 */ { - /* If it's a system call interrupt, it's not an error. */ -#ifdef NX_TRANS_SOCKET - if (!ECHECK(EINTR) || - (_NXDisplayErrorFunction != NULL && - (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { - _XIOError(dpy); - return; - } -#else - if (!ECHECK(EINTR)) - _XIOError(dpy); -#endif - } -#ifdef NX_TRANS_SOCKET - if (_XGetIOError(dpy)) { - return; - } -#endif - } -#ifdef XTHREADS - if (dpy->lock && dpy->lock->reply_bytes_left > 0) - { - dpy->lock->reply_bytes_left -= original_size; - if (dpy->lock->reply_bytes_left == 0) { - dpy->flags &= ~XlibDisplayReply; - UnlockNextReplyReader(dpy); - } - } -#endif /* XTHREADS*/ -} - -/* - * _XSend - Flush the buffer and send the client data. 32 bit word aligned - * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. - * This routine may have to be reworked if int < long; - */ -void -_XSend ( - register Display *dpy, - _Xconst char *data, - register long size) -{ - struct iovec iov[3]; - static char const pad[3] = {0, 0, 0}; - /* XText8 and XText16 require that the padding bytes be zero! */ - - long skip, dbufsize, padsize, total, todo; - _XExtension *ext; -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE) - int congestion; -#endif - -#ifdef NX_TRANS_SOCKET -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XSend: Sending data with [%d] bytes to write.\n", - (dpy->bufptr - dpy->buffer)); -#endif - if (!size || (dpy->flags & XlibDisplayIOError)) - { - if (dpy->flags & XlibDisplayIOError) - { -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XSend: Returning with I/O error detected.\n"); -#endif - dpy->bufptr = dpy->buffer; - dpy->last_req = (char *)&_dummy_request; - } - - return; - } -#else - if (!size || (dpy->flags & XlibDisplayIOError)) return; -#endif - dbufsize = dpy->bufptr - dpy->buffer; -#ifdef XTHREADS - dpy->flags |= XlibDisplayWriting; - /* make sure no one else can put in data */ - dpy->bufptr = dpy->bufmax; -#endif - padsize = -size & 3; - for (ext = dpy->flushes; ext; ext = ext->next_flush) { - (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, dbufsize); - (*ext->before_flush)(dpy, &ext->codes, (char *)data, size); - if (padsize) - (*ext->before_flush)(dpy, &ext->codes, pad, padsize); - } - skip = 0; - todo = total = dbufsize + size + padsize; - - /* - * There are 3 pieces that may need to be written out: - * - * o whatever is in the display buffer - * o the data passed in by the user - * o any padding needed to 32bit align the whole mess - * - * This loop looks at all 3 pieces each time through. It uses skip - * to figure out whether or not a given piece is needed. - */ - while (total) { - long before = skip; /* amount of whole thing written */ - long remain = todo; /* amount to try this time, <= total */ - int i = 0; - long len; - - /* You could be very general here and have "in" and "out" iovecs - * and write a loop without using a macro, but what the heck. This - * translates to: - * - * how much of this piece is new? - * if more new then we are trying this time, clamp - * if nothing new - * then bump down amount already written, for next piece - * else put new stuff in iovec, will need all of next piece - * - * Note that todo had better be at least 1 or else we'll end up - * writing 0 iovecs. - */ -#define InsertIOV(pointer, length) \ - len = (length) - before; \ - if (len > remain) \ - len = remain; \ - if (len <= 0) { \ - before = (-len); \ - } else { \ - iov[i].iov_len = len; \ - iov[i].iov_base = (pointer) + before; \ - i++; \ - remain -= len; \ - before = 0; \ - } - - InsertIOV (dpy->buffer, dbufsize) - InsertIOV ((char *)data, size) - InsertIOV ((char *)pad, padsize) - - ESET(0); - if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) { -#ifdef NX_TRANS_SOCKET - if (_NXDisplayWriteFunction != NULL) { - (*_NXDisplayWriteFunction)(dpy, len); - } -#ifdef NX_TRANS_CHANGE - if (_NXDisplayCongestionFunction != NULL && - _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) { - (*_NXDisplayCongestionFunction)(dpy, congestion); - } -#endif -#endif - skip += len; - total -= len; - todo = total; - } else if (ETEST()) { - _XWaitForWritable(dpy -#ifdef XTHREADS - , NULL -#endif - ); -#ifdef SUNSYSV - } else if (ECHECK(0)) { - _XWaitForWritable(dpy -#ifdef XTHREADS - , NULL -#endif - ); -#endif -#ifdef ESZTEST - } else if (ESZTEST()) { - if (todo > 1) - todo >>= 1; - else { - _XWaitForWritable(dpy -#ifdef XTHREADS - , NULL -#endif - ); - } -#endif -#ifdef NX_TRANS_SOCKET - } else if (!ECHECK(EINTR) || - (_NXDisplayErrorFunction != NULL && - (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) { - _XIOError(dpy); - return; - } -#else - } else if (!ECHECK(EINTR)) { - _XIOError(dpy); - } -#endif -#ifdef NX_TRANS_SOCKET - if (_XGetIOError(dpy)) { - return; - } -#endif - } - dpy->last_req = (char *) & _dummy_request; - _XSetSeqSyncFunction(dpy); - dpy->bufptr = dpy->buffer; -#ifdef XTHREADS - dpy->flags &= ~XlibDisplayWriting; -#endif - return; -} - -static void -_XGetMiscCode( - register Display *dpy) -{ - xQueryExtensionReply qrep; - register xQueryExtensionReq *qreq; - xXCMiscGetVersionReply vrep; - register xXCMiscGetVersionReq *vreq; - - if (dpy->xcmisc_opcode) - return; - GetReq(QueryExtension, qreq); - qreq->nbytes = sizeof(XCMiscExtensionName) - 1; - qreq->length += (qreq->nbytes+(unsigned)3)>>2; - _XSend(dpy, XCMiscExtensionName, (long)qreq->nbytes); - if (!_XReply (dpy, (xReply *)&qrep, 0, xTrue)) - dpy->xcmisc_opcode = -1; - else { - GetReq(XCMiscGetVersion, vreq); - vreq->reqType = qrep.major_opcode; - vreq->miscReqType = X_XCMiscGetVersion; - vreq->majorVersion = XCMiscMajorVersion; - vreq->minorVersion = XCMiscMinorVersion; - if (!_XReply (dpy, (xReply *)&vrep, 0, xTrue)) - dpy->xcmisc_opcode = -1; - else - dpy->xcmisc_opcode = qrep.major_opcode; - } -} - -void -_XIDHandler( - register Display *dpy) -{ - xXCMiscGetXIDRangeReply grep; - register xXCMiscGetXIDRangeReq *greq; - - if (dpy->resource_max == dpy->resource_mask + 1) { - _XGetMiscCode(dpy); - if (dpy->xcmisc_opcode > 0) { - GetReq(XCMiscGetXIDRange, greq); - greq->reqType = dpy->xcmisc_opcode; - greq->miscReqType = X_XCMiscGetXIDRange; - if (_XReply (dpy, (xReply *)&grep, 0, xTrue) && grep.count) { - dpy->resource_id = ((grep.start_id - dpy->resource_base) >> - dpy->resource_shift); - dpy->resource_max = dpy->resource_id; - if (grep.count > 5) - dpy->resource_max += grep.count - 6; - dpy->resource_max <<= dpy->resource_shift; - } - sync_while_locked(dpy); - } - } -} - -/* - * _XAllocID - resource ID allocation routine. - */ -XID _XAllocID( - register Display *dpy) -{ - XID id; - - id = dpy->resource_id << dpy->resource_shift; - if (id >= dpy->resource_max) { - _XSetPrivSyncFunction(dpy); - dpy->resource_max = dpy->resource_mask + 1; - } - if (id <= dpy->resource_mask) { - dpy->resource_id++; - return (dpy->resource_base + id); - } - if (id != 0x10000000) { - (void) fprintf(stderr, - "Xlib: resource ID allocation space exhausted!\n"); - id = 0x10000000; - dpy->resource_id = id >> dpy->resource_shift; - } - return id; -} - -/* - * _XAllocIDs - multiple resource ID allocation routine. - */ -void _XAllocIDs( - register Display *dpy, - XID *ids, - int count) -{ - XID id; - int i; - xXCMiscGetXIDListReply grep; - register xXCMiscGetXIDListReq *greq; - - id = dpy->resource_id << dpy->resource_shift; - if (dpy->resource_max <= dpy->resource_mask && - id <= dpy->resource_mask && - (dpy->resource_max - id) > ((count - 1) << dpy->resource_shift)) { - id += dpy->resource_base; - for (i = 0; i < count; i++) { - ids[i] = id; - id += (1 << dpy->resource_shift); - dpy->resource_id++; - } - return; - } - grep.count = 0; - _XGetMiscCode(dpy); - if (dpy->xcmisc_opcode > 0) { - GetReq(XCMiscGetXIDList, greq); - greq->reqType = dpy->xcmisc_opcode; - greq->miscReqType = X_XCMiscGetXIDList; - greq->count = count; - if (_XReply(dpy, (xReply *)&grep, 0, xFalse) && grep.count) { - _XRead32(dpy, (long *) ids, 4L * (long) (grep.count)); - for (i = 0; i < grep.count; i++) { - id = (ids[i] - dpy->resource_base) >> dpy->resource_shift; - if (id >= dpy->resource_id) - dpy->resource_id = id; - } - if (id >= dpy->resource_max) { - _XSetPrivSyncFunction(dpy); - dpy->resource_max = dpy->resource_mask + 1; - } - } - } - for (i = grep.count; i < count; i++) - ids[i] = XAllocID(dpy); -} -#endif /* !USE_XCB */ - -/* - * The hard part about this is that we only get 16 bits from a reply. - * We have three values that will march along, with the following invariant: - * dpy->last_request_read <= rep->sequenceNumber <= dpy->request - * We have to keep - * dpy->request - dpy->last_request_read < 2^16 - * or else we won't know for sure what value to use in events. We do this - * by forcing syncs when we get close. - */ - -unsigned long -_XSetLastRequestRead( - register Display *dpy, - register xGenericReply *rep) -{ - register unsigned long newseq, lastseq; - - lastseq = dpy->last_request_read; - /* - * KeymapNotify has no sequence number, but is always guaranteed - * to immediately follow another event, except when generated via - * SendEvent (hmmm). - */ - if ((rep->type & 0x7f) == KeymapNotify) - return(lastseq); - - newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber; - - if (newseq < lastseq) { - newseq += 0x10000; - if (newseq > dpy->request) { -#ifdef NX_TRANS_SOCKET - if (_NXLostSequenceFunction != NULL) - { - (*_NXLostSequenceFunction)(dpy, newseq, dpy->request, - (unsigned int) rep->type); - } - else -#endif /* #ifdef NX_TRANS_SOCKET */ - { - (void) fprintf (stderr, - "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", - newseq, dpy->request, - (unsigned int) rep->type); - } - newseq -= 0x10000; - } - } - - dpy->last_request_read = newseq; - return(newseq); -} - -#if !USE_XCB -/* - * _XReply - Wait for a reply packet and copy its contents into the - * specified rep. Meanwhile we must handle error and event packets that - * we may encounter. - */ -Status -_XReply ( - register Display *dpy, - register xReply *rep, - int extra, /* number of 32-bit words expected after the reply */ - Bool discard) /* should I discard data following "extra" words? */ -{ - /* Pull out the serial number now, so that (currently illegal) requests - * generated by an error handler don't confuse us. - */ - unsigned long cur_request = dpy->request; -#ifdef XTHREADS - struct _XCVList *cvl; -#endif -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XReply: Going to wait for an X reply.\n"); -#endif - -#ifdef NX_TRANS_SOCKET - if (dpy->flags & XlibDisplayIOError) - { -#ifdef NX_TRANS_DEBUG - fprintf(stderr, "_XReply: Returning 0 with I/O error detected.\n"); -#endif - return 0; - } -#else - if (dpy->flags & XlibDisplayIOError) - return 0; -#endif - -#ifdef XTHREADS - /* create our condition variable and append to list */ - cvl = QueueReplyReaderLock(dpy); - if (cvl) { - cvl->buf = rep; - if (dpy->lock->reply_awaiters == cvl && !dpy->lock->event_awaiters) - dpy->lock->reply_first = True; - } - -#ifdef XTHREADS_DEBUG - printf("_XReply called in thread %x, adding %x to cvl\n", - XThread_Self(), cvl); -#endif - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XReply: Going to flush the display buffer.\n"); -#endif - _XFlushInt(dpy, cvl ? cvl->cv : NULL); - /* if it is not our turn to read a reply off the wire, - * wait til we're at head of list. if there is an event waiter, - * and our reply hasn't been read, they'll be in select and will - * hand control back to us next. - */ - if(dpy->lock && - (dpy->lock->reply_awaiters != cvl || !dpy->lock->reply_first)) { - ConditionWait(dpy, cvl->cv); - } - dpy->flags |= XlibDisplayReply; -#else /* XTHREADS else */ - _XFlush(dpy); -#endif - -#ifdef NX_TRANS_SOCKET - /* - * We are going to block waiting for the remote - * X server. Be sure that the proxy has flushed - * all the data. - */ - -#ifdef NX_TRANS_TEST - fprintf(stderr, "_XReply: Requesting a flush of the NX transport.\n"); -#endif - NXTransFlush(dpy->fd); -#endif - - for (;;) { -#ifdef XTHREADS - /* Did another thread's _XReadEvents get our reply by accident? */ - if (!dpy->lock || !dpy->lock->reply_was_read) -#endif - (void) _XRead(dpy, (char *)rep, (long)SIZEOF(xReply)); -#ifdef XTHREADS - if (dpy->lock) - dpy->lock->reply_was_read = False; -#endif - - switch ((int)rep->generic.type) { - - case X_Reply: - /* Reply received. Fast update for synchronous replies, - * but deal with multiple outstanding replies. - */ - if (rep->generic.sequenceNumber == (cur_request & 0xffff)) - dpy->last_request_read = cur_request; - else { - int pend = SIZEOF(xReply); - if (_XAsyncReply(dpy, rep, (char *)rep, &pend, False) - != (char *)rep) - continue; - } - if (extra <= rep->generic.length) { - if (extra > 0) - /* - * Read the extra data into storage immediately - * following the GenericReply structure. - */ - (void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)), - ((long)extra) << 2); - if (discard) { - if (extra < rep->generic.length) - _XEatData(dpy, (rep->generic.length - extra) << 2); - } -#ifdef XTHREADS - if (dpy->lock) { - if (discard) { - dpy->lock->reply_bytes_left = 0; - } else { - dpy->lock->reply_bytes_left = - (rep->generic.length - extra) << 2; - } - if (dpy->lock->reply_bytes_left == 0) { - dpy->flags &= ~XlibDisplayReply; - UnlockNextReplyReader(dpy); - } - } else - dpy->flags &= ~XlibDisplayReply; -#endif - return 1; - } - /* - *if we get here, then extra > rep->generic.length--meaning we - * read a reply that's shorter than we expected. This is an - * error, but we still need to figure out how to handle it... - */ - (void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)), - ((long) rep->generic.length) << 2); - dpy->flags &= ~XlibDisplayReply; - UnlockNextReplyReader(dpy); -#ifdef NX_TRANS_SOCKET - /* - * The original code has provision - * for returning already. - */ -#endif - _XIOError (dpy); - return (0); - - case X_Error: - { - register _XExtension *ext; - register Bool ret = False; - int ret_code; - xError *err = (xError *) rep; - unsigned long serial; - - dpy->flags &= ~XlibDisplayReply; - serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); - if (serial == cur_request) - /* do not die on "no such font", "can't allocate", - "can't grab" failures */ - switch ((int)err->errorCode) { - case BadName: - switch (err->majorCode) { - case X_LookupColor: - case X_AllocNamedColor: - UnlockNextReplyReader(dpy); - return(0); - } - break; - case BadFont: - if (err->majorCode == X_QueryFont) { - UnlockNextReplyReader(dpy); - return (0); - } - break; - case BadAlloc: - case BadAccess: - UnlockNextReplyReader(dpy); - return (0); - } - /* - * we better see if there is an extension who may - * want to suppress the error. - */ - for (ext = dpy->ext_procs; !ret && ext; ext = ext->next) { - if (ext->error) - ret = (*ext->error)(dpy, err, &ext->codes, &ret_code); - } - if (!ret) { - _XError(dpy, err); - ret_code = 0; - } - if (serial == cur_request) { - UnlockNextReplyReader(dpy); - return(ret_code); - } - - } /* case X_Error */ - break; - default: - _XEnq(dpy, (xEvent *) rep); -#ifdef XTHREADS - if (dpy->lock && dpy->lock->event_awaiters) - ConditionSignal(dpy, dpy->lock->event_awaiters->cv); -#endif - break; - } -#ifdef NX_TRANS_SOCKET - if (_XGetIOError(dpy)) { - UnlockNextReplyReader(dpy); - return 0; - } -#endif - } -} - -static char * -_XAsyncReply( - Display *dpy, - register xReply *rep, - char *buf, - register int *lenp, - Bool discard) -{ - register _XAsyncHandler *async, *next; - register int len; - register Bool consumed = False; - char *nbuf; - - (void) _XSetLastRequestRead(dpy, &rep->generic); - len = SIZEOF(xReply) + (rep->generic.length << 2); - if (len < SIZEOF(xReply)) { -#ifdef NX_TRANS_SOCKET - - /* - * The original code has provision - * for returning already. - */ - -#endif - _XIOError (dpy); - buf += *lenp; - *lenp = 0; - return buf; - } - - for (async = dpy->async_handlers; async; async = next) { - next = async->next; - if ((consumed = (*async->handler)(dpy, rep, buf, *lenp, async->data))) - break; - } - if (!consumed) { - if (!discard) - return buf; - (void) fprintf(stderr, - "Xlib: unexpected async reply (sequence 0x%lx)!\n", - dpy->last_request_read); -#ifdef XTHREADS -#ifdef XTHREADS_DEBUG - printf("thread %x, unexpected async reply\n", XThread_Self()); -#endif -#endif - if (len > *lenp) - _XEatData(dpy, len - *lenp); - } - if (len < SIZEOF(xReply)) - { -#ifdef NX_TRANS_SOCKET - - /* - * The original code has provision - * for returning already. - */ - -#endif - _XIOError (dpy); - buf += *lenp; - *lenp = 0; - return buf; - } - if (len >= *lenp) { - buf += *lenp; - *lenp = 0; - return buf; - } - *lenp -= len; - buf += len; - len = *lenp; - nbuf = buf; - while (len > SIZEOF(xReply)) { - if (*buf == X_Reply) - return nbuf; - buf += SIZEOF(xReply); - len -= SIZEOF(xReply); - } - if (len > 0 && len < SIZEOF(xReply)) { - buf = nbuf; - len = SIZEOF(xReply) - len; - nbuf -= len; - memmove(nbuf, buf, *lenp); - (void) _XRead(dpy, nbuf + *lenp, (long)len); - *lenp += len; - } - return nbuf; -} -#endif /* !USE_XCB */ - -/* - * Support for internal connections, such as an IM might use. - * By Stephen Gildea, X Consortium, September 1993 - */ - -/* _XRegisterInternalConnection - * Each IM (or Xlib extension) that opens a file descriptor that Xlib should - * include in its select/poll mask must call this function to register the - * fd with Xlib. Any XConnectionWatchProc registered by XAddConnectionWatch - * will also be called. - * - * Whenever Xlib detects input available on fd, it will call callback - * with call_data to process it. If non-Xlib code calls select/poll - * and detects input available, it must call XProcessInternalConnection, - * which will call the associated callback. - * - * Non-Xlib code can learn about these additional fds by calling - * XInternalConnectionNumbers or, more typically, by registering - * a XConnectionWatchProc with XAddConnectionWatch - * to be called when fds are registered or unregistered. - * - * Returns True if registration succeeded, False if not, typically - * because could not allocate memory. - * Assumes Display locked when called. - */ -Status -_XRegisterInternalConnection( - Display* dpy, - int fd, - _XInternalConnectionProc callback, - XPointer call_data -) -{ - struct _XConnectionInfo *new_conni, **iptr; - struct _XConnWatchInfo *watchers; - XPointer *wd; - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XRegisterInternalConnection: Got called.\n"); -#endif - new_conni = Xmalloc(sizeof(struct _XConnectionInfo)); - if (!new_conni) - return 0; - new_conni->watch_data = Xmalloc(dpy->watcher_count * sizeof(XPointer)); - if (!new_conni->watch_data) { - Xfree(new_conni); - return 0; - } - new_conni->fd = fd; - new_conni->read_callback = callback; - new_conni->call_data = call_data; - new_conni->next = NULL; - /* link new structure onto end of list */ - for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next) - ; - *iptr = new_conni; - dpy->im_fd_length++; - _XPollfdCacheAdd(dpy, fd); - - for (watchers=dpy->conn_watchers, wd=new_conni->watch_data; - watchers; - watchers=watchers->next, wd++) { - *wd = NULL; /* for cleanliness */ - (*watchers->fn) (dpy, watchers->client_data, fd, True, wd); - } - - return 1; -} - -/* _XUnregisterInternalConnection - * Each IM (or Xlib extension) that closes a file descriptor previously - * registered with _XRegisterInternalConnection must call this function. - * Any XConnectionWatchProc registered by XAddConnectionWatch - * will also be called. - * - * Assumes Display locked when called. - */ -void -_XUnregisterInternalConnection( - Display* dpy, - int fd -) -{ - struct _XConnectionInfo *info_list, **prev; - struct _XConnWatchInfo *watch; - XPointer *wd; - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XUnregisterInternalConnection: Got called.\n"); -#endif - for (prev = &dpy->im_fd_info; (info_list = *prev); - prev = &info_list->next) { - if (info_list->fd == fd) { - *prev = info_list->next; - dpy->im_fd_length--; - for (watch=dpy->conn_watchers, wd=info_list->watch_data; - watch; - watch=watch->next, wd++) { - (*watch->fn) (dpy, watch->client_data, fd, False, wd); - } - Xfree (info_list->watch_data); - Xfree (info_list); - break; - } - } - _XPollfdCacheDel(dpy, fd); -} - -/* XInternalConnectionNumbers - * Returns an array of fds and an array of corresponding call data. - * Typically a XConnectionWatchProc registered with XAddConnectionWatch - * will be used instead of this function to discover - * additional fds to include in the select/poll mask. - * - * The list is allocated with Xmalloc and should be freed by the caller - * with Xfree; - */ -Status -XInternalConnectionNumbers( - Display *dpy, - int **fd_return, - int *count_return -) -{ - int count; - struct _XConnectionInfo *info_list; - int *fd_list; - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "XInternalConnectionNumbers: Got called.\n"); -#endif - LockDisplay(dpy); - count = 0; - for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) - count++; - fd_list = Xmalloc (count * sizeof(int)); - if (!fd_list) { - UnlockDisplay(dpy); - return 0; - } - count = 0; - for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { - fd_list[count] = info_list->fd; - count++; - } - UnlockDisplay(dpy); - - *fd_return = fd_list; - *count_return = count; - return 1; -} - -void _XProcessInternalConnection( - Display *dpy, - struct _XConnectionInfo *conn_info) -{ - dpy->flags |= XlibDisplayProcConni; -#if defined(XTHREADS) && !USE_XCB - if (dpy->lock) { - /* check cache to avoid call to thread_self */ - if (xthread_have_id(dpy->lock->reading_thread)) - dpy->lock->conni_thread = dpy->lock->reading_thread; - else - dpy->lock->conni_thread = XThread_Self(); - } -#endif /* XTHREADS && !USE_XCB */ - UnlockDisplay(dpy); - (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data); - LockDisplay(dpy); -#if defined(XTHREADS) && !USE_XCB - if (dpy->lock) - xthread_clear_id(dpy->lock->conni_thread); -#endif /* XTHREADS && !USE_XCB */ - dpy->flags &= ~XlibDisplayProcConni; -} - -/* XProcessInternalConnection - * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection - * for this fd. - * The Display is NOT locked during the call. - */ -void -XProcessInternalConnection( - Display* dpy, - int fd -) -{ - struct _XConnectionInfo *info_list; - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "XProcessInternalConnection: Got called.\n"); -#endif - - LockDisplay(dpy); - for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { - if (info_list->fd == fd) { - _XProcessInternalConnection(dpy, info_list); - break; - } - } - UnlockDisplay(dpy); -} - -/* XAddConnectionWatch - * Register a callback to be called whenever _XRegisterInternalConnection - * or _XUnregisterInternalConnection is called. - * Callbacks are called with the Display locked. - * If any connections are already registered, the callback is immediately - * called for each of them. - */ -Status -XAddConnectionWatch( - Display* dpy, - XConnectionWatchProc callback, - XPointer client_data -) -{ - struct _XConnWatchInfo *new_watcher, **wptr; - struct _XConnectionInfo *info_list; - XPointer *wd_array; - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "XAddConnectionWatch: Got called.\n"); -#endif - LockDisplay(dpy); - - /* allocate new watch data */ - for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { - wd_array = Xrealloc(info_list->watch_data, - (dpy->watcher_count + 1) * sizeof(XPointer)); - if (!wd_array) { - UnlockDisplay(dpy); - return 0; - } - info_list->watch_data = wd_array; - wd_array[dpy->watcher_count] = NULL; /* for cleanliness */ - } - - new_watcher = Xmalloc(sizeof(struct _XConnWatchInfo)); - if (!new_watcher) { - UnlockDisplay(dpy); - return 0; - } - new_watcher->fn = callback; - new_watcher->client_data = client_data; - new_watcher->next = NULL; - - /* link new structure onto end of list */ - for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next) - ; - *wptr = new_watcher; - dpy->watcher_count++; - - /* call new watcher on all currently registered fds */ - for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) { - (*callback) (dpy, client_data, info_list->fd, True, - info_list->watch_data + dpy->watcher_count - 1); - } - - UnlockDisplay(dpy); - return 1; -} - -/* XRemoveConnectionWatch - * Unregister a callback registered by XAddConnectionWatch. - * Both callback and client_data must match what was passed to - * XAddConnectionWatch. - */ -void -XRemoveConnectionWatch( - Display* dpy, - XConnectionWatchProc callback, - XPointer client_data -) -{ - struct _XConnWatchInfo *watch; - struct _XConnWatchInfo *previous = NULL; - struct _XConnectionInfo *conni; - int counter = 0; - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "XRemoveConnectionWatch: Got called.\n"); -#endif - LockDisplay(dpy); - for (watch=dpy->conn_watchers; watch; watch=watch->next) { - if (watch->fn == callback && watch->client_data == client_data) { - if (previous) - previous->next = watch->next; - else - dpy->conn_watchers = watch->next; - Xfree (watch); - dpy->watcher_count--; - /* remove our watch_data for each connection */ - for (conni=dpy->im_fd_info; conni; conni=conni->next) { - /* don't bother realloc'ing; these arrays are small anyway */ - /* overlapping */ - memmove(conni->watch_data+counter, - conni->watch_data+counter+1, - dpy->watcher_count - counter); - } - break; - } - previous = watch; - counter++; - } - UnlockDisplay(dpy); -} - -/* end of internal connections support */ - - -#if !USE_XCB -/* Read and discard "n" 8-bit bytes of data */ - -void _XEatData( - Display *dpy, - register unsigned long n) -{ -#define SCRATCHSIZE 2048 - char buf[SCRATCHSIZE]; - -#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) - fprintf(stderr, "_XEatData: Going to eat [%ld] bytes of data from descriptor [%d].\n", - n, dpy->fd); -#endif - while (n > 0) { - register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n; - (void) _XRead (dpy, buf, bytes_read); - n -= bytes_read; - } -#undef SCRATCHSIZE -} - -/* - Port from libXfixes commit - b031e3b60fa1af9e49449f23d4a84395868be3ab We need this here to - enable linking of current libXrender against libNX_X11 instead of - the system's libX11 - - The original implementation of this function (libX11 commit - 9f5d83706543696fc944c1835a403938c06f2cc5) uses xcb stuff which we - do not have in libNX_X11. So we take a workaround from another - lib. This workaround had been implemented temporarily in a couple - of X libs, see e.g. https://lists.x.org/archives/xorg-devel/2013-July/036763.html. -*/ -#include <nx-X11/Xmd.h> /* for LONG64 on 64-bit platforms */ -#include <limits.h> - -void _XEatDataWords(Display *dpy, unsigned long n) -{ -#ifndef LONG64 - if (n >= (ULONG_MAX >> 2)) - _XIOError(dpy); -#endif - _XEatData (dpy, n << 2); -} -#endif /* !USE_XCB */ - -/* Cookie jar implementation - dpy->cookiejar is a linked list. _XEnq receives the events but leaves - them in the normal EQ. _XStoreEvent returns the cookie event (minus - data pointer) and adds it to the cookiejar. _XDeq just removes - the entry like any other event but resets the data pointer for - cookie events (to avoid double-free, the memory is re-used by Xlib). - - _XFetchEventCookie (called from XGetEventData) removes a cookie from the - jar. _XFreeEventCookies removes all unclaimed cookies from the jar - (called by XNextEvent). - - _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the - normal EQ. - */ - -#include "utlist.h" -struct stored_event { - XGenericEventCookie ev; - struct stored_event *prev; - struct stored_event *next; -}; - -Bool -_XIsEventCookie(Display *dpy, XEvent *ev) -{ - return (ev->xcookie.type == GenericEvent && - dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL); -} - -/** - * Free all events in the event list. - */ -void -_XFreeEventCookies(Display *dpy) -{ - struct stored_event **head, *e, *tmp; - - if (!dpy->cookiejar) - return; - - head = (struct stored_event**)&dpy->cookiejar; - - DL_FOREACH_SAFE(*head, e, tmp) { - if (dpy->cookiejar == e) - dpy->cookiejar = NULL; - XFree(e->ev.data); - XFree(e); - } -} - -/** - * Add an event to the display's event list. This event must be freed on the - * next call to XNextEvent(). - */ -void -_XStoreEventCookie(Display *dpy, XEvent *event) -{ - XGenericEventCookie* cookie = &event->xcookie; - struct stored_event **head, *add; - - if (!_XIsEventCookie(dpy, event)) - return; - - head = (struct stored_event**)(&dpy->cookiejar); - - add = Xmalloc(sizeof(struct stored_event)); - if (!add) { - ESET(ENOMEM); - _XIOError(dpy); - } - add->ev = *cookie; - DL_APPEND(*head, add); - cookie->data = NULL; /* don't return data yet, must be claimed */ -} - -/** - * Return the event with the given cookie and remove it from the list. - */ -Bool -_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev) -{ - Bool ret = False; - struct stored_event **head, *event; - head = (struct stored_event**)&dpy->cookiejar; - - if (!_XIsEventCookie(dpy, (XEvent*)ev)) - return ret; - - DL_FOREACH(*head, event) { - if (event->ev.cookie == ev->cookie && - event->ev.extension == ev->extension && - event->ev.evtype == ev->evtype) { - *ev = event->ev; - DL_DELETE(*head, event); - Xfree(event); - ret = True; - break; - } - } - - return ret; -} - -Bool -_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) -{ - Bool ret = False; - int extension; - - if (!_XIsEventCookie(dpy, (XEvent*)in) || !out) - return ret; - - extension = in->extension & 0x7F; - - if (!dpy->generic_event_copy_vec[extension]) - return ret; - - ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out)); - out->cookie = ret ? ++dpy->next_cookie : 0; - return ret; -} - - -/* - * _XEnq - Place event packets on the display's queue. - * note that no squishing of move events in V11, since there - * is pointer motion hints.... - */ -void _XEnq( - register Display *dpy, - register xEvent *event) -{ - register _XQEvent *qelt; - int type, extension; - - if ((qelt = dpy->qfree)) { - /* If dpy->qfree is non-NULL do this, else malloc a new one. */ - dpy->qfree = qelt->next; - } - else if ((qelt = Xmalloc(sizeof(_XQEvent))) == NULL) { - /* Malloc call failed! */ - ESET(ENOMEM); -#ifdef NX_TRANS_SOCKET - _XIOError(dpy); - - return; -#else - _XIOError(dpy); -#endif - } - qelt->next = NULL; - - type = event->u.u.type & 0177; - extension = ((xGenericEvent*)event)->extension; - - qelt->event.type = type; - /* If an extension has registered a generic_event_vec handler, then - * it can handle event cookies. Otherwise, proceed with the normal - * event handlers. - * - * If the generic_event_vec is called, qelt->event is a event cookie - * with the data pointer and the "free" pointer set. Data pointer is - * some memory allocated by the extension. - */ - if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) { - XGenericEventCookie *cookie = &qelt->event.xcookie; - (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event); - cookie->cookie = ++dpy->next_cookie; - - qelt->qserial_num = dpy->next_event_serial_num++; - if (dpy->tail) dpy->tail->next = qelt; - else dpy->head = qelt; - - dpy->tail = qelt; - dpy->qlen++; - } else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) { - qelt->qserial_num = dpy->next_event_serial_num++; - if (dpy->tail) dpy->tail->next = qelt; - else dpy->head = qelt; - - dpy->tail = qelt; - dpy->qlen++; - } else { - /* ignored, or stashed away for many-to-one compression */ - qelt->next = dpy->qfree; - dpy->qfree = qelt; - } -} - -/* - * _XDeq - Remove event packet from the display's queue. - */ -void _XDeq( - register Display *dpy, - register _XQEvent *prev, /* element before qelt */ - register _XQEvent *qelt) /* element to be unlinked */ -{ - if (prev) { - if ((prev->next = qelt->next) == NULL) - dpy->tail = prev; - } else { - /* no prev, so removing first elt */ - if ((dpy->head = qelt->next) == NULL) - dpy->tail = NULL; - } - qelt->qserial_num = 0; - qelt->next = dpy->qfree; - dpy->qfree = qelt; - dpy->qlen--; - - if (_XIsEventCookie(dpy, &qelt->event)) { - XGenericEventCookie* cookie = &qelt->event.xcookie; - /* dpy->qfree is re-used, reset memory to avoid double free on - * _XFreeDisplayStructure */ - cookie->data = NULL; - } -} - -/* - * EventToWire in separate file in that often not needed. - */ - -/*ARGSUSED*/ -Bool -_XUnknownWireEvent( - register Display *dpy, /* pointer to display structure */ - register XEvent *re, /* pointer to where event should be reformatted */ - register xEvent *event) /* wire protocol event */ -{ -#ifdef notdef - (void) fprintf(stderr, - "Xlib: unhandled wire event! event number = %d, display = %x\n.", - event->u.u.type, dpy); -#endif - return(False); -} - -Bool -_XUnknownWireEventCookie( - Display *dpy, /* pointer to display structure */ - XGenericEventCookie *re, /* pointer to where event should be reformatted */ - xEvent *event) /* wire protocol event */ -{ -#ifdef notdef - fprintf(stderr, - "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.", - ((xGenericEvent*)event)->extension, dpy); -#endif - return(False); -} - -Bool -_XUnknownCopyEventCookie( - Display *dpy, /* pointer to display structure */ - XGenericEventCookie *in, /* source */ - XGenericEventCookie *out) /* destination */ -{ -#ifdef notdef - fprintf(stderr, - "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.", - in->extension, dpy); -#endif - return(False); -} - -/*ARGSUSED*/ -Status -_XUnknownNativeEvent( - register Display *dpy, /* pointer to display structure */ - register XEvent *re, /* pointer to where event should be reformatted */ - register xEvent *event) /* wire protocol event */ -{ -#ifdef notdef - (void) fprintf(stderr, - "Xlib: unhandled native event! event number = %d, display = %x\n.", - re->type, dpy); -#endif - return(0); -} -/* - * reformat a wire event into an XEvent structure of the right type. - */ -Bool -_XWireToEvent( - register Display *dpy, /* pointer to display structure */ - register XEvent *re, /* pointer to where event should be reformatted */ - register xEvent *event) /* wire protocol event */ -{ - - re->type = event->u.u.type & 0x7f; - ((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy, - (xGenericReply *)event); - ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); - ((XAnyEvent *)re)->display = dpy; - - /* Ignore the leading bit of the event type since it is set when a - client sends an event rather than the server. */ - - switch (event-> u.u.type & 0177) { - case KeyPress: - case KeyRelease: - { - register XKeyEvent *ev = (XKeyEvent*) re; - ev->root = event->u.keyButtonPointer.root; - ev->window = event->u.keyButtonPointer.event; - ev->subwindow = event->u.keyButtonPointer.child; - ev->time = event->u.keyButtonPointer.time; - ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); - ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); - ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); - ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); - ev->state = event->u.keyButtonPointer.state; - ev->same_screen = event->u.keyButtonPointer.sameScreen; - ev->keycode = event->u.u.detail; - } - break; - case ButtonPress: - case ButtonRelease: - { - register XButtonEvent *ev = (XButtonEvent *) re; - ev->root = event->u.keyButtonPointer.root; - ev->window = event->u.keyButtonPointer.event; - ev->subwindow = event->u.keyButtonPointer.child; - ev->time = event->u.keyButtonPointer.time; - ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); - ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); - ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); - ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); - ev->state = event->u.keyButtonPointer.state; - ev->same_screen = event->u.keyButtonPointer.sameScreen; - ev->button = event->u.u.detail; - } - break; - case MotionNotify: - { - register XMotionEvent *ev = (XMotionEvent *)re; - ev->root = event->u.keyButtonPointer.root; - ev->window = event->u.keyButtonPointer.event; - ev->subwindow = event->u.keyButtonPointer.child; - ev->time = event->u.keyButtonPointer.time; - ev->x = cvtINT16toInt(event->u.keyButtonPointer.eventX); - ev->y = cvtINT16toInt(event->u.keyButtonPointer.eventY); - ev->x_root = cvtINT16toInt(event->u.keyButtonPointer.rootX); - ev->y_root = cvtINT16toInt(event->u.keyButtonPointer.rootY); - ev->state = event->u.keyButtonPointer.state; - ev->same_screen = event->u.keyButtonPointer.sameScreen; - ev->is_hint = event->u.u.detail; - } - break; - case EnterNotify: - case LeaveNotify: - { - register XCrossingEvent *ev = (XCrossingEvent *) re; - ev->root = event->u.enterLeave.root; - ev->window = event->u.enterLeave.event; - ev->subwindow = event->u.enterLeave.child; - ev->time = event->u.enterLeave.time; - ev->x = cvtINT16toInt(event->u.enterLeave.eventX); - ev->y = cvtINT16toInt(event->u.enterLeave.eventY); - ev->x_root = cvtINT16toInt(event->u.enterLeave.rootX); - ev->y_root = cvtINT16toInt(event->u.enterLeave.rootY); - ev->state = event->u.enterLeave.state; - ev->mode = event->u.enterLeave.mode; - ev->same_screen = (event->u.enterLeave.flags & - ELFlagSameScreen) && True; - ev->focus = (event->u.enterLeave.flags & - ELFlagFocus) && True; - ev->detail = event->u.u.detail; - } - break; - case FocusIn: - case FocusOut: - { - register XFocusChangeEvent *ev = (XFocusChangeEvent *) re; - ev->window = event->u.focus.window; - ev->mode = event->u.focus.mode; - ev->detail = event->u.u.detail; - } - break; - case KeymapNotify: - { - register XKeymapEvent *ev = (XKeymapEvent *) re; - ev->window = None; - memcpy(&ev->key_vector[1], - (char *)((xKeymapEvent *) event)->map, - sizeof (((xKeymapEvent *) event)->map)); - } - break; - case Expose: - { - register XExposeEvent *ev = (XExposeEvent *) re; - ev->window = event->u.expose.window; - ev->x = event->u.expose.x; - ev->y = event->u.expose.y; - ev->width = event->u.expose.width; - ev->height = event->u.expose.height; - ev->count = event->u.expose.count; - } - break; - case GraphicsExpose: - { - register XGraphicsExposeEvent *ev = - (XGraphicsExposeEvent *) re; - ev->drawable = event->u.graphicsExposure.drawable; - ev->x = event->u.graphicsExposure.x; - ev->y = event->u.graphicsExposure.y; - ev->width = event->u.graphicsExposure.width; - ev->height = event->u.graphicsExposure.height; - ev->count = event->u.graphicsExposure.count; - ev->major_code = event->u.graphicsExposure.majorEvent; - ev->minor_code = event->u.graphicsExposure.minorEvent; - } - break; - case NoExpose: - { - register XNoExposeEvent *ev = (XNoExposeEvent *) re; - ev->drawable = event->u.noExposure.drawable; - ev->major_code = event->u.noExposure.majorEvent; - ev->minor_code = event->u.noExposure.minorEvent; - } - break; - case VisibilityNotify: - { - register XVisibilityEvent *ev = (XVisibilityEvent *) re; - ev->window = event->u.visibility.window; - ev->state = event->u.visibility.state; - } - break; - case CreateNotify: - { - register XCreateWindowEvent *ev = - (XCreateWindowEvent *) re; - ev->window = event->u.createNotify.window; - ev->parent = event->u.createNotify.parent; - ev->x = cvtINT16toInt(event->u.createNotify.x); - ev->y = cvtINT16toInt(event->u.createNotify.y); - ev->width = event->u.createNotify.width; - ev->height = event->u.createNotify.height; - ev->border_width = event->u.createNotify.borderWidth; - ev->override_redirect = event->u.createNotify.override; - } - break; - case DestroyNotify: - { - register XDestroyWindowEvent *ev = - (XDestroyWindowEvent *) re; - ev->window = event->u.destroyNotify.window; - ev->event = event->u.destroyNotify.event; - } - break; - case UnmapNotify: - { - register XUnmapEvent *ev = (XUnmapEvent *) re; - ev->window = event->u.unmapNotify.window; - ev->event = event->u.unmapNotify.event; - ev->from_configure = event->u.unmapNotify.fromConfigure; - } - break; - case MapNotify: - { - register XMapEvent *ev = (XMapEvent *) re; - ev->window = event->u.mapNotify.window; - ev->event = event->u.mapNotify.event; - ev->override_redirect = event->u.mapNotify.override; - } - break; - case MapRequest: - { - register XMapRequestEvent *ev = (XMapRequestEvent *) re; - ev->window = event->u.mapRequest.window; - ev->parent = event->u.mapRequest.parent; - } - break; - case ReparentNotify: - { - register XReparentEvent *ev = (XReparentEvent *) re; - ev->event = event->u.reparent.event; - ev->window = event->u.reparent.window; - ev->parent = event->u.reparent.parent; - ev->x = cvtINT16toInt(event->u.reparent.x); - ev->y = cvtINT16toInt(event->u.reparent.y); - ev->override_redirect = event->u.reparent.override; - } - break; - case ConfigureNotify: - { - register XConfigureEvent *ev = (XConfigureEvent *) re; - ev->event = event->u.configureNotify.event; - ev->window = event->u.configureNotify.window; - ev->above = event->u.configureNotify.aboveSibling; - ev->x = cvtINT16toInt(event->u.configureNotify.x); - ev->y = cvtINT16toInt(event->u.configureNotify.y); - ev->width = event->u.configureNotify.width; - ev->height = event->u.configureNotify.height; - ev->border_width = event->u.configureNotify.borderWidth; - ev->override_redirect = event->u.configureNotify.override; - } - break; - case ConfigureRequest: - { - register XConfigureRequestEvent *ev = - (XConfigureRequestEvent *) re; - ev->window = event->u.configureRequest.window; - ev->parent = event->u.configureRequest.parent; - ev->above = event->u.configureRequest.sibling; - ev->x = cvtINT16toInt(event->u.configureRequest.x); - ev->y = cvtINT16toInt(event->u.configureRequest.y); - ev->width = event->u.configureRequest.width; - ev->height = event->u.configureRequest.height; - ev->border_width = event->u.configureRequest.borderWidth; - ev->value_mask = event->u.configureRequest.valueMask; - ev->detail = event->u.u.detail; - } - break; - case GravityNotify: - { - register XGravityEvent *ev = (XGravityEvent *) re; - ev->window = event->u.gravity.window; - ev->event = event->u.gravity.event; - ev->x = cvtINT16toInt(event->u.gravity.x); - ev->y = cvtINT16toInt(event->u.gravity.y); - } - break; - case ResizeRequest: - { - register XResizeRequestEvent *ev = - (XResizeRequestEvent *) re; - ev->window = event->u.resizeRequest.window; - ev->width = event->u.resizeRequest.width; - ev->height = event->u.resizeRequest.height; - } - break; - case CirculateNotify: - { - register XCirculateEvent *ev = (XCirculateEvent *) re; - ev->window = event->u.circulate.window; - ev->event = event->u.circulate.event; - ev->place = event->u.circulate.place; - } - break; - case CirculateRequest: - { - register XCirculateRequestEvent *ev = - (XCirculateRequestEvent *) re; - ev->window = event->u.circulate.window; - ev->parent = event->u.circulate.event; - ev->place = event->u.circulate.place; - } - break; - case PropertyNotify: - { - register XPropertyEvent *ev = (XPropertyEvent *) re; - ev->window = event->u.property.window; - ev->atom = event->u.property.atom; - ev->time = event->u.property.time; - ev->state = event->u.property.state; - } - break; - case SelectionClear: - { - register XSelectionClearEvent *ev = - (XSelectionClearEvent *) re; - ev->window = event->u.selectionClear.window; - ev->selection = event->u.selectionClear.atom; - ev->time = event->u.selectionClear.time; - } - break; - case SelectionRequest: - { - register XSelectionRequestEvent *ev = - (XSelectionRequestEvent *) re; - ev->owner = event->u.selectionRequest.owner; - ev->requestor = event->u.selectionRequest.requestor; - ev->selection = event->u.selectionRequest.selection; - ev->target = event->u.selectionRequest.target; - ev->property = event->u.selectionRequest.property; - ev->time = event->u.selectionRequest.time; - } - break; - case SelectionNotify: - { - register XSelectionEvent *ev = (XSelectionEvent *) re; - ev->requestor = event->u.selectionNotify.requestor; - ev->selection = event->u.selectionNotify.selection; - ev->target = event->u.selectionNotify.target; - ev->property = event->u.selectionNotify.property; - ev->time = event->u.selectionNotify.time; - } - break; - case ColormapNotify: - { - register XColormapEvent *ev = (XColormapEvent *) re; - ev->window = event->u.colormap.window; - ev->colormap = event->u.colormap.colormap; - ev->new = event->u.colormap.new; - ev->state = event->u.colormap.state; - } - break; - case ClientMessage: - { - register int i; - register XClientMessageEvent *ev - = (XClientMessageEvent *) re; - ev->window = event->u.clientMessage.window; - ev->format = event->u.u.detail; - switch (ev->format) { - case 8: - ev->message_type = event->u.clientMessage.u.b.type; - for (i = 0; i < 20; i++) - ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; - break; - case 16: - ev->message_type = event->u.clientMessage.u.s.type; - ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0); - ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1); - ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2); - ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3); - ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4); - ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5); - ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6); - ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7); - ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8); - ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9); - break; - case 32: - ev->message_type = event->u.clientMessage.u.l.type; - ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0); - ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1); - ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2); - ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3); - ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4); - break; - default: /* XXX should never occur */ - break; - } - } - break; - case MappingNotify: - { - register XMappingEvent *ev = (XMappingEvent *)re; - ev->window = 0; - ev->first_keycode = event->u.mappingNotify.firstKeyCode; - ev->request = event->u.mappingNotify.request; - ev->count = event->u.mappingNotify.count; - } - break; - default: - return(_XUnknownWireEvent(dpy, re, event)); - } - return(True); -} - - -/* - * _XDefaultIOError - Default fatal system error reporting routine. Called - * when an X internal system error is encountered. - */ -int _XDefaultIOError( - Display *dpy) -{ - if (ECHECK(EPIPE)) { - (void) fprintf (stderr, - "X connection to %s broken (explicit kill or server shutdown).\r\n", - DisplayString (dpy)); - } else { - (void) fprintf (stderr, - "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", -#ifdef WIN32 - WSAGetLastError(), strerror(WSAGetLastError()), -#else - errno, strerror (errno), -#endif - DisplayString (dpy)); - (void) fprintf (stderr, - " after %lu requests (%lu known processed) with %d events remaining.\r\n", - NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), - QLength(dpy)); - - } -#ifdef NX_TRANS_SOCKET - if (_NXHandleDisplayError == 1) - { -#ifdef NX_TRANS_TEST - fprintf(stderr, "_XDefaultIOError: Going to return from the error handler.\n"); -#endif - return 0; - } - else - { -#ifdef NX_TRANS_TEST - fprintf(stderr, "_XDefaultIOError: Going to exit from the program.\n"); -#endif -#ifdef NX_TRANS_EXIT - NXTransExit(1); -#else - exit(1); -#endif - } -#else - exit(1); -#endif /* #ifdef NX_TRANS_SOCKET */ - /*NOTREACHED*/ -} - - -static int _XPrintDefaultError( - Display *dpy, - XErrorEvent *event, - FILE *fp) -{ - char buffer[BUFSIZ]; - char mesg[BUFSIZ]; - char number[32]; - const char *mtype = "XlibMessage"; - register _XExtension *ext = (_XExtension *)NULL; - _XExtension *bext = (_XExtension *)NULL; - XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); - XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); - (void) fprintf(fp, "%s: %s\n ", mesg, buffer); - XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", - mesg, BUFSIZ); - (void) fprintf(fp, mesg, event->request_code); - if (event->request_code < 128) { - snprintf(number, sizeof(number), "%d", event->request_code); - XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); - } else { - for (ext = dpy->ext_procs; - ext && (ext->codes.major_opcode != event->request_code); - ext = ext->next) - ; - if (ext) { - strncpy(buffer, ext->name, BUFSIZ); - buffer[BUFSIZ - 1] = '\0'; - } else - buffer[0] = '\0'; - } - (void) fprintf(fp, " (%s)\n", buffer); - if (event->request_code >= 128) { - XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", - mesg, BUFSIZ); - fputs(" ", fp); - (void) fprintf(fp, mesg, event->minor_code); - if (ext) { - snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code); - XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); - (void) fprintf(fp, " (%s)", buffer); - } - fputs("\n", fp); - } - if (event->error_code >= 128) { - /* kludge, try to find the extension that caused it */ - buffer[0] = '\0'; - for (ext = dpy->ext_procs; ext; ext = ext->next) { - if (ext->error_string) - (*ext->error_string)(dpy, event->error_code, &ext->codes, - buffer, BUFSIZ); - if (buffer[0]) { - bext = ext; - break; - } - if (ext->codes.first_error && - ext->codes.first_error < (int)event->error_code && - (!bext || ext->codes.first_error > bext->codes.first_error)) - bext = ext; - } - if (bext) - snprintf(buffer, sizeof(buffer), "%s.%d", bext->name, - event->error_code - bext->codes.first_error); - else - strcpy(buffer, "Value"); - XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); - if (mesg[0]) { - fputs(" ", fp); - (void) fprintf(fp, mesg, event->resourceid); - fputs("\n", fp); - } - /* let extensions try to print the values */ - for (ext = dpy->ext_procs; ext; ext = ext->next) { - if (ext->error_values) - (*ext->error_values)(dpy, event, fp); - } - } else if ((event->error_code == BadWindow) || - (event->error_code == BadPixmap) || - (event->error_code == BadCursor) || - (event->error_code == BadFont) || - (event->error_code == BadDrawable) || - (event->error_code == BadColor) || - (event->error_code == BadGC) || - (event->error_code == BadIDChoice) || - (event->error_code == BadValue) || - (event->error_code == BadAtom)) { - if (event->error_code == BadValue) - XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", - mesg, BUFSIZ); - else if (event->error_code == BadAtom) - XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", - mesg, BUFSIZ); - else - XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", - mesg, BUFSIZ); - fputs(" ", fp); - (void) fprintf(fp, mesg, event->resourceid); - fputs("\n", fp); - } - XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", - mesg, BUFSIZ); - fputs(" ", fp); - (void) fprintf(fp, mesg, event->serial); - XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", - mesg, BUFSIZ); - fputs("\n ", fp); - (void) fprintf(fp, mesg, dpy->request); - fputs("\n", fp); - if (event->error_code == BadImplementation) return 0; - return 1; -} - -int _XDefaultError( - Display *dpy, - XErrorEvent *event) -{ - if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0; - - /* - * Store in dpy flags that the client is exiting on an unhandled XError - * (pretend it is an IOError, since the application is dying anyway it - * does not make a difference). - * This is useful for _XReply not to hang if the application makes Xlib - * calls in _fini as part of process termination. - */ - dpy->flags |= XlibDisplayIOError; - - exit(1); - /*NOTREACHED*/ -} - -/*ARGSUSED*/ -Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) -{ - return True; -} - -/* - * _XError - upcall internal or user protocol error handler - */ -int _XError ( - Display *dpy, - register xError *rep) -{ - /* - * X_Error packet encountered! We need to unpack the error before - * giving it to the user. - */ - XEvent event; /* make it a large event */ - register _XAsyncHandler *async, *next; - - event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); - - for (async = dpy->async_handlers; async; async = next) { - next = async->next; - if ((*async->handler)(dpy, (xReply *)rep, - (char *)rep, SIZEOF(xError), async->data)) - return 0; - } - - event.xerror.display = dpy; - event.xerror.type = X_Error; - event.xerror.resourceid = rep->resourceID; - event.xerror.error_code = rep->errorCode; - event.xerror.request_code = rep->majorCode; - event.xerror.minor_code = rep->minorCode; - if (dpy->error_vec && - !(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep)) - return 0; - if (_XErrorFunction != NULL) { - int rtn_val; -#if defined(XTHREADS) && !USE_XCB - if (dpy->lock) - (*dpy->lock->user_lock_display)(dpy); - UnlockDisplay(dpy); -#endif /* XTHREADS && !USE_XCB */ - rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */ -#if defined(XTHREADS) && !USE_XCB - LockDisplay(dpy); - if (dpy->lock) - (*dpy->lock->user_unlock_display)(dpy); -#endif /* XTHREADS && !USE_XCB */ - return rtn_val; - } else { - return _XDefaultError(dpy, (XErrorEvent *)&event); - } -} - -/* - * _XIOError - call user connection error handler and exit - */ -int -_XIOError ( - Display *dpy) -{ - dpy->flags |= XlibDisplayIOError; -#ifdef WIN32 - errno = WSAGetLastError(); -#endif - - /* This assumes that the thread calling exit will call any atexit handlers. - * If this does not hold, then an alternate solution would involve - * registering an atexit handler to take over the lock, which would only - * assume that the same thread calls all the atexit handlers. */ -#ifdef XTHREADS - if (dpy->lock) - (*dpy->lock->user_lock_display)(dpy); -#endif - UnlockDisplay(dpy); - - if (_XIOErrorFunction != NULL) - (*_XIOErrorFunction)(dpy); - else - _XDefaultIOError(dpy); -#ifdef NX_TRANS_SOCKET - /* - * Check if we are supposed to return in the case - * of a display failure. The client which originated - * the X operation will have to check the value of - * the XlibDisplayIOError flag and handle appropria- - * tely the display disconnection. - */ - - if (_NXHandleDisplayError == 0) - { -#ifdef NX_TRANS_EXIT - NXTransExit(1); -#else - exit(1); -#endif - } - - /* - * We are going to return. Reset the display - * buffers. Further writes will be discarded. - */ - -#ifdef NX_TRANS_TEST - fprintf(stderr, "_XIOError: Resetting the display buffer.\n"); -#endif - - dpy->bufptr = dpy->buffer; - dpy->last_req = (char *) &_dummy_request; - -#ifdef NX_TRANS_TEST - fprintf(stderr, "_XIOError: Resetting the display flags.\n"); -#endif - - dpy->flags &= ~XlibDisplayProcConni; - dpy->flags &= ~XlibDisplayPrivSync; - dpy->flags &= ~XlibDisplayReadEvents; - dpy->flags &= ~XlibDisplayWriting; - dpy->flags &= ~XlibDisplayReply; - /* shut up the compiler by returning something */ - return 0; -#else - exit (1); -#endif - /*NOTREACHED*/ -} - - -/* - * This routine can be used to (cheaply) get some memory within a single - * Xlib routine for scratch space. A single buffer is reused each time - * if possible. To be MT safe, you can only call this between a call to - * GetReq* and a call to Data* or _XSend*, or in a context when the thread - * is guaranteed to not unlock the display. - */ -char *_XAllocScratch( - register Display *dpy, - unsigned long nbytes) -{ - if (nbytes > dpy->scratch_length) { - Xfree (dpy->scratch_buffer); - dpy->scratch_buffer = Xmalloc(nbytes); - if (dpy->scratch_buffer) - dpy->scratch_length = nbytes; - else dpy->scratch_length = 0; - } - return (dpy->scratch_buffer); -} - -/* - * Scratch space allocator you can call any time, multiple times, and be - * MT safe, but you must hand the buffer back with _XFreeTemp. - */ -char *_XAllocTemp( - register Display *dpy, - unsigned long nbytes) -{ - char *buf; - - buf = _XAllocScratch(dpy, nbytes); - dpy->scratch_buffer = NULL; - dpy->scratch_length = 0; - return buf; -} - -void _XFreeTemp( - register Display *dpy, - char *buf, - unsigned long nbytes) -{ - - Xfree(dpy->scratch_buffer); - dpy->scratch_buffer = buf; - dpy->scratch_length = nbytes; -} - -/* - * Given a visual id, find the visual structure for this id on this display. - */ -Visual *_XVIDtoVisual( - Display *dpy, - VisualID id) -{ - register int i, j, k; - register Screen *sp; - register Depth *dp; - register Visual *vp; - for (i = 0; i < dpy->nscreens; i++) { - sp = &dpy->screens[i]; - for (j = 0; j < sp->ndepths; j++) { - dp = &sp->depths[j]; - /* if nvisuals == 0 then visuals will be NULL */ - for (k = 0; k < dp->nvisuals; k++) { - vp = &dp->visuals[k]; - if (vp->visualid == id) return (vp); - } - } - } - return (NULL); -} - -int -XFree (void *data) -{ - Xfree (data); - return 1; -} - -#ifdef _XNEEDBCOPYFUNC -void _Xbcopy(b1, b2, length) - register char *b1, *b2; - register length; -{ - if (b1 < b2) { - b2 += length; - b1 += length; - while (length--) - *--b2 = *--b1; - } else { - while (length--) - *b2++ = *b1++; - } -} -#endif - -#ifdef DataRoutineIsProcedure -void Data( - Display *dpy, - _Xconst char *data, - long len) -{ - if (dpy->bufptr + (len) <= dpy->bufmax) { - memcpy(dpy->bufptr, data, (int)len); - dpy->bufptr += ((len) + 3) & ~3; - } else { - _XSend(dpy, data, len); - } -} -#endif /* DataRoutineIsProcedure */ - - -#ifdef LONG64 -int -_XData32( - Display *dpy, - register _Xconst long *data, - unsigned len) -{ - register int *buf; - register long i; - - while (len) { - buf = (int *)dpy->bufptr; - i = dpy->bufmax - (char *)buf; - if (!i) { - _XFlush(dpy); - continue; - } - if (len < i) - i = len; - dpy->bufptr = (char *)buf + i; - len -= i; - i >>= 2; - while (--i >= 0) - *buf++ = *data++; - } - return 0; -} -#endif /* LONG64 */ - - - -/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm. - * Otherwise, Xau will not be able to find your cookies in the Xauthority file. - * - * Note: POSIX says that the ``nodename'' member of utsname does _not_ have - * to have sufficient information for interfacing to the network, - * and so, you may be better off using gethostname (if it exists). - */ - -#if defined(_POSIX_SOURCE) || defined(SVR4) -#define NEED_UTSNAME -#include <sys/utsname.h> -#else -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#endif - -/* - * _XGetHostname - similar to gethostname but allows special processing. - */ -int _XGetHostname ( - char *buf, - int maxlen) -{ - int len; - -#ifdef NEED_UTSNAME - struct utsname name; - - if (maxlen <= 0 || buf == NULL) - return 0; - - uname (&name); - len = strlen (name.nodename); - if (len >= maxlen) len = maxlen - 1; - strncpy (buf, name.nodename, len); - buf[len] = '\0'; -#else - if (maxlen <= 0 || buf == NULL) - return 0; - - buf[0] = '\0'; - (void) gethostname (buf, maxlen); - buf [maxlen - 1] = '\0'; - len = strlen(buf); -#endif /* NEED_UTSNAME */ - return len; -} - - -/* - * _XScreenOfWindow - get the Screen of a given window - */ - -Screen *_XScreenOfWindow(Display *dpy, Window w) -{ - register int i; - Window root; - int x, y; /* dummy variables */ - unsigned int width, height, bw, depth; /* dummy variables */ - - if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height, - &bw, &depth) == False) { - return NULL; - } - for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ - if (root == RootWindow (dpy, i)) { - return ScreenOfDisplay (dpy, i); - } - } - return NULL; -} - -/* - * WARNING: This implementation's pre-conditions and post-conditions - * must remain compatible with the old macro-based implementations of - * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the - * Display structure affected by those macros are part of libX11's - * ABI. - */ -void *_XGetRequest(Display *dpy, CARD8 type, size_t len) -{ - xReq *req; - - if (dpy->bufptr + len > dpy->bufmax) - _XFlush(dpy); - /* Request still too large, so do not allow it to overflow. */ - if (dpy->bufptr + len > dpy->bufmax) { - fprintf(stderr, - "Xlib: request %d length %zd would exceed buffer size.\n", - type, len); - /* Changes failure condition from overflow to NULL dereference. */ - return NULL; - } - - if (len % 4) - fprintf(stderr, - "Xlib: request %d length %zd not a multiple of 4.\n", - type, len); - - dpy->last_req = dpy->bufptr; - - req = (xReq*)dpy->bufptr; - req->reqType = type; - req->length = len / 4; - dpy->bufptr += len; - dpy->request++; - return req; -} - -#if defined(WIN32) - -/* - * These functions are intended to be used internally to Xlib only. - * These functions will always prefix the path with a DOS drive in the - * form "<drive-letter>:". As such, these functions are only suitable - * for use by Xlib function that supply a root-based path to some - * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will - * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir". - */ - -static int access_file (path, pathbuf, len_pathbuf, pathret) - char* path; - char* pathbuf; - int len_pathbuf; - char** pathret; -{ - if (access (path, F_OK) == 0) { - if (strlen (path) < len_pathbuf) - *pathret = pathbuf; - else - *pathret = Xmalloc (strlen (path) + 1); - if (*pathret) { - strcpy (*pathret, path); - return 1; - } - } - return 0; -} - -static int AccessFile (path, pathbuf, len_pathbuf, pathret) - char* path; - char* pathbuf; - int len_pathbuf; - char** pathret; -{ - unsigned long drives; - int i, len; - char* drive; - char buf[MAX_PATH]; - char* bufp; - - /* just try the "raw" name first and see if it works */ - if (access_file (path, pathbuf, len_pathbuf, pathret)) - return 1; - - /* try the places set in the environment */ - drive = getenv ("_XBASEDRIVE"); - if (!drive) - drive = "C:"; - len = strlen (drive) + strlen (path); - if (len < MAX_PATH) bufp = buf; - else bufp = Xmalloc (len + 1); - strcpy (bufp, drive); - strcat (bufp, path); - if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { - if (bufp != buf) Xfree (bufp); - return 1; - } - - /* one last place to look */ - drive = getenv ("HOMEDRIVE"); - if (drive) { - len = strlen (drive) + strlen (path); - if (len < MAX_PATH) bufp = buf; - else bufp = Xmalloc (len + 1); - strcpy (bufp, drive); - strcat (bufp, path); - if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { - if (bufp != buf) Xfree (bufp); - return 1; - } - } - - /* tried everywhere else, go fishing */ -#define C_DRIVE ('C' - 'A') -#define Z_DRIVE ('Z' - 'A') - /* does OS/2 (with or with gcc-emx) have getdrives? */ - drives = _getdrives (); - for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */ - if ((1 << i) & drives) { - len = 2 + strlen (path); - if (len < MAX_PATH) bufp = buf; - else bufp = Xmalloc (len + 1); - *bufp = 'A' + i; - *(bufp + 1) = ':'; - *(bufp + 2) = '\0'; - strcat (bufp, path); - if (access_file (bufp, pathbuf, len_pathbuf, pathret)) { - if (bufp != buf) Xfree (bufp); - return 1; - } - } - } - return 0; -} - -int _XOpenFile(path, flags) - _Xconst char* path; - int flags; -{ - char buf[MAX_PATH]; - char* bufp = NULL; - int ret = -1; - UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); - - if (AccessFile (path, buf, MAX_PATH, &bufp)) - ret = open (bufp, flags); - - (void) SetErrorMode (olderror); - - if (bufp != buf) Xfree (bufp); - - return ret; -} - -int _XOpenFileMode(path, flags, mode) - _Xconst char* path; - int flags; - mode_t mode; -{ - char buf[MAX_PATH]; - char* bufp = NULL; - int ret = -1; - UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); - - if (AccessFile (path, buf, MAX_PATH, &bufp)) - ret = open (bufp, flags, mode); - - (void) SetErrorMode (olderror); - - if (bufp != buf) Xfree (bufp); - - return ret; -} - -void* _XFopenFile(path, mode) - _Xconst char* path; - _Xconst char* mode; -{ - char buf[MAX_PATH]; - char* bufp = NULL; - void* ret = NULL; - UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); - - if (AccessFile (path, buf, MAX_PATH, &bufp)) - ret = fopen (bufp, mode); - - (void) SetErrorMode (olderror); - - if (bufp != buf) Xfree (bufp); - - return ret; -} - -int _XAccessFile(path) - _Xconst char* path; -{ - char buf[MAX_PATH]; - char* bufp; - int ret = -1; - UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS); - - ret = AccessFile (path, buf, MAX_PATH, &bufp); - - (void) SetErrorMode (olderror); - - if (bufp != buf) Xfree (bufp); - - return ret; -} - -#endif - -#ifdef WIN32 -#undef _Xdebug -int _Xdebug = 0; -int *_Xdebug_p = &_Xdebug; -void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn; -void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn; -void (**_XLockMutex_fn_p)(LockInfoPtr -#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) - , char * /* file */ - , int /* line */ -#endif - ) = &_XLockMutex_fn; -void (**_XUnlockMutex_fn_p)(LockInfoPtr -#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) - , char * /* file */ - , int /* line */ -#endif - ) = &_XUnlockMutex_fn; -LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock; -#endif |