Blame src/XlibAsync.c

Packit Service dc579d
/*
Packit Service dc579d
Packit Service dc579d
Copyright 1992, 1998  The Open Group
Packit Service dc579d
Packit Service dc579d
Permission to use, copy, modify, distribute, and sell this software and its
Packit Service dc579d
documentation for any purpose is hereby granted without fee, provided that
Packit Service dc579d
the above copyright notice appear in all copies and that both that
Packit Service dc579d
copyright notice and this permission notice appear in supporting
Packit Service dc579d
documentation.
Packit Service dc579d
Packit Service dc579d
The above copyright notice and this permission notice shall be included
Packit Service dc579d
in all copies or substantial portions of the Software.
Packit Service dc579d
Packit Service dc579d
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Packit Service dc579d
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit Service dc579d
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Packit Service dc579d
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
Packit Service dc579d
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
Packit Service dc579d
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Packit Service dc579d
OTHER DEALINGS IN THE SOFTWARE.
Packit Service dc579d
Packit Service dc579d
Except as contained in this notice, the name of The Open Group shall
Packit Service dc579d
not be used in advertising or otherwise to promote the sale, use or
Packit Service dc579d
other dealings in this Software without prior written authorization
Packit Service dc579d
from The Open Group.
Packit Service dc579d
Packit Service dc579d
*/
Packit Service dc579d
Packit Service dc579d
#ifdef HAVE_CONFIG_H
Packit Service dc579d
#include <config.h>
Packit Service dc579d
#endif
Packit Service dc579d
#include <X11/Xlibint.h>
Packit Service dc579d
#include <X11/Xos.h>
Packit Service dc579d
Packit Service dc579d
/*
Packit Service dc579d
 * Xlib's _XAsyncErrorState sequence number may wrap in 32bit
Packit Service dc579d
 * and we cannot use 64bit as it's public API.
Packit Service dc579d
 */
Packit Service dc579d
#ifdef LONG64
Packit Service dc579d
#define _XLIB_ASYNC_SEQUENCE_CMP(a,op,b)     ((a == 0) || (a op b))
Packit Service dc579d
#else /* !LONG64 */
Packit Service dc579d
#define _XLIB_ASYNC_SEQUENCE_CMP(a,op,b)     ((a == 0) || \
Packit Service dc579d
                                              (((a op b) && (b - a op (UINT32_MAX >> 1))) || \
Packit Service dc579d
                                               ((b op a) && ((UINT32_MAX >> 1) op a - b))))
Packit Service dc579d
#endif /* !LONG64 */
Packit Service dc579d
Packit Service dc579d
/*ARGSUSED*/
Packit Service dc579d
Bool
Packit Service dc579d
_XAsyncErrorHandler(
Packit Service dc579d
    register Display *dpy,
Packit Service dc579d
    register xReply *rep,
Packit Service dc579d
    char *buf,
Packit Service dc579d
    int len,
Packit Service dc579d
    XPointer data)
Packit Service dc579d
{
Packit Service dc579d
    register _XAsyncErrorState *state;
Packit Service dc579d
Packit Service dc579d
    state = (_XAsyncErrorState *)data;
Packit Service dc579d
    if (rep->generic.type == X_Error &&
Packit Service dc579d
	(!state->error_code ||
Packit Service dc579d
	 rep->error.errorCode == state->error_code) &&
Packit Service dc579d
	(!state->major_opcode ||
Packit Service dc579d
	 rep->error.majorCode == state->major_opcode) &&
Packit Service dc579d
	(!state->minor_opcode ||
Packit Service dc579d
	 rep->error.minorCode == state->minor_opcode) &&
Packit Service dc579d
	(_XLIB_ASYNC_SEQUENCE_CMP(state->min_sequence_number,<=,dpy->last_request_read)) &&
Packit Service dc579d
	(_XLIB_ASYNC_SEQUENCE_CMP(state->max_sequence_number,>=,dpy->last_request_read))) {
Packit Service dc579d
	state->last_error_received = rep->error.errorCode;
Packit Service dc579d
	state->error_count++;
Packit Service dc579d
	return True;
Packit Service dc579d
    }
Packit Service dc579d
    return False;
Packit Service dc579d
}
Packit Service dc579d
Packit Service dc579d
void _XDeqAsyncHandler(
Packit Service dc579d
    Display *dpy,
Packit Service dc579d
    register _XAsyncHandler *handler)
Packit Service dc579d
{
Packit Service dc579d
    register _XAsyncHandler **prev;
Packit Service dc579d
    register _XAsyncHandler *async;
Packit Service dc579d
Packit Service dc579d
    for (prev = &dpy->async_handlers;
Packit Service dc579d
	 (async = *prev) && (async != handler);
Packit Service dc579d
	 prev = &async->next)
Packit Service dc579d
	;
Packit Service dc579d
    if (async)
Packit Service dc579d
	*prev = async->next;
Packit Service dc579d
}
Packit Service dc579d
Packit Service dc579d
char *
Packit Service dc579d
_XGetAsyncReply(
Packit Service dc579d
    register Display *dpy,
Packit Service dc579d
    register char *replbuf,	/* data is read into this buffer */
Packit Service dc579d
    register xReply *rep,	/* value passed to calling handler */
Packit Service dc579d
    char *buf,			/* value passed to calling handler */
Packit Service dc579d
    int len,			/* value passed to calling handler */
Packit Service dc579d
    int extra,			/* extra words to read, ala _XReply */
Packit Service dc579d
    Bool discard)		/* discard after extra?, ala _XReply */
Packit Service dc579d
{
Packit Service dc579d
    if (extra == 0) {
Packit Service dc579d
	if (discard && (rep->generic.length << 2) > len)
Packit Service dc579d
	    _XEatData (dpy, (rep->generic.length << 2) - len);
Packit Service dc579d
	return (char *)rep;
Packit Service dc579d
    }
Packit Service dc579d
Packit Service dc579d
    if (extra <= rep->generic.length) {
Packit Service dc579d
	int size = SIZEOF(xReply) + (extra << 2);
Packit Service dc579d
	if (size > len) {
Packit Service dc579d
	    memcpy(replbuf, buf, len);
Packit Service dc579d
	    _XRead(dpy, replbuf + len, size - len);
Packit Service dc579d
	    buf = replbuf;
Packit Service dc579d
	    len = size;
Packit Service dc579d
	}
Packit Service dc579d
Packit Service dc579d
	if (discard && rep->generic.length > extra &&
Packit Service dc579d
	    (rep->generic.length << 2) > len)
Packit Service dc579d
	    _XEatData (dpy, (rep->generic.length << 2) - len);
Packit Service dc579d
Packit Service dc579d
	return buf;
Packit Service dc579d
    }
Packit Service dc579d
    /*
Packit Service dc579d
     *if we get here, then extra > rep->generic.length--meaning we
Packit Service dc579d
     * read a reply that's shorter than we expected.  This is an
Packit Service dc579d
     * error,  but we still need to figure out how to handle it...
Packit Service dc579d
     */
Packit Service dc579d
    if ((rep->generic.length << 2) > len)
Packit Service dc579d
	_XEatData (dpy, (rep->generic.length << 2) - len);
Packit Service dc579d
    _XIOError (dpy);
Packit Service dc579d
    return (char *)rep;
Packit Service dc579d
}
Packit Service dc579d
Packit Service dc579d
void
Packit Service dc579d
_XGetAsyncData(
Packit Service dc579d
    Display *dpy,
Packit Service dc579d
    char *data,			/* data is read into this buffer */
Packit Service dc579d
    char *buf,			/* value passed to calling handler */
Packit Service dc579d
    int len,			/* value passed to calling handler */
Packit Service dc579d
    int skip,			/* number of bytes already read in previous
Packit Service dc579d
				   _XGetAsyncReply or _XGetAsyncData calls */
Packit Service dc579d
    int datalen,		/* size of data buffer in bytes */
Packit Service dc579d
    int discardtotal)		/* min. bytes to consume (after skip) */
Packit Service dc579d
{
Packit Service dc579d
    buf += skip;
Packit Service dc579d
    len -= skip;
Packit Service dc579d
    if (!data) {
Packit Service dc579d
	if (datalen > len)
Packit Service dc579d
	    _XEatData(dpy, datalen - len);
Packit Service dc579d
    } else if (datalen <= len) {
Packit Service dc579d
	memcpy(data, buf, datalen);
Packit Service dc579d
    } else {
Packit Service dc579d
	memcpy(data, buf, len);
Packit Service dc579d
	_XRead(dpy, data + len, datalen - len);
Packit Service dc579d
    }
Packit Service dc579d
    if (discardtotal > len) {
Packit Service dc579d
	if (datalen > len)
Packit Service dc579d
	    len = datalen;
Packit Service dc579d
	_XEatData(dpy, discardtotal - len);
Packit Service dc579d
    }
Packit Service dc579d
}