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