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;

Defined functions

_XError defined in line 329; used 1 times
_XIOError defined in line 317; never used
_XReply defined in line 212; used 53 times
_XSend defined in line 163; used 1 times

Defined variables

_XlibCurrentDisplay defined in line 35; never used
_qfree defined in line 36; used 2 times
padlength defined in line 38; used 2 times
rcsid defined in line 32; never used
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1618
Valid CSS Valid XHTML 1.0 Strict