1: #include <X/mit-copyright.h>
   2: 
   3: /* Copyright    Massachusetts Institute of Technology    1985	*/
   4: 
   5: /*	Routines to manage various kinds of resources:
   6:  *
   7:  *	Add_resource, Free_resource, Free_client_resources,
   8:  *	Bit_size, Pix_size,
   9:  *	Get_font, Store_cursor,
  10:  *	Define_self, Reset_hosts, Add_host, Remove_host, Invalid_host,
  11:  *	Store_cut, Fetch_cut, Rotate_cuts, Reset_cuts,
  12:  *	Init_colormap,
  13:  *	Get_color, Get_cells, Free_colors, Store_colors, Query_color,
  14:  *	Alloc_rectangle, Free_rectangles, Free_rectangle_storage,
  15:  *	Xalloc, Xrealloc
  16:  */
  17: #ifndef lint
  18: static char *rcsid_resource_c = "$Header: resource.c,v 10.11 86/02/01 15:17:05 tony Rel $";
  19: #endif
  20: 
  21: #include "Xint.h"
  22: #include <errno.h>
  23: #include <sys/socket.h>
  24: #include <sys/ioctl.h>
  25: #include <net/if.h>
  26: #include <netinet/in.h>
  27: #include <netdb.h>
  28: #ifdef DNETCONN
  29: #include <netdnet/dn.h>
  30: #include <netdnet/dnetdb.h>
  31: #endif
  32: 
  33: extern int errno;
  34: extern u_char Xstatus;
  35: extern DEVICE device;
  36: 
  37: char *Xalloc(), *Xrealloc(), *malloc(), *realloc();
  38: char *index(), *strcpy(), *strcat();
  39: FONT *GetFont();
  40: CURSOR *StoreCursor();
  41: 
  42: #define resalloc 50
  43: 
  44: /* Each resource is indexed (by the low bits of the resource id) through
  45:  * Resources, and chained through ClientResources.
  46:  */
  47: RESOURCE **Resources = NULL;
  48: static RESOURCE *ClientResources[maxsocks];
  49: 
  50: int MaxResource = 0;
  51: static RESOURCE *FreeResource = NULL;
  52: 
  53: #define ridinc (1 << 16)
  54: #define ridmask ((1 << 29) - 1)
  55: static long ridseed = 0;
  56: 
  57: typedef struct _host {
  58:     short family;
  59:     short len;
  60:     char addr[4];       /* will need to be bigger eventually */
  61:     struct _host *next;
  62: } HOST;
  63: 
  64: static HOST *selfhosts = NULL;
  65: static HOST *validhosts = NULL;
  66: 
  67: typedef struct _cmentry {
  68:     short refcnt;       /* reference count (-1 means writable) */
  69:     ushort red;     /* color value */
  70:     ushort green;
  71:     ushort blue;
  72: } CMENTRY;
  73: 
  74: static CMENTRY *colormap;   /* the color map */
  75: static int free_entries;    /* number of unallocated entries */
  76: 
  77: static int numpixels[maxsocks];     /* number of pixel held by each client */
  78: static ushort *clientpixels[maxsocks];  /* lists of pixels held by each client */
  79: 
  80: #define NUMCUTS 8
  81: static char *cutbuf[NUMCUTS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  82: static int cutbuflen[NUMCUTS] = {0, 0, 0, 0, 0, 0, 0, 0};
  83: static unsigned base_cut = 0;           /* Base cut buffer */
  84: 
  85: RECTANGLE *free_rectangles = NULL;
  86: 
  87: /* Define a client visible resource */
  88: 
  89: long Add_resource (type, client, value)
  90:     int type, client;
  91:     caddr_t value;
  92: {
  93:     register RESOURCE *rptr, **res;
  94:     register int ridx;
  95: 
  96:     if ((rptr = FreeResource) == NULL) {
  97:         /* no room, expand the resource table */
  98:         rptr = (RESOURCE *) Xalloc (resalloc * sizeof (RESOURCE));
  99:         if (ridx = MaxResource) {
 100:         res = (RESOURCE **) Xrealloc ((caddr_t) Resources,
 101:                           (ridx + resalloc) << 2);
 102:         } else {
 103:         res = (RESOURCE **) Xalloc (resalloc << 2);
 104:         ridx++;
 105:         rptr++;
 106:         }
 107:         Resources = res;
 108:         res += ridx;
 109:         MaxResource += resalloc;
 110:         /* initialize the spares */
 111:         while (ridx < MaxResource) {
 112:         *res++ = rptr;
 113:         rptr->type = RT_FREE;
 114:         rptr->id = ridx;
 115:         rptr->next = FreeResource;
 116:         FreeResource = rptr;
 117:         ridx++;
 118:         rptr++;
 119:         }
 120:         rptr = FreeResource;
 121:     }
 122:     FreeResource = rptr->next;
 123:     rptr->type = type;
 124:     rptr->value = value;
 125:     res = &ClientResources[client];
 126:     rptr->prev = (RESOURCE *) res;
 127:     if (rptr->next = *res)
 128:         (*res)->prev = rptr;
 129:     *res = rptr;
 130:     ridseed += ridinc;
 131:     ridseed &= ridmask;
 132:     return (rptr->id = ridseed + RESIDX(rptr->id));
 133: }
 134: 
 135: /* Free a client visible resource */
 136: 
 137: Free_resource (rptr)
 138:     register RESOURCE *rptr;
 139: {
 140:     switch (rptr->type) {
 141:         case RT_WINDOW:
 142:         Destroy_window ((WINDOW *) rptr->value);
 143:         break;
 144:         case RT_FONT:
 145:         if (--((FONT *) rptr->value)->refcnt == 0)
 146:             FreeFont ((FONT *) rptr->value);
 147:         break;
 148:         case RT_BITMAP:
 149:         if (--((BITMAP *) rptr->value)->refcnt == 0)
 150:             FreeBitmap ((BITMAP *) rptr->value);
 151:         break;
 152:         case RT_PIXMAP:
 153:         if (--((PIXMAP *) rptr->value)->refcnt == 0)
 154:             FreePixmap ((PIXMAP *) rptr->value);
 155:         break;
 156:         case RT_CURSOR:
 157:         if (--((CURSOR *) rptr->value)->refcnt == 0)
 158:             FreeCursor ((CURSOR *) rptr->value);
 159:         break;
 160:     }
 161:     /* unchain from client and put on free list */
 162:     rptr->type = RT_FREE;
 163:     if ((rptr->prev)->next = rptr->next)
 164:         (rptr->next)->prev = rptr->prev;
 165:     rptr->next = FreeResource;
 166:     FreeResource = rptr;
 167: }
 168: 
 169: /* Free all resources owned by a client */
 170: 
 171: Free_client_resources (client)
 172:     register int client;
 173: {
 174:     register RESOURCE *rptr, **res;
 175:     register int rval;
 176:     register WINDOW *w;
 177: 
 178:     Ungrab_client (client);
 179:     Free_client_colors (client);
 180:     /* this is slightly expensive in time, but cheap in space */
 181:     res = Resources+1;
 182:     rval = MaxResource;
 183:     while (--rval > 0) {
 184:         rptr = *res++;
 185:         if (rptr->type != RT_WINDOW)
 186:         continue;
 187:         w = (WINDOW *) rptr->value;
 188:         if (w->client == client) {
 189:         w->mask = NoEvent;
 190:         w->client = 0;
 191:         }
 192:     }
 193:     res = &ClientResources[client];
 194:     if ((rptr = *res) == NULL) return;
 195:     while (rptr->next)
 196:         rptr = rptr->next;
 197:     /* freeing in creation order avoids destroying subwindows one by one */
 198:     for (; rptr != (RESOURCE *) res; rptr = rptr->prev) {
 199:         if (rptr->type != RT_FREE)
 200:         Free_resource (rptr);
 201:     }
 202: }
 203: 
 204: /* Determine the number of bytes in a bitmap (including padding) */
 205: 
 206: Bit_size (height, width)
 207:     register int height, width;
 208: {
 209:     if (height > 0 && width > 0)
 210:         return (WordPad(BitmapSize(width, height)));
 211:     Xstatus = BadValue;
 212:     return (0);
 213: }
 214: 
 215: /* Determine the number of bytes in a pixmap (including padding) */
 216: 
 217: Pix_size (format, height, width)
 218:     register int format, height, width;
 219: {
 220:     if (height > 0 && width > 0) {
 221:         if (format == XYFormat)
 222:         return (WordPad(XYPixmapSize(width, height, device.planes)));
 223:         else if (format == ZFormat) {
 224:         if (device.planes > 8)
 225:             return (WordPad(WZPixmapSize(width, height)));
 226:         else if (device.planes > 1)
 227:             return (BytePad(BZPixmapSize(width, height)));
 228:         }
 229:     }
 230:     Xstatus = BadValue;
 231:     return (0);
 232: }
 233: 
 234: /* Create a font */
 235: 
 236: FONT *Get_font (name)
 237:     char *name;
 238: {
 239:     register RESOURCE *rptr, **res;
 240:     register int rval;
 241:     register FONT *f;
 242: 
 243:     /* First see if the font already exists somewhere */
 244:     /* Could have a separate font list, but probably not worth it */
 245:     res = Resources+1;
 246:     rval = MaxResource;
 247:     while (--rval > 0) {
 248:         rptr = *res++;
 249:         if (rptr->type == RT_FONT) {
 250:         f = (FONT *) rptr->value;
 251:         if (strcmp (f->name, name) == 0) {
 252:             f->refcnt++;
 253:             return (f);
 254:         }
 255:         }
 256:     }
 257:     /* Try to create it */
 258:     if ((f = GetFont (name)) == NULL)
 259:         Xstatus = BadFont;
 260:     return (f);
 261: }
 262: 
 263: /* Create a cursor */
 264: 
 265: CURSOR *Store_cursor (image, mask, fore, back, xoff, yoff, func)
 266:     register BITMAP *image, *mask;
 267:     int back, fore, xoff, yoff;
 268:     unsigned func;
 269: {
 270:     register CURSOR *c = NULL;
 271: 
 272:     if (func >= 16 || xoff < 0 || yoff < 0 ||
 273:         xoff >= image->width || yoff >= image->height ||
 274:         fore < 0 || (fore > WhitePixel && fore >= device.entries) ||
 275:         back < 0 || (back > WhitePixel && back >= device.entries))
 276:         Xstatus = BadValue;
 277:     else if (mask && (mask->width != image->width ||
 278:               mask->height != image->height))
 279:         Xstatus = BadMatch;
 280:     else if ((c = StoreCursor ((int) func, image, fore, back,
 281:                    mask, xoff, yoff)) == NULL)
 282:         Xstatus = BadAlloc;
 283:     return (c);
 284: }
 285: 
 286: /* Define this host for access control */
 287: 
 288: Define_self (fd)
 289:     int fd;
 290: {
 291:     char buf[2048];
 292:     struct ifconf ifc;
 293:     register struct ifreq *ifr;
 294:     register int n;
 295:     int len;
 296:     caddr_t addr;
 297:     short family;
 298:     register HOST *host;
 299: 
 300:     ifc.ifc_len = sizeof (buf);
 301:     ifc.ifc_buf = buf;
 302:     if (ioctl (fd, (int) SIOCGIFCONF, (caddr_t) &ifc) < 0)
 303:         Error ("Getting interface configuration");
 304:     for (ifr = ifc.ifc_req, n = ifc.ifc_len / sizeof (struct ifreq);
 305:          --n >= 0;
 306:          ifr++) {
 307:         if ((family = Convert_addr (&ifr->ifr_addr, &len, &addr)) <= 0)
 308:         continue;
 309:         for (host = selfhosts;
 310:          host && (family != host->family ||
 311:               bcmp (addr, host->addr, len));
 312:          host = host->next) ;
 313:         if (host) continue;
 314:         host = (HOST *) Xalloc (sizeof (HOST));
 315:         host->family = family;
 316:         host->len = len;
 317:         bcopy(addr, host->addr, len);
 318:         host->next = selfhosts;
 319:         selfhosts = host;
 320:     }
 321: }
 322: 
 323: /* Reset access control list to initial hosts */
 324: 
 325: Reset_hosts (display)
 326:     char *display;
 327: {
 328:     register HOST *host, *self;
 329:     char hostname[120];
 330:     char fname[32];
 331:     FILE *fd;
 332:     char *ptr;
 333:     register struct hostent *hp;
 334:     union {
 335:         struct sockaddr sa;
 336:         struct sockaddr_in in;
 337: #ifdef DNETCONN
 338:         struct sockaddr_dn dn;
 339: #endif
 340:     } saddr;
 341: #ifdef DNETCONN
 342:     struct nodeent *np;
 343:     struct dn_naddr dnaddr, *dnaddrp, *dnet_addr();
 344: #endif
 345:     short family;
 346:     int len;
 347:     caddr_t addr;
 348: 
 349:     while (host = validhosts) {
 350:         validhosts = host->next;
 351:         free ((caddr_t) host);
 352:     }
 353:     for (self = selfhosts; self; self = self->next) {
 354:         host = (HOST *) Xalloc (sizeof (HOST));
 355:         *host = *self;
 356:         host->next = validhosts;
 357:         validhosts = host;
 358:     }
 359:     strcpy (fname, "/etc/X");
 360:     strcat (fname, display);
 361:     strcat (fname, ".hosts");
 362:     if (fd = fopen (fname, "r")) {
 363:         while (fgets (hostname, sizeof (hostname), fd)) {
 364:         if (ptr = index (hostname, '\n'))
 365:             *ptr = 0;
 366: #ifdef DNETCONN
 367:         if ((ptr = index (hostname, ':')) && (*(ptr + 1) == ':')) {
 368:             /* node name (DECnet names end in "::") */
 369:             *ptr = 0;
 370:             if (dnaddrp = dnet_addr(hostname)) {
 371:                 /* allow nodes to be specified by address */
 372:                 Add_host (-1, XAF_DECnet, (caddr_t) dnaddrp);
 373:             } else {
 374:             if (np = getnodebyname (hostname)) {
 375:                 /* node was specified by name */
 376:                 saddr.sa.sa_family = np->n_addrtype;
 377:                 if ((family = Convert_addr (&saddr.sa, &len, &addr)) == XAF_DECnet) {
 378:                 bzero ((caddr_t) &dnaddr, sizeof (dnaddr));
 379:                 dnaddr.a_len = np->n_length;
 380:                 bcopy (np->n_addr, (caddr_t) dnaddr.a_addr, np->n_length);
 381:                 Add_host (-1, family, (caddr_t) &dnaddr);
 382:                 }
 383:             }
 384:             }
 385:         } else {
 386: #endif
 387:             /* host name */
 388:             if (hp = gethostbyname (hostname)) {
 389:             saddr.sa.sa_family = hp->h_addrtype;
 390:             if ((family = Convert_addr (&saddr.sa, &len, &addr)) > 0)
 391:                 Add_host (-1, family, hp->h_addr);
 392:             }
 393: #ifdef DNETCONN
 394:         }
 395: #endif
 396:         }
 397:         fclose (fd);
 398:     }
 399: }
 400: 
 401: /* Add a host to the access control list */
 402: 
 403: Add_host (client, family, addr)
 404:     int client;
 405:     short family;
 406:     caddr_t addr;
 407: {
 408:     int len;
 409:     register HOST *host;
 410: 
 411:     if ((len = Check_family (client, family)) < 0)
 412:         return;
 413:     for (host = validhosts; host; host = host->next) {
 414:         if (family == host->family && !bcmp (addr, host->addr, len))
 415:         return;
 416:     }
 417:     host = (HOST *) Xalloc (sizeof (HOST));
 418:     host->family = family;
 419:     host->len = len;
 420:     bcopy(addr, host->addr, len);
 421:     host->next = validhosts;
 422:     validhosts = host;
 423: }
 424: 
 425: /* Remove a host from the access control list */
 426: 
 427: Remove_host (client, family, addr)
 428:     int client;
 429:     short family;
 430:     caddr_t addr;
 431: {
 432:     int len;
 433:     register HOST *host, **prev;
 434: 
 435:     if ((len = Check_family (client, family)) < 0)
 436:         return;
 437:     for (prev = &validhosts;
 438:          (host = *prev) &&
 439:           (family != host->family || bcmp (addr, host->addr, len));
 440:          prev = &host->next) ;
 441:     if (host) {
 442:         *prev = host->next;
 443:         free ((caddr_t) host);
 444:     }
 445: }
 446: 
 447: /* Get all hosts in the access control list */
 448: 
 449: Get_hosts (family, data)
 450:     short family;
 451:     char **data;
 452: {
 453:     int len;
 454:     register int n;
 455:     register caddr_t ptr;
 456:     register HOST *host;
 457: 
 458:     if ((len = Check_family (-1, family)) < 0)
 459:         return (-1);
 460:     n = 0;
 461:     for (host = validhosts; host; host = host->next) {
 462:         if (host->family == family)
 463:         n += len;
 464:     }
 465:     if (n) {
 466:         *data = ptr = Xalloc (n);
 467:         for (host = validhosts; host; host = host->next) {
 468:         if (host->family == family) {
 469:             bcopy (host->addr, ptr, len);
 470:             ptr += len;
 471:         }
 472:         }
 473:     }
 474:     return (n);
 475: }
 476: 
 477: /* Check for valid address family, and for local host if client modification.
 478:  * Return address length.
 479:  */
 480: 
 481: Check_family (client, family)
 482:     int client;
 483:     short family;
 484: {
 485:     struct sockaddr from;
 486:     int alen;
 487:     caddr_t addr;
 488:     register HOST *host;
 489:     int len;
 490: 
 491:     switch (family) {
 492:     case XAF_INET:
 493:         len = sizeof (struct in_addr);
 494:         break;
 495: #ifdef DNETCONN
 496:     case XAF_DECnet:
 497:         len = sizeof (struct dn_naddr);
 498:         break;
 499: #endif
 500:     default:
 501:         Xstatus = BadValue;
 502:         return (-1);
 503:     }
 504:     if (client < 0) return (len);
 505:     alen = sizeof (from);
 506:     if (!getpeername (client, &from, &alen)) {
 507:         if ((family = Convert_addr (&from, &alen, &addr)) >= 0) {
 508:         if (family == 0) return (len);
 509:         for (host = selfhosts; host; host = host->next) {
 510:             if (family == host->family &&
 511:             !bcmp (addr, host->addr, alen))
 512:             return (len);
 513:         }
 514:         }
 515:     }
 516:     Xstatus = BadAccess;
 517:     return (-1);
 518: }
 519: 
 520: /* Check if a host is not in the access control list */
 521: 
 522: Invalid_host (saddr, len)
 523:     register struct sockaddr *saddr;
 524:     int len;
 525: {
 526:     short family;
 527:     caddr_t addr;
 528:     register HOST *host;
 529: 
 530:     if ((family = Convert_addr (saddr, &len, &addr)) < 0)
 531:         return (1);
 532:     if (family == 0) return (0);
 533:     for (host = validhosts; host; host = host->next) {
 534:         if (family == host->family && !bcmp (addr, host->addr, len))
 535:         return (0);
 536:     }
 537:     return (1);
 538: }
 539: 
 540: Convert_addr (saddr, len, addr)
 541:     register struct sockaddr *saddr;
 542:     int *len;
 543:     caddr_t *addr;
 544: {
 545:     if (len == 0) return (0);
 546:     switch (saddr->sa_family) {
 547:     case AF_UNSPEC:
 548:     case AF_UNIX:
 549:         return (0);
 550:     case AF_INET:
 551:         *len = sizeof (struct in_addr);
 552:         *addr = (caddr_t) &(((struct sockaddr_in *) saddr)->sin_addr);
 553:         return (XAF_INET);
 554: #ifdef DNETCONN
 555:     case AF_DECnet:
 556:         *len = sizeof (struct dn_naddr);
 557:         *addr = (caddr_t) &(((struct sockaddr_dn *) saddr)->sdn_add);
 558:         return (XAF_DECnet);
 559: #endif
 560:     default:
 561:         break;
 562:     }
 563:     return (-1);
 564: }
 565: 
 566: /* Place data in a cut buffer, discarding previous contents */
 567: 
 568: Store_cut (n, data, len)
 569:     register unsigned n;
 570:     char *data;
 571:     int len;
 572: {
 573:     if (n >= NUMCUTS)
 574:         Xstatus = BadValue;
 575:     else {
 576:         n = (base_cut + n) & (NUMCUTS - 1);
 577:         if (cutbuf[n]) {
 578:         free (cutbuf[n]);
 579:         cutbuf[n] = NULL;
 580:         }
 581:         if (cutbuflen[n] = len) {
 582:         cutbuf[n] = Xalloc (BytePad(len));
 583:         bcopy (data, cutbuf[n], len);
 584:         }
 585:     }
 586: }
 587: 
 588: /* Copy the data from a cut buffer */
 589: 
 590: Fetch_cut (n, data)
 591:     register unsigned n;
 592:     char **data;
 593: {
 594:     if (n >= NUMCUTS) {
 595:         Xstatus = BadValue;
 596:         return (-1);
 597:     }
 598:     n = (base_cut + n) & (NUMCUTS - 1);
 599:     *data = cutbuf[n];
 600:     return (cutbuflen[n]);
 601: }
 602: 
 603: /* Rotate the cut buffers */
 604: 
 605: Rotate_cuts (n)
 606:     register unsigned n;
 607: {
 608:     if (n >= NUMCUTS)
 609:         Xstatus = BadValue;
 610:     else
 611:         base_cut = (base_cut + n) & (NUMCUTS - 1);
 612: }
 613: 
 614: /* Delete the data from all cut buffers */
 615: 
 616: Reset_cuts ()
 617: {
 618:     register int i;
 619: 
 620:     for (i = -1; ++i < NUMCUTS; ) {
 621:         if (cutbuf[i]) {
 622:         free (cutbuf[i]);
 623:         cutbuf[i] = NULL;
 624:         cutbuflen[i] = 0;
 625:         }
 626:     }
 627:     base_cut = 0;
 628: }
 629: 
 630: /* Create and initialize the color map */
 631: 
 632: Init_colormap ()
 633: {
 634:     colormap = (CMENTRY *) Xalloc ((int) device.entries * sizeof (CMENTRY));
 635:     bzero ((caddr_t) colormap, device.entries * sizeof (CMENTRY));
 636:     free_entries = device.entries;
 637:     if (device.entries > WhitePixel) {
 638:         free_entries -= 2;
 639:         colormap[BlackPixel].refcnt = -1;
 640:         colormap[WhitePixel].refcnt = -1;
 641:     }
 642: }
 643: 
 644: /* Get a read-only color (probably slow for large maps) */
 645: 
 646: Get_color (client, red, green, blue)
 647:     register int client;
 648:     ushort red, green, blue;
 649: {
 650:     register CMENTRY *ent;
 651:     register int pixel;
 652:     int free = 0;
 653:     register ushort *list;
 654:     int entries;
 655:     ColorDef def;
 656: 
 657:     ResolveColor (&red, &green, &blue);
 658:     /* see if there is a match, and also look for a free entry */
 659:     entries = device.entries;
 660:     for (ent = colormap, pixel = -1; ++pixel < entries; ent++) {
 661:         if (ent->refcnt > 0) {
 662:         if (ent->red == red && ent->green == green && ent->blue == blue) {
 663:             ent->refcnt++;
 664:             goto addit;
 665:         }
 666:         } else if (free == 0 && ent->refcnt == 0)
 667:         free = pixel;
 668:     }
 669:     if ((pixel = free) == 0) {
 670:         Xstatus = BadAlloc;
 671:         return (0);
 672:     }
 673:     free_entries--;
 674:     /* fill in the entry */
 675:     ent = &colormap[pixel];
 676:     ent->refcnt = 1;
 677:     ent->red = red;
 678:     ent->green = green;
 679:     ent->blue = blue;
 680:     def.pixel = pixel;
 681:     def.red = red;
 682:     def.green = green;
 683:     def.blue = blue;
 684:     StoreColors (1, &def);
 685: addit:  /* add pixel to client list */
 686:     list = (ushort *) Xrealloc ((caddr_t) clientpixels[client],
 687:                     (numpixels[client] + 1) << 1);
 688:     clientpixels[client] = list;
 689:     list[numpixels[client]] = pixel;
 690:     numpixels[client]++;
 691:     return (pixel);
 692: }
 693: 
 694: /* Allocate writeable color cells (probably slow for large maps) */
 695: 
 696: Get_cells (client, contig, count, planes, pixels)
 697:     int client, contig, planes;
 698:     register int count;
 699:     ushort **pixels;
 700: {
 701:     register ushort *pptr;
 702:     register CMENTRY *ent;
 703:     register int pixel;
 704:     register int maxp, mask;
 705:     int entries, dplanes, base, found, save;
 706: 
 707:     dplanes = device.planes;
 708: 
 709:     if (planes == 0) {
 710:         if (count == 0)
 711:         return (0);
 712:         if (count > free_entries)
 713:         goto bad;
 714:         free_entries -= count;
 715:         /* make room for new pixels */
 716:         pptr = (ushort *) Xrealloc ((caddr_t) clientpixels[client],
 717:                     (numpixels[client] + count) << 1);
 718:         clientpixels[client] = pptr;
 719:         pptr += numpixels[client];
 720:         *pixels = pptr;
 721:         numpixels[client] += count;
 722:         /* allocate writable entries */
 723:         ent = colormap;
 724:         pixel = 0;
 725:         while (--count >= 0) {
 726:         while (ent->refcnt) {
 727:             ent++;
 728:             pixel++;
 729:         }
 730:         ent->refcnt = -1;
 731:         *pptr++ = pixel;
 732:         }
 733:         return (0);
 734:     } else if (count == 0) {
 735:         if (planes >= dplanes)
 736:         goto bad;
 737:         entries = device.entries;
 738:         base = 1 << (dplanes - planes);
 739:         /* make sure all are free */
 740:         for (pixel = base - 1, ent = &colormap[base]; ++pixel < entries; ent++) {
 741:         if (ent->refcnt)
 742:             goto bad;
 743:         }
 744:         count = entries - base;
 745:         /* make room for new pixels */
 746:         pptr = (ushort *) Xrealloc ((caddr_t) clientpixels[client],
 747:                     (numpixels[client] + count) << 1);
 748:         clientpixels[client] = pptr;
 749:         pptr += numpixels[client];
 750:         numpixels[client] += count;
 751:         free_entries -= count;
 752:         /* allocate them */
 753:         for (pixel = base - 1, ent = &colormap[base]; ++pixel < entries; ent++) {
 754:         ent->refcnt = -1;
 755:         *pptr++ = pixel;
 756:         }
 757:         return (((1 << planes) - 1) << (dplanes - planes));
 758:     } else if (planes >= dplanes || (count << planes) > free_entries)
 759:         goto bad;
 760:     /* make room for new pixels */
 761:     pptr = (ushort *) Xrealloc ((caddr_t) clientpixels[client],
 762:                     (numpixels[client] + (count << planes)) << 1);
 763:     clientpixels[client] = pptr;
 764:     *pixels = pptr + numpixels[client];
 765:     ent = colormap;
 766:     /* first try for contiguous planes, since its fastest */
 767:     for (mask = (1 << planes) - 1, base = 1, dplanes -= (planes - 1);
 768:          --dplanes >= 0;
 769:          mask += mask, base += base) {
 770:         pptr = *pixels;
 771:         found = 0;
 772:         pixel = 0;
 773:         entries = device.entries - mask;
 774:         while (pixel < entries) {
 775:         save = pixel;
 776:         maxp = pixel + mask + base;
 777:         /* check if all are free */
 778:         while (pixel != maxp && ent[pixel].refcnt == 0)
 779:             pixel += base;
 780:         if (pixel == maxp) {
 781:             /* this one works */
 782:             *pptr++ = save;
 783:             found++;
 784:             if (found == count) {
 785:             /* found enough, allocate them all */
 786:             numpixels[client] += count << planes;
 787:             free_entries -= count << planes;
 788:             while (--count >= 0) {
 789:                 pixel = (*pixels)[count];
 790:                 maxp = pixel + mask;
 791:                 while (1) {
 792:                 ent[pixel].refcnt = -1;
 793:                 if (pixel == maxp)
 794:                     break;
 795:                 pixel += base;
 796:                 *pptr++ = pixel;
 797:                 }
 798:             }
 799:             return (mask);
 800:             }
 801:         }
 802:         pixel = save + 1;
 803:         if (pixel & mask)
 804:             pixel += mask;
 805:         }
 806:     }
 807:     if (contig || planes == 1) goto fail;
 808:     /* this will be very slow for large maps, need a better algorithm */
 809:     dplanes = (1 << device.planes) - (1 << planes);
 810:     for (mask = 0; mask <= dplanes; mask++) {
 811:         /* next 3 magic statements count number of ones (HAKMEM #169) */
 812:         pixel = (mask >> 1) & 03333333333;
 813:         pixel = mask - pixel - ((pixel >> 1) & 03333333333);
 814:         if ((((pixel + (pixel >> 3)) & 0707070707) % 077) != planes)
 815:         continue;
 816:         pptr = *pixels;
 817:         found = 0;
 818:         entries = device.entries - mask;
 819:         base = 1 << (ffs(mask) - 1);
 820:         for (pixel = 0; pixel < entries; pixel++) {
 821:         if (pixel & mask) continue;
 822:         maxp = 0;
 823:         /* check if all are free */
 824:         while (ent[pixel + maxp].refcnt == 0) {
 825:             maxp += base;
 826:             if (maxp > mask)
 827:             break;
 828:             while (maxp & ~mask)
 829:             maxp += (maxp & ~mask);
 830:         }
 831:         if (maxp <= mask)
 832:             continue;
 833:         /* this one works */
 834:         *pptr++ = pixel;
 835:         found++;
 836:         if (found < count)
 837:             continue;
 838:         /* found enough, allocate them all */
 839:         numpixels[client] += count << planes;
 840:         free_entries -= count << planes;
 841:         while (--count >= 0) {
 842:             pixel = (*pixels)[count];
 843:             maxp = 0;
 844:             while (1) {
 845:             ent[pixel + maxp].refcnt = -1;
 846:             if (maxp == mask)
 847:                 break;
 848:             maxp += base;
 849:             while (maxp & ~mask)
 850:                 maxp += (maxp & ~mask);
 851:             *pptr++ = pixel + maxp;
 852:             }
 853:         }
 854:         return (mask);
 855:         }
 856:     }
 857: fail:   /* failed to get them, back out of the allocation */
 858:     if (count = numpixels[client])
 859:         clientpixels[client] = (ushort *) Xrealloc ((caddr_t) clientpixels[client],
 860:                             count << 1);
 861:     else {
 862:         free ((caddr_t) clientpixels[client]);
 863:         clientpixels[client] = NULL;
 864:     }
 865: bad:    Xstatus = BadAlloc;
 866:     return (0);
 867: }
 868: 
 869: /* Free colors and/or cells (probably slow for large numbers) */
 870: 
 871: Free_colors (client, count, pixels, mask)
 872:     int client, count;
 873:     ushort *pixels;
 874:     unsigned mask;
 875: {
 876:     register ushort *pptr, *cptr;
 877:     unsigned bits, bit;
 878:     ushort pixel;
 879:     register CMENTRY *ent;
 880:     register int n, z;
 881:     int zapped;
 882: 
 883:     if (count == 0) return;
 884:     bits = 0;
 885:     zapped = 0;
 886:     while (1) {
 887:         /* go through pixel list */
 888:         for (pptr = pixels, n = count; --n >= 0; pptr++) {
 889:         pixel = *pptr | bits;
 890:         /* find match in client list */
 891:         for (cptr = clientpixels[client], z = numpixels[client];
 892:              --z >= 0 && *cptr != pixel;
 893:              cptr++) ;
 894:         if (z >= 0 && pixel) {
 895:             ent = &colormap[pixel];
 896:             if (ent->refcnt < 0)
 897:             ent->refcnt = 0;
 898:             else
 899:             ent->refcnt--;
 900:             if (ent->refcnt == 0)
 901:             free_entries++;
 902:             *cptr = 0;
 903:             zapped++;
 904:         } else if (pixel >= device.entries)
 905:             Xstatus = BadValue;
 906:         else
 907:             Xstatus = BadAccess;
 908:         }
 909:         if (bits == mask)
 910:         break;
 911:         /* generate next bits value */
 912:         bit = 1;
 913:         while (1) {
 914:         while (!(mask & bit))
 915:             bit += bit;
 916:         bits ^= bit;
 917:         if (bits & bit)
 918:             break;
 919:         bit += bit;
 920:         }
 921:     }
 922:     if (zapped) {
 923:         /* delete zeroes from list */
 924:         n = numpixels[client] - zapped;
 925:         if (n) {
 926:         pixels = (ushort *) Xalloc (n << 1);
 927:         pptr = pixels;
 928:         cptr = clientpixels[client];
 929:         z = n;
 930:         while (1) {
 931:             if (*cptr) {
 932:             *pptr++ = *cptr;
 933:             if (--z == 0)
 934:                 break;
 935:             }
 936:             cptr++;
 937:         }
 938:         } else
 939:         pixels = NULL;
 940:         free ((caddr_t) clientpixels[client]);
 941:         clientpixels[client] = pixels;
 942:         numpixels[client] = n;
 943:     }
 944: }
 945: 
 946: /* Free all of a client's colors and cells */
 947: 
 948: Free_client_colors (client)
 949:     register int client;
 950: {
 951:     register ushort *pptr;
 952:     register int n;
 953:     register CMENTRY *ent;
 954: 
 955:     if ((pptr = clientpixels[client]) == NULL)
 956:         return;
 957:     n = numpixels[client];
 958:     while (--n >= 0) {
 959:         ent = &colormap[*pptr++];
 960:         if (ent->refcnt < 0)
 961:         ent->refcnt = 0;
 962:         else
 963:         ent->refcnt--;
 964:         if (ent->refcnt == 0)
 965:         free_entries++;
 966:     }
 967:     free ((caddr_t) clientpixels[client]);
 968:     clientpixels[client] = NULL;
 969:     numpixels[client] = 0;
 970: }
 971: 
 972: /* Redefine color values */
 973: 
 974: Store_colors (count, defs)
 975:     int count;
 976:     ColorDef *defs;
 977: {
 978:     register int n;
 979:     register ColorDef *def;
 980:     register CMENTRY *ent;
 981: 
 982:     /* first make sure all are writable */
 983:     for (def = defs, n = count; --n >= 0; def++) {
 984:         if (def->pixel >= device.entries) {
 985:         Xstatus = BadValue;
 986:         return;
 987:         } else if (colormap[def->pixel].refcnt >= 0) {
 988:         Xstatus = BadAccess;
 989:         return;
 990:         }
 991:     }
 992:     /* update them */
 993:     for (def = defs, n = count; --n >= 0; def++) {
 994:         ResolveColor (&def->red, &def->green, &def->blue);
 995:         ent = &colormap[def->pixel];
 996:         ent->red = def->red;
 997:         ent->green = def->green;
 998:         ent->blue = def->blue;
 999:     }
1000:     StoreColors (count, defs);
1001: }
1002: 
1003: /* Read the color value of a cell */
1004: 
1005: Query_color (pixel, red, green, blue)
1006:     register unsigned pixel;
1007:     ushort *red, *green, *blue;
1008: {
1009:     register CMENTRY *ent;
1010: 
1011:     if (pixel >= device.entries)
1012:         Xstatus = BadValue;
1013:     else {
1014:         ent = &colormap[pixel];
1015:         *red = ent->red;
1016:         *green = ent->green;
1017:         *blue = ent->blue;
1018:     }
1019: }
1020: 
1021: #define alloc_at_once 50
1022: 
1023: /* Called from the rectangle macros when the free list is empty.
1024:  * We allocate in chunks to minimize fragmentation.
1025:  */
1026: 
1027: RECTANGLE *Alloc_rectangle ()
1028: {
1029:     register RECTANGLE *r, *rec;
1030:     register int i;
1031: 
1032:     rec = (RECTANGLE *) Xalloc (alloc_at_once * sizeof (RECTANGLE));
1033:     r = rec;
1034:     rec->internal = 0;
1035:     i = alloc_at_once;
1036:     while (--i > 0) {
1037:         r->next = r + 1;
1038:         r++;
1039:         r->internal = 1;
1040:     }
1041:     r->next = NULL;
1042:     return (rec);
1043: }
1044: 
1045: /* Put all the rectangles back on the free list. */
1046: 
1047: Free_rectangles (rlist)
1048:     register RECTANGLE *rlist;
1049: {
1050:     register RECTANGLE *rec;
1051: 
1052:     rec = rlist;
1053:     while (rec->next)
1054:         rec = rec->next;
1055:     rec->next = free_rectangles;
1056:     free_rectangles = rlist;
1057: }
1058: 
1059: /* Free storage associated with unused rectangles */
1060: 
1061: Free_rectangle_storage ()
1062: {
1063:     register RECTANGLE *r, **pr;
1064: 
1065:     /* drop the "internal" rectangles */
1066:     pr = &free_rectangles;
1067:     while (r = *pr) {
1068:         if TRUE(r->internal)
1069:         *pr = r->next;
1070:         else
1071:         pr = &r->next;
1072:     }
1073:     /* now free the "head" rectangles */
1074:     while (r = free_rectangles) {
1075:         free_rectangles = r->next;
1076:         free ((caddr_t) r);
1077:     }
1078: }
1079: 
1080: /* malloc wrap-around, to take care of the "no memory" case, since
1081:  * it would be difficult in many places to "back out" on failure.
1082:  */
1083: 
1084: char *Xalloc (amount)
1085:     int amount;
1086: {
1087:     register char *ptr;
1088: 
1089:     if (ptr = malloc ((unsigned) amount))
1090:         return (ptr);
1091:     errno = ENOMEM;
1092:     Error ("Allocating");
1093:     /*NOTREACHED*/
1094: }
1095: 
1096: /* realloc wrap-around, to take care of the "no memory" case, since
1097:  * it would be difficult in many places to "back out" on failure.
1098:  */
1099: 
1100: char *Xrealloc (ptr, amount)
1101:     register char *ptr;
1102:     int amount;
1103: {
1104:     if (ptr)
1105:         ptr = realloc (ptr, (unsigned) amount);
1106:     else
1107:         ptr = malloc ((unsigned) amount);
1108:     if (ptr)
1109:         return (ptr);
1110:     errno = ENOMEM;
1111:     Error ("Allocating");
1112:     /*NOTREACHED*/
1113: }

Defined functions

Add_host defined in line 403; used 4 times
Add_resource defined in line 89; used 10 times
Bit_size defined in line 206; used 3 times
Check_family defined in line 481; used 3 times
Convert_addr defined in line 540; used 5 times
Define_self defined in line 288; used 3 times
Fetch_cut defined in line 590; used 1 times
Free_client_colors defined in line 948; used 1 times
Free_client_resources defined in line 171; used 1 times
Free_colors defined in line 871; used 1 times
Free_rectangle_storage defined in line 1061; used 1 times
Free_rectangles defined in line 1047; used 8 times
Free_resource defined in line 137; used 8 times
Get_cells defined in line 696; used 1 times
Get_color defined in line 646; used 1 times
Get_font defined in line 236; used 2 times
Get_hosts defined in line 449; used 1 times
Init_colormap defined in line 632; used 1 times
Invalid_host defined in line 522; used 1 times
Pix_size defined in line 217; used 4 times
Query_color defined in line 1005; used 3 times
Remove_host defined in line 427; used 1 times
Reset_cuts defined in line 616; used 1 times
Reset_hosts defined in line 325; used 1 times
Rotate_cuts defined in line 605; used 1 times
Store_colors defined in line 974; used 3 times
Store_cursor defined in line 265; used 2 times
Store_cut defined in line 568; used 1 times
Xalloc defined in line 1084; used 23 times
Xrealloc defined in line 1100; used 7 times

Defined variables

ClientResources defined in line 48; used 2 times
FreeResource defined in line 51; used 7 times
MaxResource defined in line 50; used 6 times
Resources defined in line 47; used 8 times
base_cut defined in line 83; used 5 times
colormap defined in line 74; used 15 times
cutbuf defined in line 81; used 9 times
cutbuflen defined in line 82; used 3 times
free_entries defined in line 75; used 11 times
free_rectangles defined in line 85; used 5 times
numpixels defined in line 77; used 19 times
rcsid_resource_c defined in line 18; never used
ridseed defined in line 55; used 3 times
selfhosts defined in line 64; used 5 times
validhosts defined in line 65; used 11 times

Defined struct's

_cmentry defined in line 67; never used
_host defined in line 57; used 2 times
  • in line 61(2)

Defined typedef's

CMENTRY defined in line 72; used 10 times
HOST defined in line 62; used 15 times

Defined macros

NUMCUTS defined in line 80; used 9 times
alloc_at_once defined in line 1021; used 2 times
resalloc defined in line 42; used 4 times
ridinc defined in line 53; used 1 times
ridmask defined in line 54; used 1 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2623
Valid CSS Valid XHTML 1.0 Strict