|
|
1.1 ! root 1: #include <X/mit-copyright.h> ! 2: ! 3: /* Copyright Massachusetts Institute of Technology 1985 */ ! 4: ! 5: /* ! 6: * XlibInternal.c - Internal support routines for the C subroutine ! 7: * interface library (Xlib) to the X Window System Protocol V8.0. ! 8: */ ! 9: ! 10: #include "XlibInternal.h" ! 11: #include <sys/uio.h> ! 12: ! 13: /* ! 14: * The following routines are internal routines used by Xlib for protocol ! 15: * packet transmission and reception. ! 16: * ! 17: * XIOError(Display *) will be called if any sort of system call error occurs. ! 18: * This is assumed to be a fatal condition, i.e., XIOError should not return. ! 19: * ! 20: * XError(Display *, XErrorEvent *) will be called whenever an X_Error event is ! 21: * received. This is not assumed to be a fatal condition, i.e., it is ! 22: * acceptable for this procedure to return. However, XError should NOT ! 23: * perform any operations (directly or indirectly) on the DISPLAY. ! 24: * ! 25: * Routines declared with a return type of 'Status' return 0 on failure, ! 26: * and non 0 on success. Routines with no declared return type don't ! 27: * return anything. Whenever possible routines that create objects return ! 28: * the object they have created. ! 29: */ ! 30: ! 31: #ifndef lint ! 32: static char rcsid[] = "$Header: XlibInternal.c,v 10.12 86/02/01 15:42:11 tony Rel $"; ! 33: #endif ! 34: ! 35: Display *_XlibCurrentDisplay = NULL; /* default display to use in library */ ! 36: _QEvent *_qfree = NULL; /* NULL _QEvent. */ ! 37: ! 38: static int padlength[4] = {0, 3, 2, 1}; ! 39: /* lookup table for adding padding bytes to data that is read from ! 40: or written to the X socket. */ ! 41: ! 42: /* ! 43: * _XFlush - Flush the X request buffer. If the buffer is empty, no ! 44: * action is taken. This routine correctly handles incremental writes. ! 45: */ ! 46: _XFlush (dpy) ! 47: register Display *dpy; ! 48: { ! 49: register int size; ! 50: register int write_stat; ! 51: register char *bufindex; ! 52: ! 53: size = dpy->bufptr - dpy->buffer; ! 54: bufindex = dpy->bufptr = dpy->buffer; ! 55: /* ! 56: * While write has not written the entire buffer, keep looping ! 57: * untill the entire buffer is written. bufindex will be incremented ! 58: * and size decremented as buffer is written out. ! 59: */ ! 60: while (size) { ! 61: if ((write_stat = write(dpy->fd, bufindex, size)) == -1) { ! 62: /* Write failed! */ ! 63: /* errno set by write system call. */ ! 64: _XIOError(dpy); ! 65: } ! 66: size -= write_stat; ! 67: bufindex += write_stat; ! 68: } ! 69: dpy->lastdraw = NULL; ! 70: } ! 71: ! 72: ! 73: /* ! 74: * _XRead - Read bytes from the socket taking into account incomplete ! 75: * reads. ! 76: */ ! 77: _XRead (dpy, data, size) ! 78: register Display *dpy; ! 79: register char *data; ! 80: register int size; ! 81: { ! 82: register int bytes_read; ! 83: ! 84: while ((bytes_read = read(dpy->fd, data, size)) != size) { ! 85: ! 86: if (bytes_read > 0) { ! 87: size -= bytes_read; ! 88: data += bytes_read; ! 89: } ! 90: ! 91: else if (bytes_read == 0) { ! 92: /* Read failed because of end of file! */ ! 93: errno = EPIPE; ! 94: _XIOError(dpy); ! 95: } ! 96: ! 97: else /* bytes_read is less than 0; presumably -1 */ { ! 98: /* If it's a system call interrupt, it's not an error. */ ! 99: if (errno != EINTR) ! 100: _XIOError(dpy); ! 101: } ! 102: } ! 103: } ! 104: ! 105: /* ! 106: * _XReadPad - Read bytes from the socket taking into account incomplete ! 107: * reads. If the number of bytes is not 0 mod 32, read additional pad ! 108: * bytes. ! 109: */ ! 110: _XReadPad (dpy, data, size) ! 111: register Display *dpy; ! 112: register char *data; ! 113: register int size; ! 114: { ! 115: register int bytes_read; ! 116: struct iovec iov[2]; ! 117: char pad[3]; ! 118: ! 119: iov[0].iov_len = size; ! 120: iov[0].iov_base = data; ! 121: /* ! 122: * The following hack is used to provide 32 bit long-word ! 123: * aligned padding. The [1] vector is of length 0, 1, 2, or 3, ! 124: * whatever is needed. ! 125: */ ! 126: ! 127: iov[1].iov_len = padlength[size & 3]; ! 128: iov[1].iov_base = pad; ! 129: size += iov[1].iov_len; ! 130: ! 131: while ((bytes_read = readv (dpy->fd, iov, 2)) != size) { ! 132: ! 133: if (bytes_read > 0) { ! 134: size -= bytes_read; ! 135: if ((iov[0].iov_len -= bytes_read) < 0) { ! 136: iov[1].iov_len += iov[0].iov_len; ! 137: iov[1].iov_base -= iov[0].iov_len; ! 138: iov[0].iov_len = 0; ! 139: } ! 140: else ! 141: iov[0].iov_base += bytes_read; ! 142: } ! 143: ! 144: else if (bytes_read == 0) { ! 145: /* Read failed because of end of file! */ ! 146: errno = EPIPE; ! 147: _XIOError(dpy); ! 148: } ! 149: ! 150: else /* bytes_read is less than 0; presumably -1 */ { ! 151: /* If it's a system call interrupt, it's not an error. */ ! 152: if (errno != EINTR) ! 153: _XIOError(dpy); ! 154: } ! 155: } ! 156: ! 157: } ! 158: ! 159: /* ! 160: * _XSend - Flush the buffer and send the client data. 32 bit word aligned ! 161: * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. ! 162: */ ! 163: _XSend (dpy, data, size) ! 164: register Display *dpy; ! 165: char *data; ! 166: register int size; ! 167: { ! 168: register int len; ! 169: struct iovec iov[3]; ! 170: char pad[3]; ! 171: ! 172: iov[0].iov_len = len = dpy->bufptr - dpy->buffer; ! 173: iov[0].iov_base = dpy->bufptr = dpy->buffer; ! 174: iov[1].iov_len = size; ! 175: iov[1].iov_base = data; ! 176: /* ! 177: * The following hack is used to provide 32 bit long-word ! 178: * aligned padding. The [2] vector is of length 0, 1, 2, or 3, ! 179: * whatever is needed. ! 180: */ ! 181: iov[2].iov_len = padlength[size & 3]; ! 182: iov[2].iov_base = pad; ! 183: len += (size + 3) & ~3; ! 184: /* ! 185: * Use while to allow for incremental writes. ! 186: */ ! 187: while ((size = writev(dpy->fd, iov, 3)) != len) { ! 188: if (size < 0) _XIOError(dpy); ! 189: len -= size; ! 190: if ((iov[0].iov_len -= size) < 0) { ! 191: iov[1].iov_len += iov[0].iov_len; ! 192: iov[1].iov_base -= iov[0].iov_len; ! 193: iov[0].iov_len = 0; ! 194: if (iov[1].iov_len < 0) { ! 195: iov[2].iov_len += iov[1].iov_len; ! 196: iov[2].iov_base -= iov[1].iov_len; ! 197: iov[1].iov_len = 0; ! 198: } ! 199: } ! 200: else { ! 201: iov[0].iov_base += size; ! 202: } ! 203: } ! 204: dpy->lastdraw = NULL; ! 205: } ! 206: ! 207: /* ! 208: * _XReply - Wait for a reply packet and copy its contents into the ! 209: * specified rep. Mean while we must handle error and event packets that ! 210: * we may encounter. ! 211: */ ! 212: Status _XReply (dpy, rep) ! 213: register Display *dpy; ! 214: register XRep *rep; ! 215: { ! 216: _XFlush(dpy); ! 217: while (1) { ! 218: _XRead(dpy, (char *)rep, sizeof(XRep)); ! 219: switch ((int)rep->code) { ! 220: ! 221: case X_Reply: ! 222: /* Reply recieved. */ ! 223: return(1); ! 224: ! 225: case X_Error: ! 226: { ! 227: /* X_Error packet encountered! */ ! 228: int current_request = dpy->request; ! 229: XErrorEvent *error = (XErrorEvent *) rep; ! 230: ! 231: if (error->serial == current_request) ! 232: /* do not die on "no such font", "can't allocate", ! 233: "can't grab" failures */ ! 234: switch (error->error_code) { ! 235: case BadFont: ! 236: if (error->request_code != X_GetFont) ! 237: break; ! 238: case BadAlloc: ! 239: case BadColor: ! 240: case BadGrab: ! 241: return (0); ! 242: } ! 243: _XError(dpy, error); ! 244: if (error->serial == current_request) ! 245: return(0); ! 246: } ! 247: break; ! 248: default: ! 249: _XEnq(dpy, (XEvent *) rep); ! 250: break; ! 251: } ! 252: } ! 253: } ! 254: ! 255: ! 256: /* ! 257: * _XEnq - Place event packets on the display's queue. ! 258: */ ! 259: _XEnq (dpy, event) ! 260: register Display *dpy; ! 261: register XEvent *event; ! 262: { ! 263: register _QEvent *qelt; ! 264: extern char *malloc(); ! 265: ! 266: if ( ! 267: /* If we are squishing MouseMoved events AND ... */ ! 268: dpy->squish && ! 269: /* the current event is a MouseMoved event AND ... */ ! 270: (event->type == MouseMoved) && ! 271: /* if there is a last event on the display queue AND ... */ ! 272: (qelt = dpy->tail) && ! 273: /* if that last event is also a MouseMoved event AND ... */ ! 274: (qelt->event.type == MouseMoved) && ! 275: /* it has the same event window as the current event ... */ ! 276: (event->window == qelt->event.window) ! 277: ) { ! 278: /* then replace the last event with the current event! */ ! 279: qelt->event = *event; ! 280: return; ! 281: } ! 282: if (qelt = _qfree) { ! 283: /* If _qfree is non-NULL do this, else malloc a new one. */ ! 284: _qfree = qelt->next; ! 285: } ! 286: else if ((qelt = (_QEvent *) malloc((unsigned)sizeof(_QEvent))) == NULL) { ! 287: /* Malloc call failed! */ ! 288: errno = ENOMEM; ! 289: _XIOError(dpy); ! 290: } ! 291: qelt->next = NULL; ! 292: qelt->event = *event; ! 293: if (dpy->tail) { ! 294: dpy->tail->next = qelt; ! 295: } ! 296: else { ! 297: dpy->head = qelt; ! 298: } ! 299: dpy->tail = qelt; ! 300: dpy->qlen++; ! 301: } ! 302: ! 303: ! 304: /* ! 305: * Undefine the routine pointers so we can define the following default ! 306: * routines. ! 307: */ ! 308: #undef _XError ! 309: #undef _XIOError ! 310: ! 311: ! 312: /* ! 313: * _XIOError - Default fatal system error reporting routine. Called when ! 314: * an X internal system error is encountered. ! 315: */ ! 316: /*ARGSUSED*/ ! 317: _XIOError (dpy) ! 318: Display *dpy; ! 319: { ! 320: perror("XIO"); ! 321: exit(1); ! 322: } ! 323: ! 324: ! 325: /* ! 326: * _XError - Default non-fatal error reporting routine. Called when an ! 327: * X_Error packet is encountered in the input stream. ! 328: */ ! 329: _XError (dpy, rep) ! 330: Display *dpy; ! 331: XErrorEvent *rep; ! 332: { ! 333: fprintf(stderr, "X Error: %s\n", XErrDescrip (rep->error_code)); ! 334: fprintf(stderr, " Request code: %d\n", rep->request_code); ! 335: fprintf(stderr, " Request function: %d\n", rep->func); ! 336: fprintf(stderr, " Request window 0x%x\n", rep->window); ! 337: fprintf(stderr, " Error Serial #%d\n", rep->serial); ! 338: fprintf(stderr, " Current serial #%d\n", dpy->request); ! 339: exit(1); ! 340: } ! 341: ! 342: int (*_XIOErrorFunction)() = _XIOError; ! 343: int (*_XErrorFunction)() = _XError;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.