|
|
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.13 86/04/22 15:30:52 jg Rel $"; ! 33: #endif ! 34: ! 35: #ifdef titan ! 36: #define iovbase iov_base.saddr ! 37: #else ! 38: #define iovbase iov_base ! 39: #endif ! 40: Display *_XlibCurrentDisplay = NULL; /* default display to use in library */ ! 41: _QEvent *_qfree = NULL; /* NULL _QEvent. */ ! 42: ! 43: static int padlength[4] = {0, 3, 2, 1}; ! 44: /* lookup table for adding padding bytes to data that is read from ! 45: or written to the X socket. */ ! 46: ! 47: /* ! 48: * _XFlush - Flush the X request buffer. If the buffer is empty, no ! 49: * action is taken. This routine correctly handles incremental writes. ! 50: */ ! 51: _XFlush (dpy) ! 52: register Display *dpy; ! 53: { ! 54: register int size; ! 55: register int write_stat; ! 56: register char *bufindex; ! 57: ! 58: size = dpy->bufptr - dpy->buffer; ! 59: bufindex = dpy->bufptr = dpy->buffer; ! 60: /* ! 61: * While write has not written the entire buffer, keep looping ! 62: * untill the entire buffer is written. bufindex will be incremented ! 63: * and size decremented as buffer is written out. ! 64: */ ! 65: while (size) { ! 66: if ((write_stat = write(dpy->fd, bufindex, size)) == -1) { ! 67: /* Write failed! */ ! 68: /* errno set by write system call. */ ! 69: _XIOError(dpy); ! 70: } ! 71: size -= write_stat; ! 72: bufindex += write_stat; ! 73: } ! 74: dpy->lastdraw = NULL; ! 75: } ! 76: ! 77: ! 78: /* ! 79: * _XRead - Read bytes from the socket taking into account incomplete ! 80: * reads. ! 81: */ ! 82: _XRead (dpy, data, size) ! 83: register Display *dpy; ! 84: register char *data; ! 85: register int size; ! 86: { ! 87: register int bytes_read; ! 88: ! 89: while ((bytes_read = read(dpy->fd, data, size)) != size) { ! 90: ! 91: if (bytes_read > 0) { ! 92: size -= bytes_read; ! 93: data += bytes_read; ! 94: } ! 95: ! 96: else if (bytes_read == 0) { ! 97: /* Read failed because of end of file! */ ! 98: errno = EPIPE; ! 99: _XIOError(dpy); ! 100: } ! 101: ! 102: else /* bytes_read is less than 0; presumably -1 */ { ! 103: /* If it's a system call interrupt, it's not an error. */ ! 104: if (errno != EINTR) ! 105: _XIOError(dpy); ! 106: } ! 107: } ! 108: } ! 109: ! 110: /* ! 111: * _XReadPad - Read bytes from the socket taking into account incomplete ! 112: * reads. If the number of bytes is not 0 mod 32, read additional pad ! 113: * bytes. ! 114: */ ! 115: _XReadPad (dpy, data, size) ! 116: register Display *dpy; ! 117: register char *data; ! 118: register int size; ! 119: { ! 120: register int bytes_read; ! 121: struct iovec iov[2]; ! 122: char pad[3]; ! 123: ! 124: iov[0].iov_len = size; ! 125: iov[0].iovbase = data; ! 126: /* ! 127: * The following hack is used to provide 32 bit long-word ! 128: * aligned padding. The [1] vector is of length 0, 1, 2, or 3, ! 129: * whatever is needed. ! 130: */ ! 131: ! 132: iov[1].iov_len = padlength[size & 3]; ! 133: iov[1].iovbase = pad; ! 134: size += iov[1].iov_len; ! 135: ! 136: while ((bytes_read = readv (dpy->fd, iov, 2)) != size) { ! 137: ! 138: if (bytes_read > 0) { ! 139: size -= bytes_read; ! 140: if ((iov[0].iov_len -= bytes_read) < 0) { ! 141: iov[1].iov_len += iov[0].iov_len; ! 142: iov[1].iovbase -= iov[0].iov_len; ! 143: iov[0].iov_len = 0; ! 144: } ! 145: else ! 146: iov[0].iovbase += bytes_read; ! 147: } ! 148: ! 149: else if (bytes_read == 0) { ! 150: /* Read failed because of end of file! */ ! 151: errno = EPIPE; ! 152: _XIOError(dpy); ! 153: } ! 154: ! 155: else /* bytes_read is less than 0; presumably -1 */ { ! 156: /* If it's a system call interrupt, it's not an error. */ ! 157: if (errno != EINTR) ! 158: _XIOError(dpy); ! 159: } ! 160: } ! 161: ! 162: } ! 163: ! 164: /* ! 165: * _XSend - Flush the buffer and send the client data. 32 bit word aligned ! 166: * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. ! 167: */ ! 168: _XSend (dpy, data, size) ! 169: register Display *dpy; ! 170: char *data; ! 171: register int size; ! 172: { ! 173: register int len; ! 174: struct iovec iov[3]; ! 175: char pad[3]; ! 176: ! 177: iov[0].iov_len = len = dpy->bufptr - dpy->buffer; ! 178: iov[0].iovbase = dpy->bufptr = dpy->buffer; ! 179: iov[1].iov_len = size; ! 180: iov[1].iovbase = data; ! 181: /* ! 182: * The following hack is used to provide 32 bit long-word ! 183: * aligned padding. The [2] vector is of length 0, 1, 2, or 3, ! 184: * whatever is needed. ! 185: */ ! 186: iov[2].iov_len = padlength[size & 3]; ! 187: iov[2].iovbase = pad; ! 188: len += (size + 3) & ~3; ! 189: /* ! 190: * Use while to allow for incremental writes. ! 191: */ ! 192: while ((size = writev(dpy->fd, iov, 3)) != len) { ! 193: if (size < 0) _XIOError(dpy); ! 194: len -= size; ! 195: if ((iov[0].iov_len -= size) < 0) { ! 196: iov[1].iov_len += iov[0].iov_len; ! 197: iov[1].iovbase -= iov[0].iov_len; ! 198: iov[0].iov_len = 0; ! 199: if (iov[1].iov_len < 0) { ! 200: iov[2].iov_len += iov[1].iov_len; ! 201: iov[2].iovbase -= iov[1].iov_len; ! 202: iov[1].iov_len = 0; ! 203: } ! 204: } ! 205: else { ! 206: iov[0].iovbase += size; ! 207: } ! 208: } ! 209: dpy->lastdraw = NULL; ! 210: } ! 211: ! 212: /* ! 213: * _XReply - Wait for a reply packet and copy its contents into the ! 214: * specified rep. Mean while we must handle error and event packets that ! 215: * we may encounter. ! 216: */ ! 217: Status _XReply (dpy, rep) ! 218: register Display *dpy; ! 219: register XRep *rep; ! 220: { ! 221: _XFlush(dpy); ! 222: while (1) { ! 223: _XRead(dpy, (char *)rep, sizeof(XRep)); ! 224: switch ((int)rep->code) { ! 225: ! 226: case X_Reply: ! 227: /* Reply recieved. */ ! 228: return(1); ! 229: ! 230: case X_Error: ! 231: { ! 232: /* X_Error packet encountered! */ ! 233: int current_request = dpy->request; ! 234: XErrorEvent *error = (XErrorEvent *) rep; ! 235: ! 236: if (error->serial == current_request) ! 237: /* do not die on "no such font", "can't allocate", ! 238: "can't grab" failures */ ! 239: switch (error->error_code) { ! 240: case BadFont: ! 241: if (error->request_code != X_GetFont) ! 242: break; ! 243: case BadAlloc: ! 244: case BadColor: ! 245: case BadGrab: ! 246: return (0); ! 247: } ! 248: _XError(dpy, error); ! 249: if (error->serial == current_request) ! 250: return(0); ! 251: } ! 252: break; ! 253: default: ! 254: _XEnq(dpy, (XEvent *) rep); ! 255: break; ! 256: } ! 257: } ! 258: } ! 259: ! 260: ! 261: /* ! 262: * _XEnq - Place event packets on the display's queue. ! 263: */ ! 264: _XEnq (dpy, event) ! 265: register Display *dpy; ! 266: register XEvent *event; ! 267: { ! 268: register _QEvent *qelt; ! 269: extern char *malloc(); ! 270: ! 271: if ( ! 272: /* If we are squishing MouseMoved events AND ... */ ! 273: dpy->squish && ! 274: /* the current event is a MouseMoved event AND ... */ ! 275: (event->type == MouseMoved) && ! 276: /* if there is a last event on the display queue AND ... */ ! 277: (qelt = dpy->tail) && ! 278: /* if that last event is also a MouseMoved event AND ... */ ! 279: (qelt->event.type == MouseMoved) && ! 280: /* it has the same event window as the current event ... */ ! 281: (event->window == qelt->event.window) ! 282: ) { ! 283: /* then replace the last event with the current event! */ ! 284: qelt->event = *event; ! 285: return; ! 286: } ! 287: if (qelt = _qfree) { ! 288: /* If _qfree is non-NULL do this, else malloc a new one. */ ! 289: _qfree = qelt->next; ! 290: } ! 291: else if ((qelt = (_QEvent *) malloc((unsigned)sizeof(_QEvent))) == NULL) { ! 292: /* Malloc call failed! */ ! 293: errno = ENOMEM; ! 294: _XIOError(dpy); ! 295: } ! 296: qelt->next = NULL; ! 297: qelt->event = *event; ! 298: if (dpy->tail) { ! 299: dpy->tail->next = qelt; ! 300: } ! 301: else { ! 302: dpy->head = qelt; ! 303: } ! 304: dpy->tail = qelt; ! 305: dpy->qlen++; ! 306: } ! 307: ! 308: ! 309: /* ! 310: * Undefine the routine pointers so we can define the following default ! 311: * routines. ! 312: */ ! 313: #undef _XError ! 314: #undef _XIOError ! 315: ! 316: ! 317: /* ! 318: * _XIOError - Default fatal system error reporting routine. Called when ! 319: * an X internal system error is encountered. ! 320: */ ! 321: /*ARGSUSED*/ ! 322: _XIOError (dpy) ! 323: Display *dpy; ! 324: { ! 325: perror("XIO"); ! 326: exit(1); ! 327: } ! 328: ! 329: ! 330: /* ! 331: * _XError - Default non-fatal error reporting routine. Called when an ! 332: * X_Error packet is encountered in the input stream. ! 333: */ ! 334: _XError (dpy, rep) ! 335: Display *dpy; ! 336: XErrorEvent *rep; ! 337: { ! 338: fprintf(stderr, "X Error: %s\n", XErrDescrip (rep->error_code)); ! 339: fprintf(stderr, " Request code: %d\n", rep->request_code); ! 340: fprintf(stderr, " Request function: %d\n", rep->func); ! 341: fprintf(stderr, " Request window 0x%x\n", rep->window); ! 342: fprintf(stderr, " Error Serial #%d\n", rep->serial); ! 343: fprintf(stderr, " Current serial #%d\n", dpy->request); ! 344: exit(1); ! 345: } ! 346: ! 347: int (*_XIOErrorFunction)() = _XIOError; ! 348: int (*_XErrorFunction)() = _XError; ! 349: ! 350: #ifdef BIGSHORTS ! 351: UnpackShorts(from, to, bytes) ! 352: ushort_p *from; ! 353: short *to; ! 354: unsigned bytes; ! 355: { ! 356: unsigned i; ! 357: for (i = 0; i < (bytes/psizeof(short)); i++) ! 358: if (i&1) ! 359: to[i] = from[i>>1].right; ! 360: else ! 361: to[i] = from[i>>1].left; ! 362: } ! 363: ! 364: char packbuffer[1000]; ! 365: PackData(dpy, data, len) ! 366: register Display *dpy; ! 367: short *data; ! 368: unsigned len; ! 369: { ! 370: if (dpy->bufptr + len < dpy->bufmax) { ! 371: PackShorts(data, dpy->bufptr, len); ! 372: dpy->bufptr += (len + 3) & ~3; ! 373: } else { ! 374: PackShorts(data, packbuffer, len); ! 375: _XSend(dpy, packbuffer, len); ! 376: } ! 377: } ! 378: ! 379: PackShorts(from, to, bytes) ! 380: short *from; ! 381: char *to; ! 382: unsigned bytes; ! 383: { ! 384: unsigned i, n, offset; ! 385: ushort_p *uto; ! 386: ! 387: uto = (ushort_p *)to; ! 388: offset = ((int)to & 2) >> 1; /* lost 2 bits of pointer */ ! 389: n = (bytes / 2) + offset; ! 390: for (i = offset; i < n; i++) { ! 391: if (i&1) ! 392: uto[i>>1].right = from[i-offset]; ! 393: else ! 394: uto[i>>1].left = from[i-offset]; ! 395: } ! 396: } ! 397: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.