diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/dps/cslibint.c | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/lib/dps/cslibint.c')
-rw-r--r-- | nx-X11/lib/dps/cslibint.c | 1910 |
1 files changed, 1910 insertions, 0 deletions
diff --git a/nx-X11/lib/dps/cslibint.c b/nx-X11/lib/dps/cslibint.c new file mode 100644 index 000000000..84d7b753e --- /dev/null +++ b/nx-X11/lib/dps/cslibint.c @@ -0,0 +1,1910 @@ +/* + * cslibint.c -- low level I/O + * + * (c) Copyright 1993-1994 Adobe Systems Incorporated. + * All rights reserved. + * + * Permission to use, copy, modify, distribute, and sublicense this software + * and its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notices appear in all copies and that + * both those copyright notices and this permission notice appear in + * supporting documentation and that the name of Adobe Systems Incorporated + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. No trademark license + * to use the Adobe trademarks is hereby granted. If the Adobe trademark + * "Display PostScript"(tm) is used to describe this software, its + * functionality or for any other purpose, such use shall be limited to a + * statement that this software works in conjunction with the Display + * PostScript system. Proper trademark attribution to reflect Adobe's + * ownership of the trademark shall be given whenever any such reference to + * the Display PostScript system is made. + * + * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR + * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. + * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE + * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT + * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE. + * + * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems + * Incorporated which may be registered in certain jurisdictions + * + * Portions Copyright 1985, 1986, 1987 Massachusetts Institute of Technology + * + * 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, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * Author: Adobe Systems Incorporated and MIT X Consortium + */ +/* $XFree86: xc/lib/dps/cslibint.c,v 1.4tsi Exp $ */ + +/* + * XlibInternal.c - Internal support routines for the C subroutine + * interface library (Xlib) to the X Window System Protocol V11.0. + */ +#define NEED_EVENTS +#define NEED_REPLIES + +#include <X11/Xlibint.h> +#include <X11/Xos.h> +#include "Xlibnet.h" +#include <stdio.h> + +#include "dpsassert.h" +#include "cslibint.h" + +static void _EatData32 (Display *dpy, unsigned long n); + +/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define ETEST(err) (err == EAGAIN) +#else +#define ETEST(err) (err == EWOULDBLOCK) +#endif +#endif + +#ifdef LACHMAN +#ifdef EMSGSIZE +#undef EMSGSIZE +#endif +#define EMSGSIZE ERANGE +#endif + +#if defined(SVR4) && defined(sun) +#define SUNSYSV 1 +#endif + +/* + * 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 *, XErrorEvent *) 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. + */ + +extern _XQEvent *_qfree; + +static int padlength[4] = {0, 3, 2, 1}; + /* lookup table for adding padding bytes to data that is read from + or written to the X socket. */ + +static xReq _dummy_request = { + 0, 0, 0 +}; +/* + * N_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 N_XFlush (Display *dpy) +{ + register long size, todo; + register int write_stat; + register char *bufindex; + + if (!dpy) return; + + if (dpy->flags & XlibDisplayIOError) return; + + size = todo = dpy->bufptr - dpy->buffer; + bufindex = dpy->bufptr = 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) { + errno = 0; + write_stat = WriteToServer(dpy->fd, bufindex, (int) todo); + if (write_stat >= 0) { + size -= write_stat; + todo = size; + bufindex += write_stat; + } else if (ETEST(errno)) { + N_XWaitForWritable(dpy); +#ifdef SUNSYSV + } else if (errno == 0) { + N_XWaitForWritable(dpy); +#endif +#ifdef EMSGSIZE + } else if (errno == EMSGSIZE) { + if (todo > 1) + todo >>= 1; + else + N_XWaitForWritable(dpy); +#endif + } else if (errno != EINTR) { + /* Write failed! */ + /* errno set by write system call. */ + _XIOError(dpy); + } + } + dpy->last_req = (char *)&_dummy_request; +} + +#ifdef NEEDFORNX + +int +_XEventsQueued (Display *dpy, int mode) +{ + register int len; + int pend; + char buf[BUFSIZE]; + register xReply *rep; + + if (mode == QueuedAfterFlush) + { + _XFlush(dpy); + if (dpy->qlen) + return(dpy->qlen); + } + if (dpy->flags & XlibDisplayIOError) return(dpy->qlen); + if (BytesReadable(dpy->fd, (char *) &pend) < 0) + _XIOError(dpy); +#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) + { + unsigned long r_mask[MSKCNT]; + static struct timeval zero_time; + + dpy->conn_checker = 0; + CLEARBITS(r_mask); + BITSET(r_mask, dpy->fd); + if (pend = select(dpy->fd + 1, (int *)r_mask, NULL, NULL, + &zero_time)) + { + if (pend > 0) + { + if (BytesReadable(dpy->fd, (char *) &pend) < 0) + _XIOError(dpy); + /* we should not get zero, if we do, force a read */ + if (!pend) + pend = SIZEOF(xReply); + } + else if (pend < 0 && errno != EINTR) + _XIOError(dpy); + } + } +#endif /* XCONN_CHECK_FREQ */ + if (!(len = pend)) + return(dpy->qlen); /* _XFlush can enqueue events */ + /* 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. + */ + if (len < SIZEOF(xReply)) + len = SIZEOF(xReply); + else if (len > BUFSIZE) + len = BUFSIZE; + len /= SIZEOF(xReply); + pend = len * SIZEOF(xReply); +#ifdef XCONN_CHECK_FREQ + dpy->conn_checker = 0; +#endif + _XRead (dpy, buf, (long) pend); + + /* no space between comma and type or else macro will die */ + STARTITERATE (rep,xReply, buf, (len > 0), len--) { + if (rep->generic.type == X_Error) + _XError(dpy, (xError *)rep); + else /* must be an event packet */ + _XEnq(dpy, (xEvent *) rep); + } + ENDITERATE + return(dpy->qlen); +} + +/* _XReadEvents - Flush the output queue, + * then read as many events as possible (but at least 1) and enqueue them + */ +void _XReadEvents(Display *dpy) +{ + char buf[BUFSIZE]; + long pend_not_register; /* because can't "&" a register variable */ + register long pend; + register xEvent *ev; + Bool not_yet_flushed = True; + + do { + /* find out how much data can be read */ + if (BytesReadable(dpy->fd, (char *) &pend_not_register) < 0) + _XIOError(dpy); + pend = pend_not_register; + + /* must read at least one xEvent; if none is pending, then + we'll just flush and block waiting for it */ + if (pend < SIZEOF(xEvent)) { + pend = SIZEOF(xEvent); + /* don't flush until we block the first time */ + if (not_yet_flushed) { + int qlen = dpy->qlen; + _XFlush (dpy); + if (qlen != dpy->qlen) return; + not_yet_flushed = False; + } + } + + /* but we won't read more than the max buffer size */ + if (pend > BUFSIZE) + pend = BUFSIZE; + + /* round down to an integral number of XReps */ + pend = (pend / SIZEOF(xEvent)) * SIZEOF(xEvent); + + _XRead (dpy, buf, pend); + + /* no space between comma and type or else macro will die */ + STARTITERATE (ev,xEvent, buf, (pend > 0), + pend -= SIZEOF(xEvent)) { + if (ev->u.u.type == X_Error) + _XError (dpy, (xError *) ev); + else /* it's an event packet; enqueue it */ + _XEnq (dpy, ev); + } + ENDITERATE + } while (dpy->head == NULL); +} + +#endif /* NEEDFORNX */ + +/* + * N_XRead - Read bytes from the socket taking into account incomplete + * reads. This routine may have to be reworked if int < long. + */ +int N_XRead (Display *dpy, char *data, long size) +{ + register long bytes_read; + + if (!dpy) return 0; + if ((dpy->flags & XlibDisplayIOError) || size == 0) return 0; + errno = 0; + while ((bytes_read = ReadFromServer(dpy->fd, data, (int)size)) + != size) { + + if (bytes_read > 0) { + size -= bytes_read; + data += bytes_read; + } + else if (ETEST(errno)) { + N_XWaitForReadable(dpy); + errno = 0; + } +#ifdef SUNSYSV + else if (errno == 0) { + N_XWaitForReadable(dpy); + } +#endif + else if (bytes_read == 0) { + /* Read failed because of end of file! */ + errno = EPIPE; + _XIOError(dpy); + } + + else /* bytes_read is less than 0; presumably -1 */ { + /* If it's a system call interrupt, it's not an error. */ + if (errno != EINTR) + _XIOError(dpy); + } + } + return 0; +} + +#ifdef WORD64 + +/* + * XXX This is a *really* stupid way of doing this.... + * PACKBUFFERSIZE must be a multiple of 4. + */ + +#define PACKBUFFERSIZE 4096 + + +/* + * _XRead32 - Read bytes from the socket unpacking each 32 bits + * into a long (64 bits on a CRAY computer). + * + */ +static void _doXRead32 (Display *dpy, long *data, long size, char *packbuffer) +{ + long *lpack,*lp; + long mask32 = 0x00000000ffffffff; + long maskw, nwords, i, bits; + + _XReadPad (dpy, packbuffer, size); + + lp = data; + lpack = (long *) packbuffer; + nwords = size >> 2; + bits = 32; + + for(i=0;i<nwords;i++){ + maskw = mask32 << bits; + *lp++ = ( *lpack & maskw ) >> bits; + bits = bits ^32; + if(bits){ + lpack++; + } + } +} + +void _XRead32 (Display *dpy, long *data, long len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 2; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + _doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) _doXRead32 (dpy, data, len, packbuffer); +} + + + +/* + * _XRead16 - Read bytes from the socket unpacking each 16 bits + * into a long (64 bits on a CRAY computer). + * + */ +static void _doXRead16 (Display *dpy, short *data, long size, char *packbuffer) +{ + long *lpack,*lp; + long mask16 = 0x000000000000ffff; + long maskw, nwords, i, bits; + + _XRead(dpy,packbuffer,size); /* don't do a padded read... */ + + lp = (long *) data; + lpack = (long *) packbuffer; + nwords = size >> 1; /* number of 16 bit words to be unpacked */ + bits = 48; + for(i=0;i<nwords;i++){ + maskw = mask16 << bits; + *lp++ = ( *lpack & maskw ) >> bits; + bits -= 16; + if(bits < 0){ + lpack++; + bits = 48; + } + } +} + +void _XRead16 (Display *dpy, short *data, long len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 1; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + _doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) _doXRead16 (dpy, data, len, packbuffer); +} + +void _XRead16Pad (Display *dpy, short *data, long size) +{ + int slop = (size & 3); + short slopbuf[3]; + + _XRead16 (dpy, data, size); + if (slop > 0) { + _XRead16 (dpy, slopbuf, 4 - slop); + } +} +#endif /* WORD64 */ + + +/* + * N_XReadPad - Read bytes from the socket taking into account incomplete + * reads. If the number of bytes is not 0 mod 32, read additional pad + * bytes. This routine may have to be reworked if int < long. + */ +void N_XReadPad (Display *dpy, char *data, long size) +{ + register long bytes_read; + struct iovec iov[2]; + char pad[3]; + + if (!dpy) return; + 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 = padlength[size & 3]; + iov[1].iov_base = pad; + size += iov[1].iov_len; + errno = 0; + while ((bytes_read = ReadvFromServer (dpy->fd, iov, 2)) != size) { + + if (bytes_read > 0) { + size -= bytes_read; + if (iov[0].iov_len < bytes_read) { + iov[1].iov_len += iov[0].iov_len - bytes_read; + iov[1].iov_base = + (char *)iov[1].iov_base + bytes_read - iov[0].iov_len; + 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(errno)) { + N_XWaitForReadable(dpy); + errno = 0; + } +#ifdef SUNSYSV + else if (errno == 0) { + N_XWaitForReadable(dpy); + } +#endif + else if (bytes_read == 0) { + /* Read failed because of end of file! */ + errno = EPIPE; + _XIOError(dpy); + } + + else /* bytes_read is less than 0; presumably -1 */ { + /* If it's a system call interrupt, it's not an error. */ + if (errno != EINTR) + _XIOError(dpy); + } + } +} + +/* + * N_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 N_XSend (Display *dpy, _Xconst char *data, long size) +{ + struct iovec iov[3]; + static char pad[3] = {0, 0, 0}; + /* XText8 and XText16 require that the padding bytes be zero! */ + + long skip = 0; + long dpybufsize = (dpy->bufptr - dpy->buffer); + long padsize = padlength[size & 3]; + long total = dpybufsize + size + padsize; + long todo = total; + + if (dpy->flags & XlibDisplayIOError) return; + + /* + * 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, dpybufsize) + InsertIOV ((char *)data, size) + InsertIOV (pad, padsize) + + errno = 0; + if ((len = WritevToServer(dpy->fd, iov, i)) >= 0) { + skip += len; + total -= len; + todo = total; + } else if (ETEST(errno)) { + N_XWaitForWritable(dpy); +#ifdef SUNSYSV + } else if (errno == 0) { + N_XWaitForWritable(dpy); +#endif +#ifdef EMSGSIZE + } else if (errno == EMSGSIZE) { + if (todo > 1) + todo >>= 1; + else + N_XWaitForWritable(dpy); +#endif + } else if (errno != EINTR) { + _XIOError(dpy); + } + } + + dpy->bufptr = dpy->buffer; + dpy->last_req = (char *) & _dummy_request; + return; +} + +#ifdef NEEDFORNX +/* + * _XAllocID - normal resource ID allocation routine. A client + * can roll his own and instatantiate it if he wants, but must + * follow the rules. + */ +XID _XAllocID(Display *dpy) +{ + XID id; + + id = dpy->resource_id << dpy->resource_shift; + 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; +} + +/* + * The hard part about this is that we only get 16 bits from a reply. Well, + * then, we have three values that will march along, with the following + * invariant: + * dpy->last_request_read <= rep->sequenceNumber <= dpy->request + * The right choice for rep->sequenceNumber is the largest that + * still meets these constraints. + */ + +unsigned long +_XSetLastRequestRead(Display *dpy, xGenericReply *rep) +{ + register unsigned long newseq, lastseq; + + /* + * 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(dpy->last_request_read); + + newseq = (dpy->last_request_read & ~((unsigned long)0xffff)) | + rep->sequenceNumber; + lastseq = dpy->last_request_read; + while (newseq < lastseq) { + newseq += 0x10000; + if (newseq > dpy->request) { + (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; + break; + } + } + + dpy->last_request_read = newseq; + return(newseq); +} + +#endif /* NEEDFORNX */ + +/* + * N_XReply - Wait for a reply packet and copy its contents into the + * specified rep. Mean while we must handle error and event packets that + * we may encounter. + */ +Status N_XReply ( + Display *dpy, + 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; + + if (dpy->flags & XlibDisplayIOError) return (0); + + N_XFlush(dpy); + while (1) { + N_XRead(dpy, (char *)rep, (long)SIZEOF(xReply)); + 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 + (void) _XSetLastRequestRead(dpy, &rep->generic); + if (extra == 0) { + if (discard && (rep->generic.length > 0)) + /* unexpectedly long reply! */ + _EatData32 (dpy, rep->generic.length); + return (1); + } + if ((unsigned) extra == rep->generic.length) { + /* + * Read the extra data into storage immediately following + * the GenericReply structure. + */ + N_XRead (dpy, (char *) (NEXTPTR(rep,xReply)), + ((long)extra) << 2); + return (1); + } + if ((unsigned) extra < rep->generic.length) { + /* Actual reply is longer than "extra" */ + N_XRead (dpy, (char *) (NEXTPTR(rep,xReply)), + ((long)extra) << 2); + if (discard) + _EatData32 (dpy, rep->generic.length - extra); + 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... + */ + N_XRead (dpy, (char *) (NEXTPTR(rep,xReply)), + ((long) rep->generic.length) << 2); + _XIOError (dpy); + return (0); + + case X_Error: + { + register _XExtension *ext; + register Bool ret = False; + int ret_code; + xError *err = (xError *) rep; + unsigned long serial; + + serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); + /* + * 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) + return(ret_code); + } + break; + default: + /* There should never be any events on this connection! */ + DPSFatalProc(NULL, "N_XReply read bogus X event"); + break; + } + } +} + + +/* Read and discard "n" 8-bit bytes of data */ + +static void +N_XEatData (Display *dpy, unsigned long n) +{ +#define SCRATCHSIZE 2048 + char buf[SCRATCHSIZE]; + + while (n > 0) { + register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n; + N_XRead (dpy, buf, bytes_read); + n -= bytes_read; + } +#undef SCRATCHSIZE +} + + +/* Read and discard "n" 32-bit words. */ + +static void _EatData32 (Display *dpy, unsigned long n) +{ + N_XEatData (dpy, n << 2); +} + + +#ifdef NEEDFORNX +/* + * _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 (Display *dpy, xEvent *event) +{ + register _XQEvent *qelt; + +/*NOSTRICT*/ + if (qelt = _qfree) { + /* If _qfree is non-NULL do this, else malloc a new one. */ + _qfree = qelt->next; + } + else if ((qelt = + (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { + /* Malloc call failed! */ + errno = ENOMEM; + _XIOError(dpy); + } + qelt->next = NULL; + /* go call through display to find proper event reformatter */ + if ((*dpy->event_vec[event->u.u.type & 0177])(dpy, &qelt->event, event)) { + 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 = _qfree; + _qfree = qelt; + } +} +/* + * EventToWire in separate file in that often not needed. + */ +#endif /* NEEDFORNX */ + +/*ARGSUSED*/ +Bool +N_XUnknownWireEvent( + Display *dpy, /* pointer to display structure */ + XEvent *re, /* pointer to where event should be reformatted */ + xEvent *event) /* wire protocol event */ +{ + char mbuf[256]; + + sprintf(mbuf, "NX: unhandled wire event %d, agent = %lx", re->type, (long)dpy); + DPSWarnProc(NULL, mbuf); + return(False); +} + +/*ARGSUSED*/ +Status +N_XUnknownNativeEvent( + Display *dpy, /* pointer to display structure */ + XEvent *re, /* pointer to where event should be reformatted */ + xEvent *event) /* wire protocol event */ +{ + char mbuf[256]; + + sprintf(mbuf, "NX: unhandled native event %d, agent = %lx", re->type, (long)dpy); + DPSWarnProc(NULL, mbuf); + return(0); +} + +#ifdef NEEDFORNX +/* + * reformat a wire event into an XEvent structure of the right type. + */ +Bool +_XWireToEvent( + Display *dpy, /* pointer to display structure */ + XEvent *re, /* pointer to where event should be reformatted */ + 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 = dpy->current; + bcopy ((char *)((xKeymapEvent *) event)->map, + &ev->key_vector[1], + 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); +} + + +#ifndef USL_SHARELIB + +static char *_SysErrorMsg (int n) +{ + extern char *sys_errlist[]; + extern int sys_nerr; + char *s = ((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error"); + + return (s ? s : "no such error"); +} + +#endif /* USL sharedlibs in don't define for SVR3.2 */ + + +/* + * _XDefaultIOError - Default fatal system error reporting routine. Called + * when an X internal system error is encountered. + */ +_XDefaultIOError (Display *dpy) +{ + (void) fprintf (stderr, + "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", + errno, _SysErrorMsg (errno), DisplayString (dpy)); + (void) fprintf (stderr, + " after %lu requests (%lu known processed) with %d events remaining.\r\n", + NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), + QLength(dpy)); + + if (errno == EPIPE) { + (void) fprintf (stderr, + " The connection was probably broken by a server shutdown or KillClient.\r\n"); + } + exit(1); +} + + +static int _XPrintDefaultError (Display *dpy, XErrorEvent *event, FILE *fp) +{ + char buffer[BUFSIZ]; + char mesg[BUFSIZ]; + char number[32]; + 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) { + sprintf(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) + strcpy(buffer, ext->name); + 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) { + sprintf(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 < event->error_code && + (!bext || ext->codes.first_error > bext->codes.first_error)) + bext = ext; + } + if (bext) + sprintf(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; + exit(1); + /*NOTREACHED*/ +} + +/*ARGSUSED*/ +Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we) +{ + return True; +} + +/* + * _XError - prepare to upcall user protocol error handler + */ +int _XError (Display *dpy, 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 */ + + event.xerror.display = dpy; + event.xerror.type = X_Error; + event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep); + 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) { + return ((*_XErrorFunction)(dpy, &event)); /* upcall */ + } else { + return _XDefaultError(dpy, &event); + } +} + +/* + * _XIOError - call user connection error handler and exit + */ +int _XIOError (Display *dpy) +{ + dpy->flags |= XlibDisplayIOError; + if (_XIOErrorFunction != NULL) + (*_XIOErrorFunction)(dpy); + else + _XDefaultIOError(dpy); + exit (1); +} + + +/* + * This routine can be used to (cheaply) get some memory within a single + * Xlib routine for scratch space. It is reallocated from the same place + * each time, unless the library needs a large scratch space. + */ +char *_XAllocScratch (Display *dpy, unsigned long nbytes) +{ + if (nbytes > dpy->scratch_length) { + if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer); + if (dpy->scratch_buffer = Xmalloc((unsigned) nbytes)) + dpy->scratch_length = nbytes; + else dpy->scratch_length = 0; + } + return (dpy->scratch_buffer); +} + +/* + * 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); +} + +void XFree (void *data) +{ + Xfree (data); +} + +#ifdef _XNEEDBCOPYFUNC +void _Xbcopy(char *b1, char *b2, length) +{ + if (b1 < b2) { + b2 += length; + b1 += length; + while (length--) + *--b2 = *--b1; + } else { + while (length--) + *b2++ = *b1++; + } +} +#endif + +#endif /* NEEDFORNX */ + +void NXProcData (Display *dpy, char *data, long len) +{ + if (dpy->bufptr + (len) <= dpy->bufmax) { + bcopy(data, dpy->bufptr, (int)len); + dpy->bufptr += ((len) + 3) & ~3; + } else { + N_XSend(dpy, data, len); + } +} + + +#ifdef WORD64 + +/* + * XXX This is a *really* stupid way of doing this. It should just use + * dpy->bufptr directly, taking into account where in the word it is. + */ + +/* + * Data16 - Place 16 bit data in the buffer. + * + * "dpy" is a pointer to a Display. + * "data" is a pointer to the data. + * "len" is the length in bytes of the data. + */ + +static void +doData16(Display *dpy, short *data, unsigned len, char *packbuffer) +{ + long *lp,*lpack; + long i, nwords,bits; + long mask16 = 0x000000000000ffff; + + lp = (long *)data; + lpack = (long *)packbuffer; + +/* nwords is the number of 16 bit values to be packed, + * the low order 16 bits of each word will be packed + * into 64 bit words + */ + nwords = len >> 1; + bits = 48; + + for(i=0;i<nwords;i++){ + if (bits == 48) *lpack = 0; + *lpack ^= (*lp & mask16) << bits; + bits -= 16 ; + lp++; + if(bits < 0){ + lpack++; + bits = 48; + } + } + Data(dpy, packbuffer, len); +} + +void +Data16 (Display *dpy, short *data, unsigned len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 1; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + doData16 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) doData16 (dpy, data, len, packbuffer); +} + +/* + * Data32 - Place 32 bit data in the buffer. + * + * "dpy" is a pointer to a Display. + * "data" is a pointer to the data. + * "len" is the length in bytes of the data. + */ + +static doData32 (Display *dpy, long *data, unsigned len, char *packbuffer) +{ + long *lp,*lpack; + long i,bits,nwords; + long mask32 = 0x00000000ffffffff; + + lpack = (long *) packbuffer; + lp = data; + +/* nwords is the number of 32 bit values to be packed + * the low order 32 bits of each word will be packed + * into 64 bit words + */ + nwords = len >> 2; + bits = 32; + + for(i=0;i<nwords;i++){ + if (bits == 32) *lpack = 0; + *lpack ^= (*lp & mask32) << bits; + bits = bits ^32; + lp++; + if(bits) + lpack++; + } + Data(dpy, packbuffer, len); +} + +Data32 (Display *dpy, long *data, unsigned len) +{ + char packbuffer[PACKBUFFERSIZE]; + unsigned nunits = PACKBUFFERSIZE >> 2; + + for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) { + doData32 (dpy, data, PACKBUFFERSIZE, packbuffer); + } + if (len) doData32 (dpy, data, len, packbuffer); +} + +#endif /* WORD64 */ + + +#ifdef NEEDFORNX + +/* + * _XFreeQ - free the queue of events, called by XCloseDisplay + */ + +void _XFreeQ (void) +{ + register _XQEvent *qelt = _qfree; + + while (qelt) { + register _XQEvent *qnxt = qelt->next; + Xfree ((char *) qelt); + qelt = qnxt; + } + _qfree = NULL; + return; +} +#endif /* NEEDFORNX */ + +/* 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(AIXV3)) || defined(hpux) || defined(USG) || defined(SVR4) +#define NEED_UTSNAME +#include <sys/utsname.h> +#endif + +/* + * N_XGetHostname - similar to gethostname but allows special processing. + */ +int N_XGetHostname (char *buf, int maxlen) +{ + int len; + +#ifdef NEED_UTSNAME + struct utsname name; + + uname (&name); + len = strlen (name.nodename); + if (len >= maxlen) len = maxlen - 1; + strncpy (buf, name.nodename, len); + buf[len] = '\0'; +#else + buf[0] = '\0'; + (void) gethostname (buf, maxlen); + buf [maxlen - 1] = '\0'; + len = strlen(buf); +#endif /* NEED_UTSNAME */ + return len; +} + +#ifdef NEEDFORNX +/* + * _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 None; + } + for (i = 0; i < ScreenCount (dpy); i++) { /* find root from list */ + if (root == RootWindow (dpy, i)) { + return ScreenOfDisplay (dpy, i); + } + } + return NULL; +} +#endif /* NEEDFORNX */ + +#if (MSKCNT > 4) +/* + * This is a macro if MSKCNT <= 4 + */ +int +N_XANYSET(unsigned long *src) +{ + int i; + + for (i=0; i<MSKCNT; i++) + if (src[ i ]) + return (1); + return (0); +} +#endif + +#ifdef NEEDFORNX +#ifdef CRAY +/* + * Cray UniCOS does not have readv and writev so we emulate + */ +#include <sys/socket.h> + +int _XReadV (int fd, struct iovec *iov, int iovcnt) +{ + struct msghdr hdr; + + hdr.msg_iov = iov; + hdr.msg_iovlen = iovcnt; + hdr.msg_accrights = 0; + hdr.msg_accrightslen = 0; + hdr.msg_name = 0; + hdr.msg_namelen = 0; + + return (recvmsg (fd, &hdr, 0)); +} + +int _XWriteV (int fd, struct iovec *iov, int iovcnt) +{ + struct msghdr hdr; + + hdr.msg_iov = iov; + hdr.msg_iovlen = iovcnt; + hdr.msg_accrights = 0; + hdr.msg_accrightslen = 0; + hdr.msg_name = 0; + hdr.msg_namelen = 0; + + return (sendmsg (fd, &hdr, 0)); +} + +#endif /* CRAY */ + +#if defined(SYSV) && defined(i386) && !defined(STREAMSCONN) +/* + * SYSV/386 does not have readv so we emulate + */ +#include <sys/uio.h> + +int _XReadV (int fd, struct iovec *iov, int iovcnt) +{ + int i, len, total; + char *base; + + errno = 0; + for (i=0, total=0; i<iovcnt; i++, iov++) { + len = iov->iov_len; + base = iov->iov_base; + while (len > 0) { + register int nbytes; + nbytes = read(fd, base, len); + if (nbytes < 0 && total == 0) return -1; + if (nbytes <= 0) return total; + errno = 0; + len -= nbytes; + total += nbytes; + base += nbytes; + } + } + return total; +} + +#endif /* SYSV && i386 && !STREAMSCONN */ + +#ifdef STREAMSCONN +/* + * Copyright 1988, 1989 AT&T, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of AT&T not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. AT&T makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL AT&T + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + iovec.c (C source file) + Acc: 575557389 Mon Mar 28 08:03:09 1988 + Mod: 575557397 Mon Mar 28 08:03:17 1988 + Sta: 575557397 Mon Mar 28 08:03:17 1988 + Owner: 2011 + Group: 1985 + Permissions: 664 +*/ +/* + START USER STAMP AREA +*/ +/* + END USER STAMP AREA +*/ + + +extern char _XsTypeofStream[]; +extern Xstream _XsStream[]; + +#define MAX_WORKAREA 4096 +static char workarea[MAX_WORKAREA]; + + + +int +_XReadV (int fd, struct iovec v[], int n) +{ + int i, rc, len, size = 0; + char * buf = workarea; + char * p; + + if (n <= 0 || n > 16) + { + errno = EINVAL; + return (-1); + } + for (i = 0; i < n; ++i) + { + if ((len = v[i].iov_len) < 0 || v[i].iov_base == NULL) + { + errno = EINVAL; + return (-1); + } + size += len; + } + if ((size > MAX_WORKAREA) && ((buf = malloc (size)) == NULL)) + { + errno = EINVAL; + return (-1); + } + if((rc = (*_XsStream[_XsTypeOfStream[fd]].ReadFromStream)(fd, buf, size, + BUFFERING))> 0) + { + for (i = 0, p = buf; i < n; ++i) + { + memcpy (v[i].iov_base, p, len = v[i].iov_len); + p += len; + } + } + if (size > MAX_WORKAREA) + free (buf); + + return (rc); +} + +int +_XWriteV (int fd, struct iovec v[], int n) +{ + int i, rc, len, size = 0; + char * buf = workarea; + char * p; + + if (n <= 0 || n > 16) + { + errno = EINVAL; + return (-1); + } + for (i = 0; i < n; ++i) + { + if ((len = v[i].iov_len) < 0 || v[i].iov_base == NULL) + { + errno = EINVAL; + return (-1); + } + size += len; + } + + if ((size > MAX_WORKAREA) && ((buf = malloc (size)) == NULL)) + { + errno = EINVAL; + return (-1); + } + for (i = 0, p = buf; i < n; ++i) + { + memcpy (p, v[i].iov_base, len = v[i].iov_len); + p += len; + } + rc = (*_XsStream[_XsTypeOfStream[fd]].WriteToStream)(fd, buf, size); + + if (size > MAX_WORKAREA) + free (buf); + + return (rc); +} + + + +#endif /* STREAMSCONN */ +#endif /* NEEDFORNX */ |