1/* 2 3Copyright 1992, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from 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*/ 48Bool 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 75void _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 90char * 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 132void 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