Home | History | Annotate | Line # | Download | only in src
      1 /*
      2 
      3 Copyright 1992, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included
     12 in all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall
     23 not be used in advertising or otherwise to promote the sale, use or
     24 other dealings in this Software without prior written authorization
     25 from The Open Group.
     26 
     27 */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include <config.h>
     31 #endif
     32 #include <X11/Xlibint.h>
     33 #include <X11/Xos.h>
     34 
     35 /*
     36  * Xlib's _XAsyncErrorState sequence number may wrap in 32bit
     37  * and we cannot use 64bit as it's public API.
     38  */
     39 #ifdef LONG64
     40 #define _XLIB_ASYNC_SEQUENCE_CMP(a,op,b)     ((a == 0) || (a op b))
     41 #else /* !LONG64 */
     42 #define _XLIB_ASYNC_SEQUENCE_CMP(a,op,b)     ((a == 0) || \
     43                                               (((a op b) && (b - a op (UINT32_MAX >> 1))) || \
     44                                                ((b op a) && ((UINT32_MAX >> 1) op a - b))))
     45 #endif /* !LONG64 */
     46 
     47 /*ARGSUSED*/
     48 Bool
     49 _XAsyncErrorHandler(
     50     register Display *dpy,
     51     register xReply *rep,
     52     char *buf,
     53     int len,
     54     XPointer data)
     55 {
     56     register _XAsyncErrorState *state;
     57 
     58     state = (_XAsyncErrorState *)data;
     59     if (rep->generic.type == X_Error &&
     60 	(!state->error_code ||
     61 	 rep->error.errorCode == state->error_code) &&
     62 	(!state->major_opcode ||
     63 	 rep->error.majorCode == state->major_opcode) &&
     64 	(!state->minor_opcode ||
     65 	 rep->error.minorCode == state->minor_opcode) &&
     66 	(_XLIB_ASYNC_SEQUENCE_CMP(state->min_sequence_number,<=,dpy->last_request_read)) &&
     67 	(_XLIB_ASYNC_SEQUENCE_CMP(state->max_sequence_number,>=,dpy->last_request_read))) {
     68 	state->last_error_received = rep->error.errorCode;
     69 	state->error_count++;
     70 	return True;
     71     }
     72     return False;
     73 }
     74 
     75 void _XDeqAsyncHandler(
     76     Display *dpy,
     77     register _XAsyncHandler *handler)
     78 {
     79     register _XAsyncHandler **prev;
     80     register _XAsyncHandler *async;
     81 
     82     for (prev = &dpy->async_handlers;
     83 	 (async = *prev) && (async != handler);
     84 	 prev = &async->next)
     85 	;
     86     if (async)
     87 	*prev = async->next;
     88 }
     89 
     90 char *
     91 _XGetAsyncReply(
     92     register Display *dpy,
     93     register char *replbuf,	/* data is read into this buffer */
     94     register xReply *rep,	/* value passed to calling handler */
     95     char *buf,			/* value passed to calling handler */
     96     int len,			/* value passed to calling handler */
     97     int extra,			/* extra words to read, ala _XReply */
     98     Bool discard)		/* discard after extra?, ala _XReply */
     99 {
    100     if (extra == 0) {
    101 	if (discard && (rep->generic.length << 2) > len)
    102 	    _XEatData (dpy, (rep->generic.length << 2) - len);
    103 	return (char *)rep;
    104     }
    105 
    106     if (extra <= rep->generic.length) {
    107 	int size = SIZEOF(xReply) + (extra << 2);
    108 	if (size > len) {
    109 	    memcpy(replbuf, buf, len);
    110 	    _XRead(dpy, replbuf + len, size - len);
    111 	    buf = replbuf;
    112 	    len = size;
    113 	}
    114 
    115 	if (discard && rep->generic.length > extra &&
    116 	    (rep->generic.length << 2) > len)
    117 	    _XEatData (dpy, (rep->generic.length << 2) - len);
    118 
    119 	return buf;
    120     }
    121     /*
    122      *if we get here, then extra > rep->generic.length--meaning we
    123      * read a reply that's shorter than we expected.  This is an
    124      * error,  but we still need to figure out how to handle it...
    125      */
    126     if ((rep->generic.length << 2) > len)
    127 	_XEatData (dpy, (rep->generic.length << 2) - len);
    128     _XIOError (dpy);
    129     return (char *)rep;
    130 }
    131 
    132 void
    133 _XGetAsyncData(
    134     Display *dpy,
    135     char *data,			/* data is read into this buffer */
    136     char *buf,			/* value passed to calling handler */
    137     int len,			/* value passed to calling handler */
    138     int skip,			/* number of bytes already read in previous
    139 				   _XGetAsyncReply or _XGetAsyncData calls */
    140     int datalen,		/* size of data buffer in bytes */
    141     int discardtotal)		/* min. bytes to consume (after skip) */
    142 {
    143     buf += skip;
    144     len -= skip;
    145     if (!data) {
    146 	if (datalen > len)
    147 	    _XEatData(dpy, datalen - len);
    148     } else if (datalen <= len) {
    149 	memcpy(data, buf, datalen);
    150     } else {
    151 	memcpy(data, buf, len);
    152 	_XRead(dpy, data + len, datalen - len);
    153     }
    154     if (discardtotal > len) {
    155 	if (datalen > len)
    156 	    len = datalen;
    157 	_XEatData(dpy, discardtotal - len);
    158     }
    159 }
    160