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