|
|
1.1 ! root 1: /* ! 2: * $XConsortium: XlibInt.c,v 11.90 88/09/30 17:25:18 jim Exp $ ! 3: */ ! 4: ! 5: #include "copyright.h" ! 6: /* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */ ! 7: ! 8: /* ! 9: * XlibInternal.c - Internal support routines for the C subroutine ! 10: * interface library (Xlib) to the X Window System Protocol V11.0. ! 11: */ ! 12: #define NEED_EVENTS ! 13: #define NEED_REPLIES ! 14: ! 15: #include <stdio.h> ! 16: #include "Xlibint.h" ! 17: ! 18: #ifdef ISOCONN ! 19: #include <isode/psap.h> ! 20: #include <isode/tsap.h> ! 21: #include <isode/isoservent.h> ! 22: ! 23: #endif /* ISOCONN */ ! 24: ! 25: #ifdef CRAY ! 26: ! 27: /* ! 28: * Cray UniCOS does not have readv and writev so we emulate ! 29: */ ! 30: #include <sys/socket.h> ! 31: ! 32: static int readv (fd, iov, iovcnt) ! 33: int fd; ! 34: struct iovec *iov; ! 35: int iovcnt; ! 36: { ! 37: struct msghdr hdr; ! 38: ! 39: hdr.msg_iov = iov; ! 40: hdr.msg_iovlen = iovcnt; ! 41: hdr.msg_accrights = 0; ! 42: hdr.msg_accrightslen = 0; ! 43: hdr.msg_name = 0; ! 44: hdr.msg_namelen = 0; ! 45: ! 46: return (recvmsg (fd, &hdr, 0)); ! 47: } ! 48: ! 49: static int writev (fd, iov, iovcnt) ! 50: int fd; ! 51: struct iovec *iov; ! 52: int iovcnt; ! 53: { ! 54: struct msghdr hdr; ! 55: ! 56: hdr.msg_iov = iov; ! 57: hdr.msg_iovlen = iovcnt; ! 58: hdr.msg_accrights = 0; ! 59: hdr.msg_accrightslen = 0; ! 60: hdr.msg_name = 0; ! 61: hdr.msg_namelen = 0; ! 62: ! 63: return (sendmsg (fd, &hdr, 0)); ! 64: } ! 65: ! 66: #endif /* CRAY */ ! 67: ! 68: #ifdef ISOCONN ! 69: /* ! 70: * Need these Convenience routines to map IO to T-service ! 71: * XXX ! 72: * Should map error returns in td->td_reason into ! 73: * errno's appropriately... ! 74: */ ! 75: ! 76: /* ! 77: * Check if any bytes queued that could be read... ! 78: */ ! 79: TBytesReadable(fd, ptr) ! 80: int fd; ! 81: long *ptr; ! 82: { ! 83: struct TSAPdisconnect tds; ! 84: struct TSAPdisconnect *td = &tds; ! 85: int ret = TSelectOctets (fd, ptr, td); ! 86: if (ret == NOTOK) { ! 87: fprintf(stderr, "Client TBytesReadable: %s\n", ! 88: TErrString(td->td_reason)); ! 89: } ! 90: return ret; ! 91: } ! 92: ! 93: /* ! 94: * need followinf for arg mismatch ! 95: */ ! 96: UBytesReadable(fd, ptr) ! 97: int fd; ! 98: long *ptr; ! 99: { ! 100: return ioctl(fd, FIONREAD, ptr); ! 101: } ! 102: ! 103: /* ! 104: * Simple read from transport cx, client ! 105: */ ! 106: TReadFromServer(fd, data, size) ! 107: int fd; ! 108: unsigned size; ! 109: char *data; ! 110: { ! 111: char *aptr = data; ! 112: struct TSAPdisconnect tds; ! 113: struct TSAPdisconnect *td = &tds; ! 114: static struct TSAPdata txs; ! 115: static struct TSAPdata *tx = &txs; ! 116: static struct qbuf *qb; ! 117: static char *qptr; ! 118: static int ingot, qcpy, result = 0; ! 119: int q2data, ret; ! 120: ! 121: #ifdef ISODEBUG ! 122: if (isodexbug) { ! 123: fprintf(stderr, "TReadFromServer %d want %d (%d buffered)\n", ! 124: fd, size, result); ! 125: } ! 126: #endif /* ISODEBUG */ ! 127: if (result == 0) { ! 128: if ((ret = TReadRequest(fd, tx, OK, td)) == NOTOK) { ! 129: #ifdef ISODEBUG ! 130: if (errno == EWOULDBLOCK) { ! 131: fprintf(stderr, "Client TReadReq would block: %s\n", ! 132: TErrString(td->td_reason)); ! 133: if (!DR_FATAL(td->td_reason)) ! 134: errno = EWOULDBLOCK; ! 135: else ! 136: errno = EBADF; ! 137: return ret; ! 138: } ! 139: if (isodexbug) ! 140: fprintf(stderr, "Client TReadReq: %s\n", ! 141: TErrString(td->td_reason)); ! 142: #endif /* ISODEBUG */ ! 143: /* ! 144: * map problems here - eg fTimeOut... ! 145: */ ! 146: if (td->td_reason == DR_TIMER) ! 147: errno = EWOULDBLOCK; ! 148: return ret; ! 149: } ! 150: result = tx->tx_cc; ! 151: qb = &(tx->tx_qbuf); ! 152: qptr = qb->qb_data; ! 153: #ifdef ISODEBUG ! 154: if (isodexbug) ! 155: fprintf(stderr, "TReadRequest want %d got %d\n", ! 156: size, result); ! 157: #endif ! 158: } ! 159: #ifdef ISODEBUG ! 160: else { ! 161: if (isodexbug) ! 162: fprintf(stderr, "TReadFromServer want %d buffered %d\n", ! 163: size, result); ! 164: } ! 165: #endif ! 166: /* ! 167: * Buffer it ! 168: */ ! 169: ingot = 0; ! 170: aptr = data; ! 171: for(ingot = 0, aptr = data, q2data = min(size, result); ! 172: ingot<q2data; ! 173: aptr += qcpy, ingot+= qcpy) { ! 174: int aleft = q2data - ingot; ! 175: if (qb->qb_len > aleft) { ! 176: qcpy = aleft; ! 177: bcopy(qptr, aptr, qcpy); ! 178: qptr += aleft; ! 179: } else { ! 180: qcpy = qb->qb_len; ! 181: bcopy(qb->qb_data, aptr, qcpy); ! 182: if ((qb = qb->qb_forw) == NULL) ! 183: break; ! 184: qptr = qb->qb_data; ! 185: } ! 186: } ! 187: if ((result -= ingot) <= 0) { ! 188: result = 0; ! 189: TXFREE(tx); ! 190: } ! 191: return ingot; ! 192: ! 193: } ! 194: ! 195: /* ! 196: * Simple write on transport descriptor client ! 197: */ ! 198: TWriteToServer(fd, data, size) ! 199: int fd; ! 200: unsigned size; ! 201: char *data; ! 202: { ! 203: struct TSAPdisconnect tds; ! 204: struct TSAPdisconnect *td = &tds; ! 205: ! 206: #ifdef ISODEBUG ! 207: if (isodexbug) ! 208: fprintf(stderr, "TWriteToServer %d: %d\n", fd, size); ! 209: #endif ! 210: if (TDataRequest(fd, data, size, td) == NOTOK) { ! 211: if (errno != EWOULDBLOCK) ! 212: fprintf(stderr, "Client TDataReq: %s\n", ! 213: TErrString(td->td_reason)); ! 214: return -1; ! 215: } else ! 216: return size; ! 217: } ! 218: ! 219: /* ! 220: * This is really disgusting, as we do 2 copies - one qbuf into data, ! 221: * one data into iovecs...should really do something utterly neater or ! 222: * ask mtr to provide another T-Service interface for pre-alloced ! 223: * bufs - ideally iovec style ! 224: * ! 225: * or change the structure of X to do async... ! 226: */ ! 227: TReadvFromServer(fd, iov, iovcnt) ! 228: int fd, iovcnt; ! 229: struct iovec *iov; ! 230: { ! 231: int i, size, result, left, bcp; ! 232: char *data, *dp; ! 233: struct iovec *iovp; ! 234: ! 235: for(i=0, size = 0, iovp = iov; i < iovcnt; i++, iovp++) ! 236: size += iovp->iov_len; ! 237: ! 238: #ifdef ISODEBUG ! 239: if (isodexbug) ! 240: fprintf(stderr, "TReadvFromServer %d, want %d\n", fd, size); ! 241: #endif ! 242: if ((data = Xmalloc(size)) == NULL) { ! 243: #ifdef ISODEBUG ! 244: if (isodexbug) ! 245: fprintf(stderr, "TReadvFromServer, malloc failed\n"); ! 246: #endif ! 247: /* ! 248: * Could map to EWOULDBLOCK...? ! 249: */ ! 250: return(-1); ! 251: } ! 252: ! 253: /* ! 254: * Note, TReadFromServer is written to *NOT* return more than size ! 255: */ ! 256: if ((result = TReadFromServer(fd, data, size)) == NOTOK) { ! 257: if (errno != EWOULDBLOCK) ! 258: fprintf(stderr, "TReadvReq err\n"); ! 259: return(-1); ! 260: } ! 261: ! 262: left = result; ! 263: dp = data; ! 264: while (left > 0) { ! 265: bcp = iov->iov_len; ! 266: if (bcp > left ) ! 267: bcp = left; ! 268: bcopy(dp, iov->iov_base, bcp); ! 269: if (bcp < left) ! 270: iov++; ! 271: dp += bcp; ! 272: left -= bcp; ! 273: } ! 274: Xfree(data); ! 275: return result; ! 276: } ! 277: ! 278: /* ! 279: * scatter gather write to transport descriptor ! 280: */ ! 281: TWritevToServer(fd, iov, iovcnt) ! 282: int fd, iovcnt; ! 283: struct iovec *iov; ! 284: { ! 285: struct TSAPdisconnect tds; ! 286: struct TSAPdisconnect *td = &tds; ! 287: struct udvec uv[64], *uvp; ! 288: int i, ret, tot = 0; ! 289: ! 290: /* ! 291: * Yuck needs dynamicising, or else rely on ! 292: * iov's being same as uv's ! 293: */ ! 294: if (iovcnt >= 64) { ! 295: fprintf(stderr, "Very Bad News i am afraid\n"); ! 296: return -99; ! 297: } ! 298: for (i=0, uvp = uv; i<iovcnt; uvp++, iov++, i++) { ! 299: uvp->uv_base = iov->iov_base; ! 300: uvp->uv_len = iov->iov_len; ! 301: tot += uvp->uv_len; ! 302: } ! 303: #ifdef ISODEBUG ! 304: if (isodexbug) ! 305: fprintf(stderr, "TWritevToServer %d: %d\n",fd, tot); ! 306: #endif ! 307: uv[iovcnt].uv_base = NULLCP; ! 308: uv[iovcnt].uv_len = 0; ! 309: if ((ret = TWriteRequest(fd, uv, td)) == NOTOK) { ! 310: if (errno != EWOULDBLOCK) ! 311: fprintf(stderr, "Client TReadReq: %s\n", TErrString(td->td_reason)); ! 312: return -1; ! 313: } ! 314: return tot; ! 315: } ! 316: ! 317: TDiscFromServer(fd) ! 318: int fd; ! 319: { ! 320: struct TSAPdisconnect tds; ! 321: struct TSAPdisconnect *td = &tds; ! 322: ! 323: if (TDiscRequest(fd, NULLCP, 0, td) == NOTOK) ! 324: fprintf(stderr, "TDR failed %s\n", TErrString(td->td_reason)); ! 325: } ! 326: ! 327: #endif /* ISOCONN */ ! 328: ! 329: /* ! 330: * The following routines are internal routines used by Xlib for protocol ! 331: * packet transmission and reception. ! 332: * ! 333: * XIOError(Display *) will be called if any sort of system call error occurs. ! 334: * This is assumed to be a fatal condition, i.e., XIOError should not return. ! 335: * ! 336: * XError(Display *, XErrorEvent *) will be called whenever an X_Error event is ! 337: * received. This is not assumed to be a fatal condition, i.e., it is ! 338: * acceptable for this procedure to return. However, XError should NOT ! 339: * perform any operations (directly or indirectly) on the DISPLAY. ! 340: * ! 341: * Routines declared with a return type of 'Status' return 0 on failure, ! 342: * and non 0 on success. Routines with no declared return type don't ! 343: * return anything. Whenever possible routines that create objects return ! 344: * the object they have created. ! 345: */ ! 346: ! 347: _XQEvent *_qfree = NULL; /* NULL _XQEvent. */ ! 348: ! 349: static int padlength[4] = {0, 3, 2, 1}; ! 350: /* lookup table for adding padding bytes to data that is read from ! 351: or written to the X socket. */ ! 352: ! 353: static xReq _dummy_request = { ! 354: 0, 0, 0 ! 355: }; ! 356: /* ! 357: * _XFlush - Flush the X request buffer. If the buffer is empty, no ! 358: * action is taken. This routine correctly handles incremental writes. ! 359: * This routine may have to be reworked if int < long. ! 360: */ ! 361: _XFlush (dpy) ! 362: register Display *dpy; ! 363: { ! 364: register long size, todo; ! 365: register int write_stat; ! 366: register char *bufindex; ! 367: ! 368: size = todo = dpy->bufptr - dpy->buffer; ! 369: bufindex = dpy->bufptr = dpy->buffer; ! 370: /* ! 371: * While write has not written the entire buffer, keep looping ! 372: * until the entire buffer is written. bufindex will be incremented ! 373: * and size decremented as buffer is written out. ! 374: */ ! 375: while (size) { ! 376: errno = 0; ! 377: write_stat = WriteToServer(dpy->fd, bufindex, (int) todo); ! 378: if (write_stat >= 0) { ! 379: size -= write_stat; ! 380: todo = size; ! 381: bufindex += write_stat; ! 382: #ifdef EWOULDBLOCK ! 383: } else if (errno == EWOULDBLOCK) { ! 384: _XWaitForWritable(dpy); ! 385: #endif ! 386: #ifdef SUNSYSV ! 387: } else if (errno == 0) { ! 388: _XWaitForWritable(dpy); ! 389: #endif ! 390: #ifdef EMSGSIZE ! 391: } else if (errno == EMSGSIZE) { ! 392: todo >>= 1; ! 393: #endif ! 394: } else { ! 395: /* Write failed! */ ! 396: /* errno set by write system call. */ ! 397: (*_XIOErrorFunction)(dpy); ! 398: } ! 399: } ! 400: dpy->last_req = (char *)&_dummy_request; ! 401: } ! 402: ! 403: int ! 404: _XEventsQueued (dpy, mode) ! 405: register Display *dpy; ! 406: int mode; ! 407: { ! 408: register int len; ! 409: int pend; ! 410: char buf[BUFSIZE]; ! 411: register xReply *rep; ! 412: ! 413: if (mode == QueuedAfterFlush) ! 414: _XFlush(dpy); ! 415: if (BytesReadable(dpy->fd, (char *) &pend) < 0) ! 416: (*_XIOErrorFunction)(dpy); ! 417: if ((len = pend) < SIZEOF(xReply)) ! 418: return(dpy->qlen); /* _XFlush can enqueue events */ ! 419: else if (len > BUFSIZE) ! 420: len = BUFSIZE; ! 421: len /= SIZEOF(xReply); ! 422: pend = len * SIZEOF(xReply); ! 423: _XRead (dpy, buf, (long) pend); ! 424: ! 425: /* no space between comma and type or else macro will die */ ! 426: STARTITERATE (rep,xReply, buf, (len > 0), len--) { ! 427: if (rep->generic.type == X_Error) ! 428: _XError(dpy, (xError *)rep); ! 429: else /* must be an event packet */ ! 430: _XEnq(dpy, (xEvent *) rep); ! 431: } ! 432: ENDITERATE ! 433: return(dpy->qlen); ! 434: } ! 435: ! 436: /* _XReadEvents - Flush the output queue, ! 437: * then read as many events as possible (but at least 1) and enqueue them ! 438: */ ! 439: _XReadEvents(dpy) ! 440: register Display *dpy; ! 441: { ! 442: char buf[BUFSIZE]; ! 443: long pend_not_register; /* because can't "&" a register variable */ ! 444: register long pend; ! 445: register xEvent *ev; ! 446: Bool not_yet_flushed = True; ! 447: ! 448: do { ! 449: /* find out how much data can be read */ ! 450: if (BytesReadable(dpy->fd, (char *) &pend_not_register) < 0) ! 451: (*_XIOErrorFunction)(dpy); ! 452: pend = pend_not_register; ! 453: ! 454: /* must read at least one xEvent; if none is pending, then ! 455: we'll just flush and block waiting for it */ ! 456: if (pend < SIZEOF(xEvent)) { ! 457: pend = SIZEOF(xEvent); ! 458: /* don't flush until we block the first time */ ! 459: if (not_yet_flushed) { ! 460: int qlen = dpy->qlen; ! 461: _XFlush (dpy); ! 462: if (qlen != dpy->qlen) return; ! 463: not_yet_flushed = False; ! 464: } ! 465: } ! 466: ! 467: /* but we won't read more than the max buffer size */ ! 468: if (pend > BUFSIZE) ! 469: pend = BUFSIZE; ! 470: ! 471: /* round down to an integral number of XReps */ ! 472: pend = (pend / SIZEOF(xEvent)) * SIZEOF(xEvent); ! 473: ! 474: _XRead (dpy, buf, pend); ! 475: ! 476: /* no space between comma and type or else macro will die */ ! 477: STARTITERATE (ev,xEvent, buf, (pend > 0), ! 478: pend -= SIZEOF(xEvent)) { ! 479: if (ev->u.u.type == X_Error) ! 480: _XError (dpy, (xError *) ev); ! 481: else /* it's an event packet; enqueue it */ ! 482: _XEnq (dpy, ev); ! 483: } ! 484: ENDITERATE ! 485: } while (dpy->head == NULL); ! 486: } ! 487: ! 488: /* ! 489: * _XRead - Read bytes from the socket taking into account incomplete ! 490: * reads. This routine may have to be reworked if int < long. ! 491: */ ! 492: _XRead (dpy, data, size) ! 493: register Display *dpy; ! 494: register char *data; ! 495: register long size; ! 496: { ! 497: register long bytes_read; ! 498: ! 499: if (size == 0) return; ! 500: errno = 0; ! 501: while ((bytes_read = ReadFromServer(dpy->fd, data, (int)size)) ! 502: != size) { ! 503: ! 504: if (bytes_read > 0) { ! 505: size -= bytes_read; ! 506: data += bytes_read; ! 507: } ! 508: #ifdef EWOULDBLOCK ! 509: else if (errno == EWOULDBLOCK) { ! 510: _XWaitForReadable(dpy); ! 511: errno = 0; ! 512: } ! 513: #endif ! 514: #ifdef SUNSYSV ! 515: else if (errno == 0) { ! 516: _XWaitForReadable(dpy); ! 517: } ! 518: #endif ! 519: else if (bytes_read == 0) { ! 520: /* Read failed because of end of file! */ ! 521: errno = EPIPE; ! 522: (*_XIOErrorFunction)(dpy); ! 523: } ! 524: ! 525: else /* bytes_read is less than 0; presumably -1 */ { ! 526: /* If it's a system call interrupt, it's not an error. */ ! 527: if (errno != EINTR) ! 528: (*_XIOErrorFunction)(dpy); ! 529: } ! 530: } ! 531: } ! 532: ! 533: #ifdef WORD64 ! 534: ! 535: /* ! 536: * XXX This is a *really* stupid way of doing this.... ! 537: */ ! 538: ! 539: #define PACKBUFFERSIZE 4096 ! 540: ! 541: ! 542: /* ! 543: * _XRead32 - Read bytes from the socket unpacking each 32 bits ! 544: * into a long (64 bits on a CRAY computer). ! 545: * ! 546: */ ! 547: static _doXRead32 (dpy, data, size, packbuffer) ! 548: register Display *dpy; ! 549: register long *data; ! 550: register long size; ! 551: register char *packbuffer; ! 552: { ! 553: long *lpack,*lp; ! 554: long mask32 = 0x00000000ffffffff; ! 555: long maskw, nwords, i, bits; ! 556: ! 557: _XReadPad (dpy, packbuffer, size); ! 558: ! 559: lp = data; ! 560: lpack = (long *) packbuffer; ! 561: nwords = size >> 2; ! 562: bits = 32; ! 563: ! 564: for(i=0;i<nwords;i++){ ! 565: maskw = mask32 << bits; ! 566: *lp++ = ( *lpack & maskw ) >> bits; ! 567: bits = bits ^32; ! 568: if(bits){ ! 569: lpack++; ! 570: } ! 571: } ! 572: } ! 573: ! 574: _XRead32 (dpy, data, len) ! 575: Display *dpy; ! 576: long *data; ! 577: long len; ! 578: { ! 579: char packbuffer[PACKBUFFERSIZE]; ! 580: unsigned nwords = (PACKBUFFERSIZE >> 2); /* bytes to CARD32 */ ! 581: ! 582: for (; len > nwords; len -= nwords, data += nwords) { ! 583: _doXRead32 (dpy, data, nwords, packbuffer); ! 584: } ! 585: _doXRead32 (dpy, data, len, packbuffer); ! 586: } ! 587: ! 588: ! 589: ! 590: /* ! 591: * _XRead16 - Read bytes from the socket unpacking each 16 bits ! 592: * into a long (64 bits on a CRAY computer). ! 593: * ! 594: */ ! 595: static _doXRead16 (dpy, data, size, packbuffer) ! 596: register Display *dpy; ! 597: register short *data; ! 598: register long size; ! 599: char *packbuffer; ! 600: { ! 601: long *lpack,*lp; ! 602: long mask16 = 0x000000000000ffff; ! 603: long maskw, nwords, i, bits; ! 604: ! 605: _XRead(dpy,packbuffer,size); /* don't do a padded read... */ ! 606: ! 607: lp = (long *) data; ! 608: lpack = (long *) packbuffer; ! 609: nwords = size >> 1; /* number of 16 bit words to be unpacked */ ! 610: bits = 48; ! 611: for(i=0;i<nwords;i++){ ! 612: maskw = mask16 << bits; ! 613: *lp++ = ( *lpack & maskw ) >> bits; ! 614: bits -= 16; ! 615: if(bits < 0){ ! 616: lpack++; ! 617: bits = 48; ! 618: } ! 619: } ! 620: } ! 621: ! 622: _XRead16 (dpy, data, len) ! 623: Display *dpy; ! 624: short *data; ! 625: long len; ! 626: { ! 627: char packbuffer[PACKBUFFERSIZE]; ! 628: unsigned nwords = (PACKBUFFERSIZE >> 1); /* bytes to CARD16 */ ! 629: ! 630: for (; len > nwords; len -= nwords, data += nwords) { ! 631: _doXRead16 (dpy, data, nwords, packbuffer); ! 632: } ! 633: _doXRead16 (dpy, data, len, packbuffer); ! 634: } ! 635: ! 636: _XRead16Pad (dpy, data, size) ! 637: Display *dpy; ! 638: short *data; ! 639: long size; ! 640: { ! 641: int slop = (size & 3); ! 642: short slopbuf[3]; ! 643: ! 644: _XRead16 (dpy, data, size); ! 645: if (slop > 0) { ! 646: _XRead16 (dpy, slopbuf, 4 - slop); ! 647: } ! 648: } ! 649: #endif /* WORD64 */ ! 650: ! 651: ! 652: /* ! 653: * _XReadPad - Read bytes from the socket taking into account incomplete ! 654: * reads. If the number of bytes is not 0 mod 32, read additional pad ! 655: * bytes. This routine may have to be reworked if int < long. ! 656: */ ! 657: _XReadPad (dpy, data, size) ! 658: register Display *dpy; ! 659: register char *data; ! 660: register long size; ! 661: { ! 662: register long bytes_read; ! 663: struct iovec iov[2]; ! 664: char pad[3]; ! 665: ! 666: if (size == 0) return; ! 667: iov[0].iov_len = (int)size; ! 668: iov[0].iov_base = data; ! 669: /* ! 670: * The following hack is used to provide 32 bit long-word ! 671: * aligned padding. The [1] vector is of length 0, 1, 2, or 3, ! 672: * whatever is needed. ! 673: */ ! 674: ! 675: iov[1].iov_len = padlength[size & 3]; ! 676: iov[1].iov_base = pad; ! 677: size += iov[1].iov_len; ! 678: ! 679: errno = 0; ! 680: while ((bytes_read = ReadvFromServer (dpy->fd, iov, 2)) != size) { ! 681: ! 682: if (bytes_read > 0) { ! 683: size -= bytes_read; ! 684: if ((iov[0].iov_len -= bytes_read) < 0) { ! 685: iov[1].iov_len += iov[0].iov_len; ! 686: iov[1].iov_base -= iov[0].iov_len; ! 687: iov[0].iov_len = 0; ! 688: } ! 689: else ! 690: iov[0].iov_base += bytes_read; ! 691: } ! 692: #ifdef EWOULDBLOCK ! 693: else if (errno == EWOULDBLOCK) { ! 694: _XWaitForReadable(dpy); ! 695: errno = 0; ! 696: } ! 697: #endif ! 698: #ifdef SUNSYSV ! 699: else if (errno == 0) { ! 700: _XWaitForReadable(dpy); ! 701: } ! 702: #endif ! 703: else if (bytes_read == 0) { ! 704: /* Read failed because of end of file! */ ! 705: errno = EPIPE; ! 706: (*_XIOErrorFunction)(dpy); ! 707: } ! 708: ! 709: else /* bytes_read is less than 0; presumably -1 */ { ! 710: /* If it's a system call interrupt, it's not an error. */ ! 711: if (errno != EINTR) ! 712: (*_XIOErrorFunction)(dpy); ! 713: } ! 714: } ! 715: ! 716: } ! 717: ! 718: /* ! 719: * _XSend - Flush the buffer and send the client data. 32 bit word aligned ! 720: * transmission is used, if size is not 0 mod 4, extra bytes are transmitted. ! 721: * This routine may have to be reworked if int < long; ! 722: */ ! 723: _XSend (dpy, data, size) ! 724: register Display *dpy; ! 725: char *data; ! 726: register long size; ! 727: { ! 728: struct iovec iov[3]; ! 729: static char pad[3] = {0, 0, 0}; ! 730: /* XText8 and XText16 require that the padding bytes be zero! */ ! 731: ! 732: long skip = 0; ! 733: long total = (dpy->bufptr - dpy->buffer) + ((size + 3) & ~3); ! 734: long todo = total; ! 735: ! 736: while (total) { ! 737: long before = skip; ! 738: long remain = todo; ! 739: int i = 0; ! 740: long len; ! 741: ! 742: /* You could be very general here and have "in" and "out" iovecs ! 743: * and write a loop without using a macro, but what the heck ! 744: */ ! 745: ! 746: #define InsertIOV(pointer, length) \ ! 747: len = (length) - before; \ ! 748: if (len > remain) \ ! 749: len = remain; \ ! 750: if (len <= 0) { \ ! 751: before = -len; \ ! 752: } else { \ ! 753: iov[i].iov_len = len; \ ! 754: iov[i].iov_base = (pointer) + before; \ ! 755: i++; \ ! 756: remain -= len; \ ! 757: before = 0; \ ! 758: } ! 759: ! 760: InsertIOV(dpy->buffer, dpy->bufptr - dpy->buffer) ! 761: InsertIOV(data, size) ! 762: /* Provide 32-bit aligned padding as necessary */ ! 763: InsertIOV(pad, padlength[size & 3]) ! 764: ! 765: errno = 0; ! 766: if ((len = WritevToServer(dpy->fd, iov, i)) >= 0) { ! 767: skip += len; ! 768: total -= len; ! 769: todo = total; ! 770: #ifdef EWOULDBLOCK ! 771: } else if (errno == EWOULDBLOCK) { ! 772: _XWaitForWritable(dpy); ! 773: #endif ! 774: #ifdef SUNSYSV ! 775: } else if (errno == 0) { ! 776: _XWaitForWritable(dpy); ! 777: #endif ! 778: #ifdef EMSGSIZE ! 779: } else if (errno == EMSGSIZE) { ! 780: todo = todo >> 1; ! 781: #endif ! 782: } else { ! 783: (*_XIOErrorFunction)(dpy); ! 784: } ! 785: } ! 786: ! 787: dpy->bufptr = dpy->buffer; ! 788: dpy->last_req = (char *) & _dummy_request; ! 789: } ! 790: ! 791: /* ! 792: * _XAllocID - normal resource ID allocation routine. A client ! 793: * can roll his own and instatantiate it if he wants, but must ! 794: * follow the rules. ! 795: */ ! 796: XID _XAllocID(dpy) ! 797: register Display *dpy; ! 798: { ! 799: return (dpy->resource_base + (dpy->resource_id++ << dpy->resource_shift)); ! 800: } ! 801: ! 802: /* ! 803: * The hard part about this is that we only get 16 bits from a reply. Well, ! 804: * then, we have three values that will march along, with the following ! 805: * invariant: ! 806: * dpy->last_request_read <= rep->sequenceNumber <= dpy->request ! 807: * The right choice for rep->sequenceNumber is the largest that ! 808: * still meets these constraints. ! 809: */ ! 810: static unsigned long ! 811: _SetLastRequestRead(dpy, rep) ! 812: register Display *dpy; ! 813: register xGenericReply *rep; ! 814: { ! 815: register unsigned long newseq, lastseq; ! 816: ! 817: /* ! 818: * KeymapNotify has no sequence number, but is always guaranteed ! 819: * to immediately follow another event, except when generated via ! 820: * SendEvent (hmmm). ! 821: */ ! 822: if ((rep->type & 0x7f) == KeymapNotify) ! 823: return(dpy->last_request_read); ! 824: ! 825: newseq = (dpy->last_request_read & ~((unsigned long)0xffff)) | ! 826: rep->sequenceNumber; ! 827: lastseq = dpy->last_request_read; ! 828: while (newseq < lastseq) { ! 829: newseq += 0x10000; ! 830: if (newseq > dpy->request) { ! 831: (void) fprintf (stderr, ! 832: "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n", ! 833: newseq, dpy->request, ! 834: (unsigned int) rep->type); ! 835: newseq -= 0x10000; ! 836: break; ! 837: } ! 838: } ! 839: ! 840: dpy->last_request_read = newseq; ! 841: return(newseq); ! 842: } ! 843: ! 844: /* ! 845: * _XReply - Wait for a reply packet and copy its contents into the ! 846: * specified rep. Mean while we must handle error and event packets that ! 847: * we may encounter. ! 848: */ ! 849: Status _XReply (dpy, rep, extra, discard) ! 850: register Display *dpy; ! 851: register xReply *rep; ! 852: int extra; /* number of 32-bit words expected after the reply */ ! 853: Bool discard; /* should I discard data followind "extra" words? */ ! 854: { ! 855: /* Pull out the serial number now, so that (currently illegal) requests ! 856: * generated by an error handler don't confuse us. ! 857: */ ! 858: unsigned long cur_request = dpy->request; ! 859: ! 860: _XFlush(dpy); ! 861: while (1) { ! 862: _XRead(dpy, (char *)rep, (long)SIZEOF(xReply)); ! 863: switch ((int)rep->generic.type) { ! 864: ! 865: case X_Reply: ! 866: /* Reply received. Fast update for synchronous replies, ! 867: * but deal with multiple outstanding replies. ! 868: */ ! 869: if (rep->generic.sequenceNumber == (cur_request & 0xffff)) ! 870: dpy->last_request_read = cur_request; ! 871: else ! 872: (void) _SetLastRequestRead(dpy, &rep->generic); ! 873: if (extra == 0) { ! 874: if (discard && (rep->generic.length > 0)) ! 875: /* unexpectedly long reply! */ ! 876: _EatData (dpy, rep->generic.length); ! 877: return (1); ! 878: } ! 879: if (extra == rep->generic.length) { ! 880: /* ! 881: * Read the extra data into storage immediately following ! 882: * the GenericReply structure. ! 883: */ ! 884: _XRead (dpy, NEXTPTR(rep,xReply), ((long)extra) << 2); ! 885: return (1); ! 886: } ! 887: if (extra < rep->generic.length) { ! 888: /* Actual reply is longer than "extra" */ ! 889: _XRead (dpy, NEXTPTR(rep,xReply), ((long)extra) << 2); ! 890: if (discard) ! 891: _EatData (dpy, rep->generic.length - extra); ! 892: return (1); ! 893: } ! 894: /* ! 895: *if we get here, then extra > rep->generic.length--meaning we ! 896: * read a reply that's shorter than we expected. This is an ! 897: * error, but we still need to figure out how to handle it... ! 898: */ ! 899: _XRead (dpy, NEXTPTR(rep,xReply), ! 900: ((long) rep->generic.length) << 2); ! 901: (*_XIOErrorFunction) (dpy); ! 902: return (0); ! 903: ! 904: case X_Error: ! 905: { ! 906: register _XExtension *ext; ! 907: register Bool ret = False; ! 908: int ret_code; ! 909: xError *err = (xError *) rep; ! 910: unsigned long serial; ! 911: ! 912: serial = _SetLastRequestRead(dpy, (xGenericReply *)rep); ! 913: if (serial == cur_request) ! 914: /* do not die on "no such font", "can't allocate", ! 915: "can't grab" failures */ ! 916: switch ((int)err->errorCode) { ! 917: case BadName: ! 918: switch (err->majorCode) { ! 919: case X_OpenFont: ! 920: case X_LookupColor: ! 921: case X_AllocNamedColor: ! 922: return(0); ! 923: } ! 924: break; ! 925: case BadFont: ! 926: if (err->majorCode == X_QueryFont) ! 927: return (0); ! 928: break; ! 929: case BadAlloc: ! 930: case BadAccess: ! 931: return (0); ! 932: /* ! 933: * we better see if there is an extension who may ! 934: * want to suppress the error. ! 935: */ ! 936: default: ! 937: ext = dpy->ext_procs; ! 938: while (ext) { ! 939: if (ext->error != NULL) ! 940: ret = (*ext->error) ! 941: (dpy, err, &ext->codes, &ret_code); ! 942: ext = ext->next; ! 943: } ! 944: if (ret) return (ret_code); ! 945: break; ! 946: } ! 947: _XError(dpy, err); ! 948: if (serial == cur_request) ! 949: return(0); ! 950: } ! 951: break; ! 952: default: ! 953: _XEnq(dpy, (xEvent *) rep); ! 954: break; ! 955: } ! 956: } ! 957: } ! 958: ! 959: ! 960: /* Read and discard "n" 32-bit words. */ ! 961: ! 962: static _EatData (dpy, n) ! 963: Display *dpy; ! 964: unsigned long n; ! 965: { ! 966: unsigned int bufsize; ! 967: char *buf; ! 968: n <<= 2; /* convert to number of bytes */ ! 969: buf = Xmalloc (bufsize = (n > 2048) ? 2048 : n); ! 970: while (n) { ! 971: long bytes_read = (n > bufsize) ? bufsize : n; ! 972: _XRead (dpy, buf, bytes_read); ! 973: n -= bytes_read; ! 974: } ! 975: Xfree (buf); ! 976: } ! 977: ! 978: /* ! 979: * _XEnq - Place event packets on the display's queue. ! 980: * note that no squishing of move events in V11, since there ! 981: * is pointer motion hints.... ! 982: */ ! 983: _XEnq (dpy, event) ! 984: register Display *dpy; ! 985: register xEvent *event; ! 986: { ! 987: register _XQEvent *qelt; ! 988: ! 989: /*NOSTRICT*/ ! 990: if (qelt = _qfree) { ! 991: /* If _qfree is non-NULL do this, else malloc a new one. */ ! 992: _qfree = qelt->next; ! 993: } ! 994: else if ((qelt = ! 995: (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) { ! 996: /* Malloc call failed! */ ! 997: errno = ENOMEM; ! 998: (*_XIOErrorFunction)(dpy); ! 999: } ! 1000: qelt->next = NULL; ! 1001: /* go call through display to find proper event reformatter */ ! 1002: if ((*dpy->event_vec[event->u.u.type & 0177])(dpy, &qelt->event, event)) { ! 1003: if (dpy->tail) dpy->tail->next = qelt; ! 1004: else dpy->head = qelt; ! 1005: ! 1006: dpy->tail = qelt; ! 1007: dpy->qlen++; ! 1008: } else { ! 1009: /* ignored, or stashed away for many-to-one compression */ ! 1010: qelt->next = _qfree; ! 1011: _qfree = qelt; ! 1012: } ! 1013: } ! 1014: /* ! 1015: * EventToWire in seperate file in that often not needed. ! 1016: */ ! 1017: ! 1018: /*ARGSUSED*/ ! 1019: Bool ! 1020: _XUnknownWireEvent(dpy, re, event) ! 1021: register Display *dpy; /* pointer to display structure */ ! 1022: register XEvent *re; /* pointer to where event should be reformatted */ ! 1023: register xEvent *event; /* wire protocol event */ ! 1024: { ! 1025: #ifdef notdef ! 1026: (void) fprintf(stderr, ! 1027: "Xlib: unhandled wire event! event number = %d, display = %x\n.", ! 1028: event->u.u.type, dpy); ! 1029: #endif ! 1030: return(False); ! 1031: } ! 1032: ! 1033: /*ARGSUSED*/ ! 1034: Status ! 1035: _XUnknownNativeEvent(dpy, re, event) ! 1036: register Display *dpy; /* pointer to display structure */ ! 1037: register XEvent *re; /* pointer to where event should be reformatted */ ! 1038: register xEvent *event; /* wire protocol event */ ! 1039: { ! 1040: #ifdef notdef ! 1041: (void) fprintf(stderr, ! 1042: "Xlib: unhandled native event! event number = %d, display = %x\n.", ! 1043: re->type, dpy); ! 1044: #endif ! 1045: return(0); ! 1046: } ! 1047: /* ! 1048: * reformat a wire event into an XEvent structure of the right type. ! 1049: */ ! 1050: Bool ! 1051: _XWireToEvent(dpy, re, event) ! 1052: register Display *dpy; /* pointer to display structure */ ! 1053: register XEvent *re; /* pointer to where event should be reformatted */ ! 1054: register xEvent *event; /* wire protocol event */ ! 1055: { ! 1056: ! 1057: re->type = event->u.u.type & 0x7f; ! 1058: ((XAnyEvent *)re)->serial = _SetLastRequestRead(dpy, ! 1059: (xGenericReply *)event); ! 1060: ((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0); ! 1061: ((XAnyEvent *)re)->display = dpy; ! 1062: ! 1063: /* Ignore the leading bit of the event type since it is set when a ! 1064: client sends an event rather than the server. */ ! 1065: ! 1066: switch (event-> u.u.type & 0177) { ! 1067: case KeyPress: ! 1068: case KeyRelease: ! 1069: { ! 1070: register XKeyEvent *ev = (XKeyEvent*) re; ! 1071: ev->root = event->u.keyButtonPointer.root; ! 1072: ev->window = event->u.keyButtonPointer.event; ! 1073: ev->subwindow = event->u.keyButtonPointer.child; ! 1074: ev->time = event->u.keyButtonPointer.time; ! 1075: ev->x = event->u.keyButtonPointer.eventX; ! 1076: ev->y = event->u.keyButtonPointer.eventY; ! 1077: ev->x_root = event->u.keyButtonPointer.rootX; ! 1078: ev->y_root = event->u.keyButtonPointer.rootY; ! 1079: ev->state = event->u.keyButtonPointer.state; ! 1080: ev->same_screen = event->u.keyButtonPointer.sameScreen; ! 1081: ev->keycode = event->u.u.detail; ! 1082: } ! 1083: break; ! 1084: case ButtonPress: ! 1085: case ButtonRelease: ! 1086: { ! 1087: register XButtonEvent *ev = (XButtonEvent *) re; ! 1088: ev->root = event->u.keyButtonPointer.root; ! 1089: ev->window = event->u.keyButtonPointer.event; ! 1090: ev->subwindow = event->u.keyButtonPointer.child; ! 1091: ev->time = event->u.keyButtonPointer.time; ! 1092: ev->x = event->u.keyButtonPointer.eventX; ! 1093: ev->y = event->u.keyButtonPointer.eventY; ! 1094: ev->x_root = event->u.keyButtonPointer.rootX; ! 1095: ev->y_root = event->u.keyButtonPointer.rootY; ! 1096: ev->state = event->u.keyButtonPointer.state; ! 1097: ev->same_screen = event->u.keyButtonPointer.sameScreen; ! 1098: ev->button = event->u.u.detail; ! 1099: } ! 1100: break; ! 1101: case MotionNotify: ! 1102: { ! 1103: register XMotionEvent *ev = (XMotionEvent *)re; ! 1104: ev->root = event->u.keyButtonPointer.root; ! 1105: ev->window = event->u.keyButtonPointer.event; ! 1106: ev->subwindow = event->u.keyButtonPointer.child; ! 1107: ev->time = event->u.keyButtonPointer.time; ! 1108: ev->x = event->u.keyButtonPointer.eventX; ! 1109: ev->y = event->u.keyButtonPointer.eventY; ! 1110: ev->x_root = event->u.keyButtonPointer.rootX; ! 1111: ev->y_root = event->u.keyButtonPointer.rootY; ! 1112: ev->state = event->u.keyButtonPointer.state; ! 1113: ev->same_screen = event->u.keyButtonPointer.sameScreen; ! 1114: ev->is_hint = event->u.u.detail; ! 1115: } ! 1116: break; ! 1117: case EnterNotify: ! 1118: case LeaveNotify: ! 1119: { ! 1120: register XCrossingEvent *ev = (XCrossingEvent *) re; ! 1121: ev->root = event->u.enterLeave.root; ! 1122: ev->window = event->u.enterLeave.event; ! 1123: ev->subwindow = event->u.enterLeave.child; ! 1124: ev->time = event->u.enterLeave.time; ! 1125: ev->x = event->u.enterLeave.eventX; ! 1126: ev->y = event->u.enterLeave.eventY; ! 1127: ev->x_root = event->u.enterLeave.rootX; ! 1128: ev->y_root = event->u.enterLeave.rootY; ! 1129: ev->state = event->u.enterLeave.state; ! 1130: ev->mode = event->u.enterLeave.mode; ! 1131: ev->same_screen = (event->u.enterLeave.flags & ! 1132: ELFlagSameScreen) && True; ! 1133: ev->focus = (event->u.enterLeave.flags & ! 1134: ELFlagFocus) && True; ! 1135: ev->detail = event->u.u.detail; ! 1136: } ! 1137: break; ! 1138: case FocusIn: ! 1139: case FocusOut: ! 1140: { ! 1141: register XFocusChangeEvent *ev = (XFocusChangeEvent *) re; ! 1142: ev->window = event->u.focus.window; ! 1143: ev->mode = event->u.focus.mode; ! 1144: ev->detail = event->u.u.detail; ! 1145: } ! 1146: break; ! 1147: case KeymapNotify: ! 1148: { ! 1149: register XKeymapEvent *ev = (XKeymapEvent *) re; ! 1150: ev->window = dpy->current; ! 1151: bcopy ((char *)((xKeymapEvent *) event)->map, ! 1152: &ev->key_vector[1], ! 1153: sizeof (((xKeymapEvent *) event)->map)); ! 1154: } ! 1155: break; ! 1156: case Expose: ! 1157: { ! 1158: register XExposeEvent *ev = (XExposeEvent *) re; ! 1159: ev->window = event->u.expose.window; ! 1160: ev->x = event->u.expose.x; ! 1161: ev->y = event->u.expose.y; ! 1162: ev->width = event->u.expose.width; ! 1163: ev->height = event->u.expose.height; ! 1164: ev->count = event->u.expose.count; ! 1165: } ! 1166: break; ! 1167: case GraphicsExpose: ! 1168: { ! 1169: register XGraphicsExposeEvent *ev = ! 1170: (XGraphicsExposeEvent *) re; ! 1171: ev->drawable = event->u.graphicsExposure.drawable; ! 1172: ev->x = event->u.graphicsExposure.x; ! 1173: ev->y = event->u.graphicsExposure.y; ! 1174: ev->width = event->u.graphicsExposure.width; ! 1175: ev->height = event->u.graphicsExposure.height; ! 1176: ev->count = event->u.graphicsExposure.count; ! 1177: ev->major_code = event->u.graphicsExposure.majorEvent; ! 1178: ev->minor_code = event->u.graphicsExposure.minorEvent; ! 1179: } ! 1180: break; ! 1181: case NoExpose: ! 1182: { ! 1183: register XNoExposeEvent *ev = (XNoExposeEvent *) re; ! 1184: ev->drawable = event->u.noExposure.drawable; ! 1185: ev->major_code = event->u.noExposure.majorEvent; ! 1186: ev->minor_code = event->u.noExposure.minorEvent; ! 1187: } ! 1188: break; ! 1189: case VisibilityNotify: ! 1190: { ! 1191: register XVisibilityEvent *ev = (XVisibilityEvent *) re; ! 1192: ev->window = event->u.visibility.window; ! 1193: ev->state = event->u.visibility.state; ! 1194: } ! 1195: break; ! 1196: case CreateNotify: ! 1197: { ! 1198: register XCreateWindowEvent *ev = ! 1199: (XCreateWindowEvent *) re; ! 1200: ev->window = event->u.createNotify.window; ! 1201: ev->parent = event->u.createNotify.parent; ! 1202: ev->x = event->u.createNotify.x; ! 1203: ev->y = event->u.createNotify.y; ! 1204: ev->width = event->u.createNotify.width; ! 1205: ev->height = event->u.createNotify.height; ! 1206: ev->border_width = event->u.createNotify.borderWidth; ! 1207: ev->override_redirect = event->u.createNotify.override; ! 1208: } ! 1209: break; ! 1210: case DestroyNotify: ! 1211: { ! 1212: register XDestroyWindowEvent *ev = ! 1213: (XDestroyWindowEvent *) re; ! 1214: ev->window = event->u.destroyNotify.window; ! 1215: ev->event = event->u.destroyNotify.event; ! 1216: } ! 1217: break; ! 1218: case UnmapNotify: ! 1219: { ! 1220: register XUnmapEvent *ev = (XUnmapEvent *) re; ! 1221: ev->window = event->u.unmapNotify.window; ! 1222: ev->event = event->u.unmapNotify.event; ! 1223: ev->from_configure = event->u.unmapNotify.fromConfigure; ! 1224: } ! 1225: break; ! 1226: case MapNotify: ! 1227: { ! 1228: register XMapEvent *ev = (XMapEvent *) re; ! 1229: ev->window = event->u.mapNotify.window; ! 1230: ev->event = event->u.mapNotify.event; ! 1231: ev->override_redirect = event->u.mapNotify.override; ! 1232: } ! 1233: break; ! 1234: case MapRequest: ! 1235: { ! 1236: register XMapRequestEvent *ev = (XMapRequestEvent *) re; ! 1237: ev->window = event->u.mapRequest.window; ! 1238: ev->parent = event->u.mapRequest.parent; ! 1239: } ! 1240: break; ! 1241: case ReparentNotify: ! 1242: { ! 1243: register XReparentEvent *ev = (XReparentEvent *) re; ! 1244: ev->event = event->u.reparent.event; ! 1245: ev->window = event->u.reparent.window; ! 1246: ev->parent = event->u.reparent.parent; ! 1247: ev->x = event->u.reparent.x; ! 1248: ev->y = event->u.reparent.y; ! 1249: ev->override_redirect = event->u.reparent.override; ! 1250: } ! 1251: break; ! 1252: case ConfigureNotify: ! 1253: { ! 1254: register XConfigureEvent *ev = (XConfigureEvent *) re; ! 1255: ev->event = event->u.configureNotify.event; ! 1256: ev->window = event->u.configureNotify.window; ! 1257: ev->above = event->u.configureNotify.aboveSibling; ! 1258: ev->x = event->u.configureNotify.x; ! 1259: ev->y = event->u.configureNotify.y; ! 1260: ev->width = event->u.configureNotify.width; ! 1261: ev->height = event->u.configureNotify.height; ! 1262: ev->border_width = event->u.configureNotify.borderWidth; ! 1263: ev->override_redirect = event->u.configureNotify.override; ! 1264: } ! 1265: break; ! 1266: case ConfigureRequest: ! 1267: { ! 1268: register XConfigureRequestEvent *ev = ! 1269: (XConfigureRequestEvent *) re; ! 1270: ev->window = event->u.configureRequest.window; ! 1271: ev->parent = event->u.configureRequest.parent; ! 1272: ev->above = event->u.configureRequest.sibling; ! 1273: ev->x = event->u.configureRequest.x; ! 1274: ev->y = event->u.configureRequest.y; ! 1275: ev->width = event->u.configureRequest.width; ! 1276: ev->height = event->u.configureRequest.height; ! 1277: ev->border_width = event->u.configureRequest.borderWidth; ! 1278: ev->value_mask = event->u.configureRequest.valueMask; ! 1279: ev->detail = event->u.u.detail; ! 1280: } ! 1281: break; ! 1282: case GravityNotify: ! 1283: { ! 1284: register XGravityEvent *ev = (XGravityEvent *) re; ! 1285: ev->window = event->u.gravity.window; ! 1286: ev->event = event->u.gravity.event; ! 1287: ev->x = event->u.gravity.x; ! 1288: ev->y = event->u.gravity.y; ! 1289: } ! 1290: break; ! 1291: case ResizeRequest: ! 1292: { ! 1293: register XResizeRequestEvent *ev = ! 1294: (XResizeRequestEvent *) re; ! 1295: ev->window = event->u.resizeRequest.window; ! 1296: ev->width = event->u.resizeRequest.width; ! 1297: ev->height = event->u.resizeRequest.height; ! 1298: } ! 1299: break; ! 1300: case CirculateNotify: ! 1301: { ! 1302: register XCirculateEvent *ev = (XCirculateEvent *) re; ! 1303: ev->window = event->u.circulate.window; ! 1304: ev->event = event->u.circulate.event; ! 1305: ev->place = event->u.circulate.place; ! 1306: } ! 1307: break; ! 1308: case CirculateRequest: ! 1309: { ! 1310: register XCirculateRequestEvent *ev = ! 1311: (XCirculateRequestEvent *) re; ! 1312: ev->window = event->u.circulate.window; ! 1313: ev->parent = event->u.circulate.event; ! 1314: ev->place = event->u.circulate.place; ! 1315: } ! 1316: break; ! 1317: case PropertyNotify: ! 1318: { ! 1319: register XPropertyEvent *ev = (XPropertyEvent *) re; ! 1320: ev->window = event->u.property.window; ! 1321: ev->atom = event->u.property.atom; ! 1322: ev->time = event->u.property.time; ! 1323: ev->state = event->u.property.state; ! 1324: } ! 1325: break; ! 1326: case SelectionClear: ! 1327: { ! 1328: register XSelectionClearEvent *ev = ! 1329: (XSelectionClearEvent *) re; ! 1330: ev->window = event->u.selectionClear.window; ! 1331: ev->selection = event->u.selectionClear.atom; ! 1332: ev->time = event->u.selectionClear.time; ! 1333: } ! 1334: break; ! 1335: case SelectionRequest: ! 1336: { ! 1337: register XSelectionRequestEvent *ev = ! 1338: (XSelectionRequestEvent *) re; ! 1339: ev->owner = event->u.selectionRequest.owner; ! 1340: ev->requestor = event->u.selectionRequest.requestor; ! 1341: ev->selection = event->u.selectionRequest.selection; ! 1342: ev->target = event->u.selectionRequest.target; ! 1343: ev->property = event->u.selectionRequest.property; ! 1344: ev->time = event->u.selectionRequest.time; ! 1345: } ! 1346: break; ! 1347: case SelectionNotify: ! 1348: { ! 1349: register XSelectionEvent *ev = (XSelectionEvent *) re; ! 1350: ev->requestor = event->u.selectionNotify.requestor; ! 1351: ev->selection = event->u.selectionNotify.selection; ! 1352: ev->target = event->u.selectionNotify.target; ! 1353: ev->property = event->u.selectionNotify.property; ! 1354: ev->time = event->u.selectionNotify.time; ! 1355: } ! 1356: break; ! 1357: case ColormapNotify: ! 1358: { ! 1359: register XColormapEvent *ev = (XColormapEvent *) re; ! 1360: ev->window = event->u.colormap.window; ! 1361: ev->colormap = event->u.colormap.colormap; ! 1362: ev->new = event->u.colormap.new; ! 1363: ev->state = event->u.colormap.state; ! 1364: } ! 1365: break; ! 1366: case ClientMessage: ! 1367: { ! 1368: register int i; ! 1369: register XClientMessageEvent *ev ! 1370: = (XClientMessageEvent *) re; ! 1371: ev->window = event->u.clientMessage.window; ! 1372: ev->format = event->u.u.detail; ! 1373: switch (ev->format) { ! 1374: case 8: ! 1375: ev->message_type = event->u.clientMessage.u.b.type; ! 1376: for (i = 0; i < 20; i++) ! 1377: ev->data.b[i] = event->u.clientMessage.u.b.bytes[i]; ! 1378: break; ! 1379: case 16: ! 1380: ev->message_type = event->u.clientMessage.u.s.type; ! 1381: ev->data.s[0] = event->u.clientMessage.u.s.shorts0; ! 1382: ev->data.s[1] = event->u.clientMessage.u.s.shorts1; ! 1383: ev->data.s[2] = event->u.clientMessage.u.s.shorts2; ! 1384: ev->data.s[3] = event->u.clientMessage.u.s.shorts3; ! 1385: ev->data.s[4] = event->u.clientMessage.u.s.shorts4; ! 1386: ev->data.s[5] = event->u.clientMessage.u.s.shorts5; ! 1387: ev->data.s[6] = event->u.clientMessage.u.s.shorts6; ! 1388: ev->data.s[7] = event->u.clientMessage.u.s.shorts7; ! 1389: ev->data.s[8] = event->u.clientMessage.u.s.shorts8; ! 1390: ev->data.s[9] = event->u.clientMessage.u.s.shorts9; ! 1391: break; ! 1392: case 32: ! 1393: ev->message_type = event->u.clientMessage.u.l.type; ! 1394: ev->data.l[0] = event->u.clientMessage.u.l.longs0; ! 1395: ev->data.l[1] = event->u.clientMessage.u.l.longs1; ! 1396: ev->data.l[2] = event->u.clientMessage.u.l.longs2; ! 1397: ev->data.l[3] = event->u.clientMessage.u.l.longs3; ! 1398: ev->data.l[4] = event->u.clientMessage.u.l.longs4; ! 1399: break; ! 1400: default: /* XXX should never occur */ ! 1401: break; ! 1402: } ! 1403: } ! 1404: break; ! 1405: case MappingNotify: ! 1406: { ! 1407: register XMappingEvent *ev = (XMappingEvent *)re; ! 1408: ev->first_keycode = event->u.mappingNotify.firstKeyCode; ! 1409: ev->request = event->u.mappingNotify.request; ! 1410: ev->count = event->u.mappingNotify.count; ! 1411: } ! 1412: break; ! 1413: default: ! 1414: return(_XUnknownWireEvent(dpy, re, event)); ! 1415: } ! 1416: return(True); ! 1417: } ! 1418: ! 1419: ! 1420: static char *_SysErrorMsg (n) ! 1421: int n; ! 1422: { ! 1423: extern char *sys_errlist[]; ! 1424: extern int sys_nerr; ! 1425: char *s = ((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error"); ! 1426: ! 1427: return (s ? s : "no such error"); ! 1428: } ! 1429: ! 1430: /* ! 1431: * _XIOError - Default fatal system error reporting routine. Called when ! 1432: * an X internal system error is encountered. ! 1433: */ ! 1434: _XIOError (dpy) ! 1435: Display *dpy; ! 1436: { ! 1437: (void) fprintf (stderr, ! 1438: "XIO: fatal IO error %d (%s) on X server \"%s\"\r\n", ! 1439: errno, _SysErrorMsg (errno), DisplayString (dpy)); ! 1440: (void) fprintf (stderr, ! 1441: " after %lu requests (%lu known processed) with %d events remaining.\r\n", ! 1442: NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy), ! 1443: QLength(dpy)); ! 1444: ! 1445: if (errno == EPIPE) { ! 1446: (void) fprintf (stderr, ! 1447: " The connection was probably broken by a server shutdown or KillClient.\r\n"); ! 1448: } ! 1449: ! 1450: exit (1); ! 1451: } ! 1452: ! 1453: /* ! 1454: * _XError - Default non-fatal error reporting routine. Called when an ! 1455: * X_Error packet is encountered in the input stream. ! 1456: */ ! 1457: int _XError (dpy, rep) ! 1458: Display *dpy; ! 1459: xError *rep; ! 1460: { ! 1461: XErrorEvent event; ! 1462: /* ! 1463: * X_Error packet encountered! We need to unpack the error before ! 1464: * giving it to the user. ! 1465: */ ! 1466: ! 1467: event.display = dpy; ! 1468: event.type = X_Error; ! 1469: event.serial = _SetLastRequestRead(dpy, (xGenericReply *)rep); ! 1470: event.resourceid = rep->resourceID; ! 1471: event.error_code = rep->errorCode; ! 1472: event.request_code = rep->majorCode; ! 1473: event.minor_code = rep->minorCode; ! 1474: if (_XErrorFunction != NULL) { ! 1475: return ((*_XErrorFunction)(dpy, &event)); ! 1476: } ! 1477: exit(1); ! 1478: /*NOTREACHED*/ ! 1479: } ! 1480: ! 1481: int _XPrintDefaultError (dpy, event, fp) ! 1482: Display *dpy; ! 1483: XErrorEvent *event; ! 1484: FILE *fp; ! 1485: { ! 1486: char buffer[BUFSIZ]; ! 1487: char mesg[BUFSIZ]; ! 1488: char number[32]; ! 1489: char *mtype = "XlibMessage"; ! 1490: XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); ! 1491: XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); ! 1492: (void) fprintf(fp, "%s: %s\n ", mesg, buffer); ! 1493: XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", ! 1494: mesg, BUFSIZ); ! 1495: (void) fprintf(fp, mesg, event->request_code); ! 1496: sprintf(number, "%d", event->request_code); ! 1497: XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); ! 1498: (void) fprintf(fp, " (%s)", buffer); ! 1499: fputs("\n ", fp); ! 1500: XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code", ! 1501: mesg, BUFSIZ); ! 1502: (void) fprintf(fp, mesg, event->minor_code); ! 1503: fputs("\n ", fp); ! 1504: XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", ! 1505: mesg, BUFSIZ); ! 1506: (void) fprintf(fp, mesg, event->resourceid); ! 1507: fputs("\n ", fp); ! 1508: XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", ! 1509: mesg, BUFSIZ); ! 1510: (void) fprintf(fp, mesg, event->serial); ! 1511: fputs("\n ", fp); ! 1512: XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", ! 1513: mesg, BUFSIZ); ! 1514: (void) fprintf(fp, mesg, dpy->request); ! 1515: fputs("\n", fp); ! 1516: if (event->error_code == BadImplementation) return 0; ! 1517: return 1; ! 1518: } ! 1519: ! 1520: int _XDefaultError(dpy, event) ! 1521: Display *dpy; ! 1522: XErrorEvent *event; ! 1523: { ! 1524: if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0; ! 1525: exit(1); ! 1526: /*NOTREACHED*/ ! 1527: } ! 1528: ! 1529: int (*_XIOErrorFunction)() = _XIOError; ! 1530: int (*_XErrorFunction)() = _XDefaultError; ! 1531: ! 1532: /* ! 1533: * This routine can be used to (cheaply) get some memory within a single ! 1534: * Xlib routine for scratch space. It is reallocated from the same place ! 1535: * each time, unless the library needs a large scratch space. ! 1536: */ ! 1537: char *_XAllocScratch (dpy, nbytes) ! 1538: register Display *dpy; ! 1539: unsigned long nbytes; ! 1540: { ! 1541: if (nbytes > dpy->scratch_length) { ! 1542: if (dpy->scratch_buffer != NULL) Xfree (dpy->scratch_buffer); ! 1543: return( dpy->scratch_length = nbytes, ! 1544: dpy->scratch_buffer = Xmalloc ((unsigned)nbytes) ); ! 1545: } ! 1546: return (dpy->scratch_buffer); ! 1547: } ! 1548: ! 1549: /* ! 1550: * Given a visual id, find the visual structure for this id on this display. ! 1551: */ ! 1552: Visual *_XVIDtoVisual (dpy, id) ! 1553: Display *dpy; ! 1554: VisualID id; ! 1555: { ! 1556: register int i, j, k; ! 1557: register Screen *sp; ! 1558: register Depth *dp; ! 1559: register Visual *vp; ! 1560: for (i = 0; i < dpy->nscreens; i++) { ! 1561: sp = &dpy->screens[i]; ! 1562: for (j = 0; j < sp->ndepths; j++) { ! 1563: dp = &sp->depths[j]; ! 1564: for (k = 0; k < dp->nvisuals; k++) { ! 1565: vp = &dp->visuals[k]; ! 1566: if (vp->visualid == id) return (vp); ! 1567: } ! 1568: } ! 1569: } ! 1570: return (NULL); ! 1571: } ! 1572: ! 1573: XFree (data) ! 1574: char *data; ! 1575: { ! 1576: Xfree (data); ! 1577: } ! 1578: ! 1579: #ifdef DataRoutineIsProcedure ! 1580: void Data (dpy, data, len) ! 1581: Display *dpy; ! 1582: char *data; ! 1583: long len; ! 1584: { ! 1585: if (dpy->bufptr + (len) <= dpy->bufmax) { ! 1586: bcopy(data, dpy->bufptr, (int)len); ! 1587: dpy->bufptr += ((len) + 3) & ~3; ! 1588: } else { ! 1589: _XSend(dpy, data, len); ! 1590: } ! 1591: } ! 1592: #endif /* DataRoutineIsProcedure */ ! 1593: ! 1594: ! 1595: #ifdef WORD64 ! 1596: ! 1597: /* ! 1598: * XXX This is a *really* stupid way of doing this. It should just use ! 1599: * dpy->bufptr directly, taking into account where in the word it is. ! 1600: */ ! 1601: ! 1602: /* ! 1603: * Data16 - Place 16 bit data in the buffer. ! 1604: * ! 1605: * "dpy" is a pointer to a Display. ! 1606: * "data" is a pointer to the data. ! 1607: * "len" is the length in bytes of the data. ! 1608: */ ! 1609: ! 1610: static doData16(dpy, data, len, packbuffer) ! 1611: register Display *dpy; ! 1612: short *data; ! 1613: unsigned len; ! 1614: char *packbuffer; ! 1615: { ! 1616: long *lp,*lpack; ! 1617: long i, nwords,bits; ! 1618: long mask16 = 0x000000000000ffff; ! 1619: ! 1620: lp = (long *)data; ! 1621: lpack = (long *)packbuffer; ! 1622: *lpack = 0; ! 1623: ! 1624: /* nwords is the number of 16 bit values to be packed, ! 1625: * the low order 16 bits of each word will be packed ! 1626: * into 64 bit words ! 1627: */ ! 1628: nwords = len >> 1; ! 1629: bits = 48; ! 1630: ! 1631: for(i=0;i<nwords;i++){ ! 1632: *lpack ^= (*lp & mask16) << bits; ! 1633: bits -= 16 ; ! 1634: lp++; ! 1635: if(bits < 0){ ! 1636: lpack++; ! 1637: *lpack = 0; ! 1638: bits = 48; ! 1639: } ! 1640: } ! 1641: Data(dpy, packbuffer, len); ! 1642: } ! 1643: ! 1644: Data16 (dpy, data, len) ! 1645: Display *dpy; ! 1646: short *data; ! 1647: unsigned len; ! 1648: { ! 1649: char packbuffer[PACKBUFFERSIZE]; ! 1650: unsigned nwords = (PACKBUFFERSIZE >> 1); /* bytes to CARD16 */ ! 1651: ! 1652: for (; len > nwords; len -= nwords, data += nwords) { ! 1653: doData16 (dpy, data, nwords, packbuffer); ! 1654: } ! 1655: doData16 (dpy, data, len, packbuffer); ! 1656: } ! 1657: ! 1658: /* ! 1659: * Data32 - Place 32 bit data in the buffer. ! 1660: * ! 1661: * "dpy" is a pointer to a Display. ! 1662: * "data" is a pointer to the data. ! 1663: * "len" is the length in bytes of the data. ! 1664: */ ! 1665: ! 1666: static doData32 (dpy, data, len, packbuffer) ! 1667: register Display *dpy; ! 1668: long *data; ! 1669: unsigned len; ! 1670: char *packbuffer; ! 1671: { ! 1672: long *lp,*lpack; ! 1673: long i,bits,nwords; ! 1674: long mask32 = 0x00000000ffffffff; ! 1675: ! 1676: lpack = (long *) packbuffer; ! 1677: lp = data; ! 1678: ! 1679: *lpack = 0; ! 1680: ! 1681: /* nwords is the number of 32 bit values to be packed ! 1682: * the low order 32 bits of each word will be packed ! 1683: * into 64 bit words ! 1684: */ ! 1685: nwords = len >> 2; ! 1686: bits = 32; ! 1687: ! 1688: for(i=0;i<nwords;i++){ ! 1689: *lpack ^= (*lp & mask32) << bits; ! 1690: bits = bits ^32; ! 1691: lp++; ! 1692: if(bits){ ! 1693: lpack++; ! 1694: *lpack = 0; ! 1695: } ! 1696: } ! 1697: Data(dpy, packbuffer, len); ! 1698: } ! 1699: ! 1700: Data32 (dpy, data, len) ! 1701: Display *dpy; ! 1702: short *data; ! 1703: unsigned len; ! 1704: { ! 1705: char packbuffer[PACKBUFFERSIZE]; ! 1706: unsigned nwords = (PACKBUFFERSIZE >> 2); /* bytes to CARD32 */ ! 1707: ! 1708: for (; len > nwords; len -= nwords, data += nwords) { ! 1709: doData32 (dpy, data, nwords, packbuffer); ! 1710: } ! 1711: doData32 (dpy, data, len, packbuffer); ! 1712: } ! 1713: ! 1714: #endif /* WORD64 */ ! 1715: ! 1716: ! 1717: ! 1718: /* ! 1719: * _XFreeQ - free the queue of events, called by XCloseDisplay when there are ! 1720: * no more displays left on the display list ! 1721: */ ! 1722: ! 1723: void _XFreeQ () ! 1724: { ! 1725: register _XQEvent *qelt = _qfree; ! 1726: ! 1727: while (qelt) { ! 1728: register _XQEvent *qnext = qelt->next; ! 1729: Xfree (qelt); ! 1730: qelt = qnext; ! 1731: } ! 1732: _qfree = NULL; ! 1733: return; ! 1734: } ! 1735: ! 1736:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.