|
|
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.