1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1985 */ 4: 5: #ifndef lint 6: static char *rcsid_pikapix_c = "$Header: pikapix.c,v 10.5 86/02/01 16:11:15 tony Rel $"; 7: #endif lint 8: 9: #include <X/Xlib.h> 10: #include <stdio.h> 11: #include <strings.h> 12: #include "../cursors/target.cursor" 13: #include "../cursors/target_mask.cursor" 14: #include <sys/types.h> 15: 16: #define pik_width 15 17: #define pik_height 15 18: static short pik_bits[] = { 19: 0x8080, 0x8080, 0x81c0, 0x83e0, 20: 0x87f0, 0x8ff8, 0x9ffc, 0xbffe, 21: 0xbffe, 0xbffe, 0xbffe, 0xbffe, 22: 0xbffe, 0xbffe, 0x8000}; 23: static short pik_mask_bits[] = { 24: 0x8080, 0x81c0, 0x83e0, 0x87f0, 25: 0x8ff8, 0x9ffc, 0xbffe, 0xffff, 26: 0xffff, 0xffff, 0xffff, 0xffff, 27: 0xffff, 0xffff, 0xffff}; 28: 29: #define MIN(a,b) (((a) < (b)) ? (a) : (b)) 30: 31: #define MAXIDX 200 32: #define PROMPT "#ffffff -> " 33: #define ASKSIZE (sizeof(PROMPT) + 25) 34: 35: #define RGBSIDE 50 36: #define RGBWIDTH (RGBSIDE * 3) 37: #define RGBHEIGHT (RGBSIDE * 2) 38: 39: #define BASEDELTA (1<<8) 40: 41: char *malloc(); 42: 43: Window win; 44: u_char *buf; 45: u_char transbuf[256]; 46: int width, height; 47: int pixels[5]; 48: Color cdefs[2]; 49: Color origdefs[256]; 50: WindowInfo rinfo; 51: Font font; 52: Color rgbdefs[3]; 53: Window rgb, redw, greenw, bluew; 54: int rgbx, rgby; 55: int shared = 0; 56: 57: main(argc, argv) 58: int argc; 59: char **argv; 60: { 61: Cursor cursor; 62: XEvent ev; 63: XExposeEvent *exp = (XExposeEvent *) &ev; 64: XMouseMovedEvent *mot = (XMouseMovedEvent *) &ev; 65: register XButtonPressedEvent *but = (XButtonPressedEvent *) &ev; 66: WindowInfo winfo; 67: Window ask; 68: int asking = 0; 69: int askwidth; 70: int askheight; 71: char colorbuf[MAXIDX + sizeof(PROMPT) + 1]; 72: register char *colorname = &colorbuf[sizeof(PROMPT)]; 73: int coloridx = 0; 74: int mixing = 0; 75: int mixtrack = 0; 76: char *string; 77: int nbytes; 78: int tpix, cnt; 79: unsigned char pixel; 80: Color cdef; 81: FontInfo finfo; 82: int xoff, yoff; 83: char *display = NULL; 84: 85: for (cnt = 1; cnt < argc; cnt++) { 86: if (!*argv[cnt]) continue; 87: if (strcmp(argv[cnt], "-s") == 0) 88: shared = 1; 89: else if (index(argv[cnt], ':')) 90: display = argv[cnt]; 91: else { 92: fprintf(stderr, "usage: pikapix [-s] [host:display]\n"); 93: (void) fflush(stderr); 94: exit(1); 95: } 96: } 97: if (!XOpenDisplay(display)) { 98: perror("pikapix"); 99: exit(1); 100: } 101: if (DisplayPlanes() < 2 || DisplayPlanes() > 8) 102: Error("only works on displays with 2 to 8 planes"); 103: cursor = XCreateCursor(target_width, target_height, 104: target_bits, target_mask_bits, 105: 8, 8, BlackPixel, WhitePixel, GXcopy); 106: while (!XGrabMouse(RootWindow, cursor, ButtonPressed)) 107: sleep(1); 108: XNextEvent(&ev); 109: XUngrabMouse(); 110: win = but->subwindow; 111: if (!win) 112: Error("no window selected"); 113: xoff = 0; 114: yoff = 0; 115: switch (but->detail & ValueMask) { 116: case LeftButton: 117: case MiddleButton: 118: do { 119: XInterpretLocator(win, &but->x, &but->y, &but->subwindow, 120: but->location); 121: if (!but->subwindow) 122: break; 123: if (!XQueryWindow(win, &winfo)) 124: Error("window disappeared"); 125: xoff += winfo.x + winfo.bdrwidth; 126: yoff += winfo.y + winfo.bdrwidth; 127: but->window = win; 128: win = but->subwindow; 129: } while ((but->detail & ValueMask) == LeftButton); 130: } 131: XFreeCursor(cursor); 132: if (!XGetColorCells(0, 5, 0, &cnt, pixels)) 133: Error("not enough color map entries"); 134: cdefs[0].pixel = pixels[0]; 135: cdefs[0].red = cdefs[0].green = cdefs[0].blue = ~0; 136: cdefs[1].pixel = pixels[1]; 137: cdefs[1].red = cdefs[1].green = cdefs[1].blue = 0; 138: XStoreColors(2, cdefs); 139: cursor = XCreateCursor(pik_width, pik_height, 140: pik_bits, pik_mask_bits, 141: 7, 0, pixels[0], pixels[1], GXcopy); 142: if (!XQueryWindow(win, &winfo)) 143: Error("window disappeared"); 144: width = winfo.width + (winfo.bdrwidth << 1); 145: height = winfo.height + (winfo.bdrwidth << 1); 146: nbytes = BZPixmapSize(width, height); 147: buf = (u_char *) malloc(nbytes); 148: if (buf == NULL) 149: Error("window too large"); 150: XPixmapGetZ(but->window, winfo.x, winfo.y, width, height, buf); 151: if (!shared) { 152: for (cnt = 256; --cnt >= 0; ) 153: transbuf[cnt] = cnt; 154: while (--nbytes >= 0) { 155: pixel = buf[nbytes]; 156: if (transbuf[pixel] != pixel) 157: continue; 158: cdef.pixel = pixel; 159: XQueryColor(&cdef); 160: if (!XGetColorCells(0, 1, 0, &cnt, &cdef.pixel)) 161: Error("not enough color map entries, try -s option"); 162: transbuf[pixel] = cdef.pixel; 163: origdefs[cdef.pixel] = cdef; 164: origdefs[pixel] = cdef; 165: origdefs[pixel].pixel = pixel; 166: XStoreColors(1, &cdef); 167: } 168: } else { 169: transbuf[0] = 1; 170: while (--nbytes >= 0) { 171: pixel = buf[nbytes]; 172: if (transbuf[pixel] == pixel) 173: continue; 174: cdef.pixel = pixel; 175: XQueryColor(&cdef); 176: transbuf[pixel] = pixel; 177: origdefs[pixel] = cdef; 178: } 179: } 180: win = XCreateWindow(RootWindow, xoff + winfo.x, yoff + winfo.y, 181: width, height, 0, (Pixmap) 0, (Pixmap) 0); 182: XStoreName(win, "pikapix"); 183: XDefineCursor(win, cursor); 184: XSelectInput(win, KeyPressed|ButtonPressed|ExposeRegion|MouseMoved); 185: XMapWindow(win); 186: font = XGetFont("6x10"); 187: if (!font) Error("couldn't open font"); 188: XQueryFont(font, &finfo); 189: askwidth = finfo.width * ASKSIZE + 2; 190: askheight = finfo.height + 2; 191: ask = XCreateWindow(RootWindow, 0, 0, askwidth, askheight, 192: 2, BlackPixmap, WhitePixmap); 193: askwidth += 4; 194: askheight += 4; 195: XSelectInput(ask, KeyPressed|ExposeWindow|ButtonPressed); 196: XDefineCursor(ask, cursor); 197: rgb = XCreateWindow(RootWindow, 0, 0, RGBWIDTH, RGBHEIGHT, 198: 2, XMakeTile(pixels[1]), XMakeTile(pixels[0])); 199: redw = XCreateWindow(rgb, 0, 0, RGBSIDE, RGBSIDE, 200: 0, (Pixmap) 0, XMakeTile(pixels[2])); 201: rgbdefs[0].pixel = pixels[2]; 202: greenw = XCreateWindow(rgb, RGBSIDE, 0, RGBSIDE, RGBSIDE, 203: 0, (Pixmap) 0, XMakeTile(pixels[3])); 204: rgbdefs[1].pixel = pixels[3]; 205: bluew = XCreateWindow(rgb, RGBSIDE * 2, 0, RGBSIDE, RGBSIDE, 206: 0, (Pixmap) 0, XMakeTile(pixels[4])); 207: rgbdefs[2].pixel = pixels[4]; 208: rgbx = (RGBWIDTH - (finfo.width * 6)) >> 1; 209: rgby = RGBSIDE + ((RGBSIDE - finfo.height) >> 1); 210: XMapSubwindows(rgb); 211: XSelectInput(rgb, ButtonPressed|ExposeWindow); 212: XSelectInput(redw, ButtonPressed|ButtonReleased|MiddleDownMotion); 213: XSelectInput(greenw, ButtonPressed|ButtonReleased|MiddleDownMotion); 214: XSelectInput(bluew, ButtonPressed|ButtonReleased|MiddleDownMotion); 215: XDefineCursor(rgb, cursor); 216: XQueryWindow(RootWindow, &rinfo); 217: RedoCursor(1); 218: while (1) { 219: XNextEvent(&ev); 220: switch ((int)ev.type) { 221: case MouseMoved: 222: if (asking || (mixing && !mixtrack)) 223: break; 224: if (mixtrack) { 225: XUpdateMouse(mot->window, &xoff, &yoff, &mot->subwindow); 226: CalcRGB(mot->window, pixel, yoff); 227: } else 228: RedoCursor(0); 229: break; 230: case KeyPressed: 231: string = XLookupMapping (&ev, &nbytes); 232: if (nbytes == 1 && (*string == '\003' || *string == '\004')) { 233: if (asking) { 234: coloridx = 0; 235: asking = 0; 236: XUnmapWindow(ask); 237: RedoCursor(0); 238: } else if (mixing) { 239: mixing = 0; 240: XUnmapWindow(rgb); 241: RedoCursor(1); 242: } else 243: exit(0); 244: } else if (asking && ev.window == ask) { 245: while (--nbytes >= 0) 246: colorname[coloridx++] = *string++; 247: if (colorname[coloridx - 1] == '\r') { 248: coloridx--; 249: asking = 0; 250: } else if (colorname[coloridx - 1] == '\177') { 251: if (--coloridx) { 252: --coloridx; 253: XClear(ask); 254: } 255: } else if (colorname[coloridx - 1] == '\025') { 256: if (--coloridx) 257: XClear(ask); 258: coloridx = 0; 259: } 260: XText(ask, 1, 1, colorbuf, sizeof (PROMPT) + coloridx, font, 261: BlackPixel, WhitePixel); 262: if (!asking) { 263: XUnmapWindow(ask); 264: if (coloridx) { 265: colorname[coloridx] = '\0'; 266: if (XParseColor(colorname, &cdef)) { 267: if (!shared) { 268: cdef.pixel = transbuf[pixel]; 269: XStoreColors(1, &cdef); 270: origdefs[cdef.pixel] = cdef; 271: RedoCursor(1); 272: } else if (XGetHardwareColor(&cdef)) { 273: if (transbuf[pixel] != pixel) { 274: tpix = transbuf[pixel]; 275: XFreeColors(&tpix, 1, 0); 276: } 277: transbuf[pixel] = cdef.pixel; 278: origdefs[cdef.pixel] = cdef; 279: RedoCursor(1); 280: BitsPut(0, 0, width, height); 281: } else XFeep(0); 282: } else 283: XFeep(0); 284: coloridx = 0; 285: } 286: } 287: } 288: break; 289: case ButtonPressed: 290: if (asking) { 291: coloridx = 0; 292: asking = 0; 293: XUnmapWindow(ask); 294: RedoCursor(1); 295: break; 296: } 297: if (mixing && but->window == rgb) { 298: switch (but->detail & ValueMask) { 299: case LeftButton: 300: case MiddleButton: 301: if ((but->detail & ValueMask) == LeftButton) 302: cdefs[0] = origdefs[pixel]; 303: else 304: cdefs[0] = cdef; 305: if (!shared) { 306: cdefs[0].pixel = transbuf[pixel]; 307: origdefs[cdefs[0].pixel] = cdefs[0]; 308: XStoreColors(1, &cdefs[0]); 309: } 310: cdefs[0].pixel = pixels[0]; 311: rgbdefs[0].red = cdefs[0].red; 312: rgbdefs[1].green = cdefs[0].green; 313: rgbdefs[2].blue = cdefs[0].blue; 314: XStoreColors(3, rgbdefs); 315: ResetCursor(); 316: PrintRGB(); 317: break; 318: case RightButton: 319: XUnmapWindow(rgb); 320: if (cdef.red != cdefs[0].red || 321: cdef.green != cdefs[0].green || 322: cdef.blue != cdefs[0].blue) { 323: cdef = cdefs[0]; 324: if (!shared) { 325: cdef.pixel = transbuf[pixel]; 326: origdefs[cdef.pixel] = cdef; 327: XStoreColors(1, &cdef); 328: } else if (XGetHardwareColor(&cdef)) { 329: if (transbuf[pixel] != pixel) { 330: tpix = transbuf[pixel]; 331: XFreeColors(&tpix, 1, 0); 332: } 333: transbuf[pixel] = cdef.pixel; 334: origdefs[cdef.pixel] = cdef; 335: RedoCursor(1); 336: BitsPut(0, 0, width, height); 337: } else 338: XFeep(0); 339: } 340: RedoCursor(1); 341: mixing = 0; 342: mixtrack = 0; 343: break; 344: } 345: break; 346: } 347: if (mixing && but->window == win) 348: break; 349: if (mixing) { 350: switch (but->detail & ValueMask) { 351: case MiddleButton: 352: mixtrack = 1; 353: CalcRGB(but->window, pixel, but->y); 354: break; 355: case LeftButton: 356: UpdateRGB(but->window, pixel, -BASEDELTA); 357: break; 358: case RightButton: 359: UpdateRGB(but->window, pixel, BASEDELTA); 360: break; 361: } 362: break; 363: } 364: pixel = buf[BZPixmapSize(width, but->y) + BZPixmapSize(but->x, 1)]; 365: switch (but->detail & ValueMask) { 366: case LeftButton: 367: if (!shared) { 368: cdef = origdefs[pixel]; 369: cdef.pixel = transbuf[pixel]; 370: origdefs[cdef.pixel] = cdef; 371: XStoreColors(1, &cdef); 372: RedoCursor(1); 373: } else if (transbuf[pixel] != pixel) { 374: tpix = transbuf[pixel]; 375: XFreeColors(&tpix, 1, 0); 376: transbuf[pixel] = pixel; 377: RedoCursor(1); 378: BitsPut(0, 0, width, height); 379: } 380: break; 381: case MiddleButton: 382: PopWindow(ask, but, askwidth, askheight); 383: (void)sprintf(colorbuf, "#%02x%02x%02x -> ", cdefs[0].red >> 8, 384: cdefs[0].green >> 8, cdefs[0].blue >> 8); 385: asking = 1; 386: break; 387: case RightButton: 388: mixing = 1; 389: cdef.red = rgbdefs[0].red = cdefs[0].red; 390: cdef.green = rgbdefs[1].green = cdefs[0].green; 391: cdef.blue = rgbdefs[2].blue = cdefs[0].blue; 392: XStoreColors(3, rgbdefs); 393: PopWindow(rgb, but, RGBWIDTH+4, RGBHEIGHT+4); 394: break; 395: } 396: break; 397: case ButtonReleased: 398: if (mixtrack && ((but->detail & ValueMask) == MiddleButton)) { 399: CalcRGB(but->window, pixel, but->y); 400: mixtrack = 0; 401: } 402: break; 403: case ExposeWindow: 404: case ExposeRegion: 405: if (exp->window == ask) { 406: XText(ask, 1, 1, colorbuf, sizeof (PROMPT) + coloridx, font, 407: BlackPixel, WhitePixel); 408: } else if (exp->window == rgb) { 409: if (exp->subwindow == NULL ) PrintRGB(); 410: } else { 411: exp->width = MIN(exp->x + exp->width, width) - exp->x; 412: exp->height = MIN(exp->y + exp->height, height) - exp->y; 413: if (exp->width > 0 && exp->height > 0) 414: BitsPut(exp->x, exp->y, exp->width, exp->height); 415: } 416: break; 417: } 418: } 419: } 420: 421: PopWindow (pop, but, w, h) 422: Window pop; 423: XButtonPressedEvent *but; 424: int w, h; 425: { 426: int x, y; 427: 428: x = ((but->location >> 16) & 0xffff) - (w >> 1); 429: if (x < 0) 430: x = 0; 431: else if (x + w > rinfo.width) 432: x = rinfo.width - w; 433: y = (but->location & 0xffff) - (h >> 1) - 3; 434: if (y < 0) 435: y = 0; 436: else if (y + h > rinfo.height) 437: y = rinfo.height - h; 438: XMoveWindow(pop, x, y); 439: XMapWindow(pop); 440: } 441: 442: RedoCursor (force) 443: int force; 444: { 445: int x, y; 446: Window sub; 447: unsigned char pixel; 448: static unsigned short curspix = ~0; 449: 450: XUpdateMouse(win, &x, &y, &sub); 451: if (x < 0 || x >= width || y < 0 || y >= height) 452: return; 453: pixel = transbuf[buf[BZPixmapSize(width, y) + BZPixmapSize(x, 1)]]; 454: if (!force && (pixel == curspix)) 455: return; 456: curspix = pixel; 457: cdefs[0] = origdefs[pixel]; 458: cdefs[0].pixel = pixels[0]; 459: ResetCursor(); 460: } 461: 462: ResetCursor() 463: { 464: if (cdefs[0].red <= 0x8000 && 465: cdefs[0].green <= 0x8000 && 466: cdefs[0].blue <= 0x8000) 467: cdefs[1].red = cdefs[1].green = cdefs[1].blue = ~0; 468: else 469: cdefs[1].red = cdefs[1].green = cdefs[1].blue = 0; 470: XStoreColors(2, cdefs); 471: } 472: 473: UpdateRGB (ew, pixel, value) 474: Window ew; 475: unsigned pixel; 476: int value; 477: { 478: Color cdef; 479: 480: if (ew == redw) { 481: value += rgbdefs[0].red; 482: if (value < 0) 483: value = 0; 484: else if (value > 0xffff) 485: value = 0xffff; 486: rgbdefs[0].red = value; 487: XStoreColors(1, &rgbdefs[0]); 488: } else if (ew == greenw) { 489: value += rgbdefs[1].green; 490: if (value < 0) 491: value = 0; 492: else if (value > 0xffff) 493: value = 0xffff; 494: rgbdefs[1].green = value; 495: XStoreColors(1, &rgbdefs[1]); 496: } else if (ew == bluew) { 497: value += rgbdefs[2].blue; 498: if (value < 0) 499: value = 0; 500: else if (value > 0xffff) 501: value = 0xffff; 502: rgbdefs[2].blue = value; 503: XStoreColors(1, &rgbdefs[2]); 504: } else 505: return; 506: cdefs[0].red = rgbdefs[0].red; 507: cdefs[0].green = rgbdefs[1].green; 508: cdefs[0].blue = rgbdefs[2].blue; 509: ResetCursor(); 510: if (!shared) { 511: cdef = cdefs[0]; 512: cdef.pixel = transbuf[pixel]; 513: origdefs[cdef.pixel] = cdef; 514: XStoreColors(1, &cdef); 515: } 516: PrintRGB(); 517: } 518: 519: CalcRGB (ew, pixel, value) 520: Window ew; 521: unsigned pixel; 522: int value; 523: { 524: Color cdef; 525: 526: if (value < 0) 527: value = 0; 528: else if (value >= RGBSIDE) 529: value = (RGBSIDE - 1); 530: value = (0xffff * value) / (RGBSIDE - 1); 531: if (ew == redw) { 532: rgbdefs[0].red = value; 533: XStoreColors(1, &rgbdefs[0]); 534: } else if (ew == greenw) { 535: rgbdefs[1].green = value; 536: XStoreColors(1, &rgbdefs[1]); 537: } else if (ew == bluew) { 538: rgbdefs[2].blue = value; 539: XStoreColors(1, &rgbdefs[2]); 540: } else 541: return; 542: cdefs[0].red = rgbdefs[0].red; 543: cdefs[0].green = rgbdefs[1].green; 544: cdefs[0].blue = rgbdefs[2].blue; 545: ResetCursor(); 546: if (!shared) { 547: cdef = cdefs[0]; 548: cdef.pixel = transbuf[pixel]; 549: origdefs[cdef.pixel] = cdef; 550: XStoreColors(1, &cdef); 551: } 552: PrintRGB(); 553: } 554: 555: PrintRGB () 556: { 557: char rgbbuf[7]; 558: 559: (void) sprintf(rgbbuf, "%02x%02x%02x", cdefs[0].red >> 8, 560: cdefs[0].green >> 8, cdefs[0].blue >> 8); 561: XText(rgb, rgbx, rgby, rgbbuf, 6, font, BlackPixel, WhitePixel); 562: } 563: 564: #define CHUNKSIZE 2048 565: u_char outbuf[CHUNKSIZE]; 566: 567: BitsPut (x, y, w, h) 568: int x, y, w, h; 569: { 570: register u_char *data, *ptr, *trans; 571: register int i, j; 572: int per, delta, linesize; 573: 574: trans = transbuf; 575: linesize = BZPixmapSize(width, 1); 576: data = &buf[y * linesize + BZPixmapSize(x, 1)]; 577: 578: per = BZPixmapSize(w, 1); 579: delta = CHUNKSIZE / per; 580: linesize -= per; 581: 582: while (h) { 583: if (h < delta) 584: delta = h; 585: for (ptr = outbuf, i = delta; --i >= 0; data += linesize) { 586: for (j = per; --j >= 0; ) 587: *ptr++ = trans[*data++]; 588: } 589: XPixmapBitsPutZ(win, x, y, w, delta, outbuf, 590: NULL, GXcopy, AllPlanes); 591: y += delta; 592: h -= delta; 593: } 594: } 595: 596: Error (why) 597: char *why; 598: { 599: fprintf(stderr, "pikapix: %s\n", why); 600: (void) fflush(stderr); 601: exit(1); 602: }