|
|
1.1 ! root 1: #include "xjerq.h" ! 2: #include <errno.h> ! 3: #ifdef BSD ! 4: #include <sys/ioctl.h> ! 5: #else ! 6: #include <sys/filio.h> ! 7: #endif ! 8: ! 9: Rectangle Drect; ! 10: Bitmap display; ! 11: struct Mouse mouse; ! 12: static struct JProc sP; ! 13: struct JProc *P; ! 14: GC gcs[4]; ! 15: Display *dpy; ! 16: unsigned long fgpix; ! 17: unsigned long bgpix; ! 18: Colormap colormap; ! 19: XColor fgcolor, bgcolor; ! 20: Font defont; ! 21: ! 22: static short arrow_bits[]={ ! 23: 0x0004, 0x000E, 0x001F, 0x003E, ! 24: 0x007C, 0x00F8, 0x01F0, 0x83E0, ! 25: 0x87C0, 0xCF80, 0xDF00, 0xFE00, ! 26: 0xFC00, 0xF800, 0xFE00, 0xFF80, ! 27: }; ! 28: Cursor normalcursor; ! 29: ! 30: /* ! 31: * Buffer for keyboard input ! 32: */ ! 33: #define KBDBUFSIZE 128 ! 34: static unsigned char kbdbuffer[KBDBUFSIZE]; ! 35: ! 36: static struct { ! 37: unsigned char *buf; ! 38: unsigned char *in; ! 39: unsigned char *out; ! 40: int cnt; ! 41: int size; ! 42: } kbdbuf = {kbdbuffer, kbdbuffer, kbdbuffer, 0, KBDBUFSIZE}; ! 43: ! 44: initdisplay(argc, argv) ! 45: int argc; ! 46: char *argv[]; ! 47: { ! 48: int i; ! 49: Window win; ! 50: XSetWindowAttributes xswa; ! 51: XSizeHints sizehints; ! 52: Font *df; ! 53: char *font; ! 54: char *geom = 0; ! 55: int flags; ! 56: int width, height, x, y; ! 57: char **ap; ! 58: ! 59: if (!(dpy= XOpenDisplay(NULL))) { ! 60: perror("Cannot open display\n"); ! 61: exit(-1); ! 62: } ! 63: ! 64: if ((font = XGetDefault(dpy, argv[0], "JerqFont")) == NULL) ! 65: font = "fixed"; ! 66: bzero(&sizehints, sizeof(sizehints)); ! 67: ap = argv; i = argc; ! 68: while (i-- > 0) { ! 69: if (!strcmp("-fn", ap[0])) { ! 70: font = ap[1]; ! 71: i--; ap++; ! 72: } ! 73: else if (ap[0][0] == '=') { ! 74: geom = ap[0]; ! 75: flags = XParseGeometry(ap[0], &x, &y, &width, &height); ! 76: if(WidthValue & flags) { ! 77: sizehints.flags |= USSize; ! 78: sizehints.width = width; ! 79: } ! 80: if(HeightValue & flags) { ! 81: sizehints.flags |= USSize; ! 82: sizehints.height = height; ! 83: } ! 84: if(XValue & flags) { ! 85: if(XNegative & flags) ! 86: x = DisplayWidth(dpy, DefaultScreen(dpy)) + x ! 87: - sizehints.width; ! 88: sizehints.flags |= USPosition; ! 89: sizehints.x = x; ! 90: } ! 91: if(YValue & flags) { ! 92: if(YNegative & flags) ! 93: y = DisplayHeight(dpy, DefaultScreen(dpy)) + y ! 94: -sizehints.height; ! 95: sizehints.flags |= USPosition; ! 96: sizehints.y = y; ! 97: } ! 98: } ! 99: ap++; ! 100: } ! 101: ! 102: df = XLoadQueryFont(dpy, font); ! 103: defont = *df; ! 104: P = &sP; ! 105: ! 106: sizehints.width_inc = sizehints.height_inc = 1; ! 107: sizehints.min_width = sizehints.min_height = 20; ! 108: sizehints.flags |= PResizeInc|PMinSize; ! 109: if (!geom) { ! 110: sizehints.width = defont.max_bounds.width * 80; ! 111: sizehints.height = (defont.max_bounds.ascent + ! 112: defont.max_bounds.descent) * 24; ! 113: sizehints.flags |= PSize; ! 114: } ! 115: ! 116: xswa.event_mask = 0; ! 117: bgpix = xswa.background_pixel = WhitePixel(dpy, 0); ! 118: fgpix = xswa.border_pixel = BlackPixel(dpy, 0); ! 119: win = XCreateWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)), ! 120: sizehints.x, sizehints.y, sizehints.width, sizehints.height, ! 121: 2, 0, ! 122: InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)), ! 123: CWEventMask | CWBackPixel | CWBorderPixel, &xswa); ! 124: ! 125: XSetStandardProperties(dpy, win, argv[0], argv[0], ! 126: None, argv, argc, &sizehints); ! 127: ! 128: XSelectInput(dpy, win, ! 129: ButtonPressMask|ButtonReleaseMask|ButtonMotionMask| ! 130: StructureNotifyMask|ExposureMask|KeyPressMask); ! 131: XMapWindow(dpy, win); ! 132: ! 133: colormap = XDefaultColormap(dpy, 0); ! 134: fgcolor.pixel = fgpix; ! 135: bgcolor.pixel = bgpix; ! 136: XQueryColor(dpy, colormap, &fgcolor); ! 137: XQueryColor(dpy, colormap, &bgcolor); ! 138: ! 139: gcs[F_STORE] = XCreateGC(dpy, win, 0, NULL); ! 140: XSetForeground(dpy, gcs[F_STORE], fgpix); ! 141: XSetBackground(dpy, gcs[F_STORE], bgpix); ! 142: XSetFont(dpy, gcs[F_STORE], defont.fid); ! 143: gcs[F_OR] = XCreateGC(dpy, win, 0, NULL); ! 144: XCopyGC(dpy, gcs[F_STORE], GCForeground|GCBackground|GCFont, gcs[F_OR]); ! 145: gcs[F_CLR] = XCreateGC(dpy, win, 0, NULL); ! 146: XCopyGC(dpy, gcs[F_STORE], GCBackground|GCFont, gcs[F_CLR]); ! 147: XSetForeground(dpy, gcs[F_CLR], bgpix); ! 148: gcs[F_XOR] = XCreateGC(dpy, win, 0, NULL); ! 149: XCopyGC(dpy, gcs[F_STORE], GCBackground|GCFont, gcs[F_XOR]); ! 150: XSetForeground(dpy, gcs[F_XOR], AllPlanes); ! 151: XSetFunction(dpy, gcs[F_XOR], GXxor); ! 152: ! 153: display.dr = win; ! 154: Drect.origin.x = 0; ! 155: Drect.origin.y = 0; ! 156: Drect.corner.x = sizehints.width; ! 157: Drect.corner.y = sizehints.height; ! 158: display.rect = Drect; ! 159: while (! P->state & RESHAPED) ! 160: handleinput(); /* wait for exposure */ ! 161: P->state &= ~RESHAPED; ! 162: normalcursor = ToCursor(arrow_bits, arrow_bits, 0, 15); ! 163: cursswitch(&normalcursor); ! 164: ! 165: ! 166: } ! 167: ! 168: Bitmap * ! 169: balloc(r) ! 170: Rectangle r; ! 171: { ! 172: Bitmap *b; ! 173: Pixmap pm; ! 174: b=(Bitmap *)malloc(sizeof (struct Bitmap)); ! 175: pm = XCreatePixmap(dpy, display.dr, r.corner.x-r.origin.x, ! 176: r.corner.y-r.origin.y, DefaultDepth(dpy, 0)); ! 177: b->dr=pm; ! 178: b->rect=r; ! 179: b->flag = BI_PIXMAP; ! 180: return b; ! 181: } ! 182: ! 183: void ! 184: bfree(b) ! 185: Bitmap *b; ! 186: { ! 187: if(b){ ! 188: XFreePixmap(dpy, b->dr); ! 189: free((char *)b); ! 190: } ! 191: } ! 192: ! 193: #define brx(b) (b->rect.origin.x) ! 194: #define bry(b) (b->rect.origin.y) ! 195: ! 196: void ! 197: rectf(b,r,f) ! 198: Bitmap *b; ! 199: Rectangle r; ! 200: Code f; ! 201: { ! 202: register wd=r.corner.x-r.origin.x; ! 203: register ht=r.corner.y-r.origin.y; ! 204: ! 205: if (b->flag & BI_PIXMAP) ! 206: r.origin = sub(r.origin, b->rect.origin); ! 207: XFillRectangle(dpy, b->dr, gcs[f], r.origin.x, r.origin.y, wd, ht); ! 208: } ! 209: ! 210: void ! 211: bitblt(sb,r,db,p,f) ! 212: Bitmap *sb, *db; ! 213: Rectangle r; /* in source bitmap */ ! 214: Point p; /* in dest bitmap */ ! 215: Code f; ! 216: { ! 217: int wd=r.corner.x-r.origin.x; ! 218: int ht=r.corner.y-r.origin.y; ! 219: ! 220: if (sb->flag & BI_PIXMAP) ! 221: r.origin = sub(r.origin, sb->rect.origin); ! 222: if (db->flag & BI_PIXMAP) ! 223: p = sub(p, db->rect.origin); ! 224: XCopyArea(dpy, sb->dr, db->dr, gcs[f], r.origin.x, r.origin.y, ! 225: wd, ht, p.x, p.y); ! 226: } ! 227: ! 228: Point ! 229: string(ft, s, b, p, f) ! 230: XFontStruct *ft; ! 231: char *s; ! 232: Bitmap *b; ! 233: Point p; ! 234: Code f; ! 235: { ! 236: Point p1; ! 237: int i; ! 238: ! 239: i = strlen(s); ! 240: p1 = p; ! 241: p.y += ft->max_bounds.ascent; ! 242: if (b->flag & BI_PIXMAP) ! 243: p = sub(p, b->rect.origin); ! 244: XDrawString(dpy, b->dr, gcs[f], p.x, p.y, s, i); ! 245: p1.x += XTextWidth(ft, s, i); ! 246: return p1; ! 247: } ! 248: ! 249: strwidth(ft,s) ! 250: XFontStruct *ft; ! 251: char *s; ! 252: { ! 253: return XTextWidth(ft, s, strlen(s)); ! 254: } ! 255: ! 256: #ifdef safe ! 257: Point ! 258: Pt(x, y) ! 259: short x, y; ! 260: { ! 261: Point p; ! 262: p.x = x; ! 263: p.y = y; ! 264: return p; ! 265: } ! 266: Rectangle ! 267: SRect(x1, y1, x2, y2) ! 268: short x1, y1, x2, y2; ! 269: { ! 270: Rectangle r; ! 271: r.origin.x = x1; ! 272: r.origin.y = y1; ! 273: r.corner.x = x2; ! 274: r.corner.y = y2; ! 275: return r; ! 276: } ! 277: Rectangle ! 278: Rpt(p1, p2) ! 279: Point p1, p2; ! 280: { ! 281: Rectangle r; ! 282: r.origin = p1; ! 283: r.corner = p2; ! 284: return r; ! 285: } ! 286: #endif safe ! 287: ! 288: Point ! 289: add(a, b) ! 290: Point a, b; ! 291: { ! 292: register short *ap= &a.x, *bp= &b.x; ! 293: *ap++ += *bp++; ! 294: *ap += *bp; ! 295: return a; ! 296: } ! 297: Point ! 298: sub(a, b) ! 299: Point a, b; ! 300: { ! 301: register short *ap= &a.x, *bp= &b.x; ! 302: *ap++ -= *bp++; ! 303: *ap -= *bp; ! 304: return a; ! 305: } ! 306: Rectangle ! 307: inset(r,n) ! 308: Rectangle r; ! 309: register n; ! 310: { ! 311: register short *rp= &r.origin.x; ! 312: *rp++ += n; ! 313: *rp++ += n; ! 314: *rp++ -= n; ! 315: *rp -= n; ! 316: return r; ! 317: } ! 318: Rectangle ! 319: raddp(r, p) ! 320: Rectangle r; ! 321: Point p; ! 322: { ! 323: register short *rp= &r.origin.x, *pp= &p.x; ! 324: *rp++ += *pp++; ! 325: *rp++ += *pp--; ! 326: *rp++ += *pp++; ! 327: *rp += *pp; ! 328: return r; ! 329: } ! 330: eqpt(p, q) ! 331: Point p, q; ! 332: { ! 333: register long *pp=(long *)&p, *qq=(long *)&q; ! 334: return *pp==*qq; ! 335: } ! 336: ptinrect(p, r) ! 337: Point p; ! 338: Rectangle r; ! 339: { ! 340: return(p.x>=r.origin.x && p.x<r.corner.x ! 341: && p.y>=r.origin.y && p.y<r.corner.y); ! 342: } ! 343: ! 344: /* ! 345: * Convert a blit style texture to a pixmap which can be used in tiling ! 346: * or cursor operations. ! 347: */ ! 348: Pixmap ToPixmap(bits) ! 349: short bits[]; ! 350: { ! 351: static XImage *im; ! 352: Pixmap pm; ! 353: ! 354: if (!im) ! 355: im = XCreateImage(dpy, XDefaultVisual(dpy, 0), 1, ! 356: XYBitmap, 0, (char *)bits, 16, 16, 8, 2); ! 357: else ! 358: im->data = (char *)bits; ! 359: pm = XCreatePixmap(dpy, display.dr, 16, 16, 1); ! 360: XPutImage(dpy, pm, gcs[F_STORE], im, 0, 0, 0, 0, 16, 16); ! 361: return pm; ! 362: } ! 363: ! 364: Cursor ToCursor(source, mask, hotx, hoty) ! 365: short source[], mask[]; ! 366: { ! 367: Pixmap sp, mp; ! 368: Cursor c; ! 369: ! 370: sp = ToPixmap(source); ! 371: mp = ToPixmap(mask); ! 372: c = XCreatePixmapCursor(dpy, sp, mp, &fgcolor, &bgcolor, hotx, hoty); ! 373: XFreePixmap(dpy, sp); ! 374: XFreePixmap(dpy, mp); ! 375: return(c); ! 376: } ! 377: ! 378: cursset(p) ! 379: Point p; ! 380: { ! 381: XWarpPointer(dpy, display.dr, display.dr, mouse.xy.x, mouse.xy.y, ! 382: display.rect.corner.x, display.rect.corner.y, p.x, p.y); ! 383: mouse.xy.x = p.x; ! 384: mouse.xy.y = p.y; ! 385: } ! 386: ! 387: jnap(i) ! 388: { ! 389: handleinput(); ! 390: } ! 391: ! 392: kbdchar() ! 393: { ! 394: int i; ! 395: ! 396: if (!kbdbuf.cnt) ! 397: return -1; ! 398: i = *kbdbuf.out++; ! 399: if (kbdbuf.out == &kbdbuf.buf[kbdbuf.size]) ! 400: kbdbuf.out = kbdbuf.buf; ! 401: if (--kbdbuf.cnt == 0) ! 402: P->state &= ~KBD; ! 403: return(i); ! 404: } ! 405: ! 406: #undef button ! 407: handleinput() ! 408: { ! 409: XEvent ev; ! 410: unsigned char s[16], *cp; ! 411: int n; ! 412: ! 413: XNextEvent(dpy, &ev); ! 414: switch (ev.type) { ! 415: case ButtonPress: ! 416: mouse.buttons |= (8 >> ev.xbutton.button); ! 417: mouse.xy.x = ev.xbutton.x; ! 418: mouse.xy.y = ev.xbutton.y; ! 419: mouse.time = ev.xbutton.time; ! 420: break; ! 421: case ButtonRelease: ! 422: mouse.buttons &= ~(8 >> ev.xbutton.button); ! 423: mouse.xy.x = ev.xbutton.x; ! 424: mouse.xy.y = ev.xbutton.y; ! 425: mouse.time = ev.xbutton.time; ! 426: break; ! 427: case MotionNotify: ! 428: mouse.xy.x = ev.xmotion.x; ! 429: mouse.xy.y = ev.xmotion.y; ! 430: break; ! 431: case MapNotify: ! 432: case NoExpose: ! 433: break; ! 434: case ConfigureNotify: ! 435: if (display.rect.corner.x != ev.xconfigure.width || ! 436: display.rect.corner.y != ev.xconfigure.height) { ! 437: display.rect.corner.x = ev.xconfigure.width; ! 438: display.rect.corner.y = ev.xconfigure.height; ! 439: Drect = display.rect; ! 440: } ! 441: break; ! 442: case Expose: ! 443: if (ev.xexpose.count == 0) { ! 444: rectf(&display, Drect, F_CLR); ! 445: P->state |= RESHAPED; ! 446: } ! 447: break; ! 448: case KeyPress: ! 449: mouse.xy.x = ev.xkey.x; ! 450: mouse.xy.y = ev.xkey.y; ! 451: mouse.time = ev.xkey.time; ! 452: n = XLookupString(&ev, s, sizeof(s), NULL, NULL); ! 453: if (n > 0) { ! 454: cp = s; ! 455: P->state |= KBD; ! 456: do { ! 457: if (kbdbuf.cnt == kbdbuf.size) ! 458: break; ! 459: *kbdbuf.in++ = *cp++; ! 460: kbdbuf.cnt++; ! 461: if (kbdbuf.in == &kbdbuf.buf[kbdbuf.size]) ! 462: kbdbuf.in = kbdbuf.buf; ! 463: } while (--n); ! 464: } ! 465: break; ! 466: default: ! 467: break; ! 468: } ! 469: } ! 470: #define button(i) (mouse.buttons&(8>>i)) ! 471: ! 472: char * ! 473: gcalloc(nbytes, where) ! 474: unsigned long nbytes; ! 475: char **where; ! 476: { ! 477: *where=(char *)alloc(nbytes); ! 478: return *where; ! 479: } ! 480: void ! 481: gcfree(s) ! 482: char *s; ! 483: { ! 484: free(s); ! 485: } ! 486: ! 487: min(a,b) ! 488: { ! 489: return (a<b? a: b); ! 490: } ! 491: max(a,b) ! 492: { ! 493: return (a>b? a: b); ! 494: } ! 495: ! 496: /* Form a circle of radius r centered at x1,y1 ! 497: */ ! 498: circle(b,p,r,f) ! 499: Bitmap *b; ! 500: Point p; ! 501: { ! 502: unsigned int diam = 2*r; ! 503: if (b->flag & BI_PIXMAP) ! 504: p = sub(p, b->rect.origin); ! 505: p = sub(p, Pt(r,r)); ! 506: XDrawArc(dpy, b->dr, gcs[f], p.x, p.y, diam, diam, 0, 23040/* 360 deg */); ! 507: } ! 508: ! 509: Cursor * ! 510: cursswitch(cp) ! 511: Cursor *cp; ! 512: { ! 513: static Cursor *prev = &normalcursor; ! 514: Cursor *ret = prev; ! 515: if (!cp) ! 516: cp = &normalcursor; ! 517: XDefineCursor(dpy, display.dr, *cp); ! 518: prev = cp; ! 519: return ret; ! 520: } ! 521: /* Fill a disc of radius r centered at x1,y1 ! 522: */ ! 523: disc(b, p, r, f) ! 524: Bitmap *b; ! 525: Point p; ! 526: int r; ! 527: Code f; ! 528: { ! 529: unsigned int diam = 2*r; ! 530: if (b->flag & BI_PIXMAP) ! 531: p = sub(p, b->rect.origin); ! 532: p = sub(p, Pt(r,r)); ! 533: XFillArc(dpy, b->dr, gcs[f], p.x, p.y, diam, diam, 0, 23040/* 360 deg */); ! 534: } ! 535: ! 536: typedef struct String{ ! 537: char *s; /* pointer to string */ ! 538: short n; /* number used, no terminal null */ ! 539: short size; /* size of allocated area */ ! 540: } String; ! 541: ! 542: getmuxbuf(pmb) ! 543: String *pmb; ! 544: { ! 545: char *ans; ! 546: int n; ! 547: ans=XFetchBytes(dpy, &n); ! 548: pmb->size=pmb->n=n; ! 549: gcalloc(pmb->size, &(pmb->s)); ! 550: strncpy(pmb->s, ans, n); ! 551: free(ans); ! 552: } ! 553: ! 554: #define UP 0 ! 555: #define DOWN 1 ! 556: ! 557: static short boxcurs_bits[] = { ! 558: 0x43FF, 0xE001, 0x7001, 0x3801, 0x1D01, 0x0F01, 0x8701, 0x8F01, ! 559: 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0xFFFF, ! 560: }; ! 561: static Cursor boxcurs; ! 562: ! 563: buttons(updown) ! 564: { ! 565: while((button123()!=0) != updown) ! 566: jnap(2); ! 567: } ! 568: ! 569: Rectangle ! 570: canon(p1, p2) ! 571: Point p1, p2; ! 572: { ! 573: Rectangle r; ! 574: r.origin.x = min(p1.x, p2.x); ! 575: r.origin.y = min(p1.y, p2.y); ! 576: r.corner.x = max(p1.x, p2.x); ! 577: r.corner.y = max(p1.y, p2.y); ! 578: return(r); ! 579: } ! 580: ! 581: static outline(r) ! 582: Rectangle r; ! 583: { ! 584: XPoint p[5], *pp; ! 585: ! 586: pp = p; ! 587: pp->x = r.corner.x; pp->y = r.origin.y; pp++; ! 588: pp->x = r.corner.x; pp->y = r.corner.y; pp++; ! 589: pp->x = r.origin.x; pp->y = r.corner.y; pp++; ! 590: pp->x = r.origin.x; pp->y = r.origin.y; pp++; ! 591: pp->x = r.corner.x; pp->y = r.origin.y; pp++; ! 592: XDrawLines(dpy, display.dr, gcs[F_XOR], p, 5, CoordModeOrigin); ! 593: } ! 594: ! 595: Rectangle ! 596: getrectb(n) ! 597: int n; ! 598: { ! 599: Rectangle r; ! 600: Point p1, p2; ! 601: ! 602: if (!boxcurs) ! 603: boxcurs = ToCursor(boxcurs_bits, boxcurs_bits, 8, 8); ! 604: cursswitch(&boxcurs); ! 605: buttons(UP); ! 606: buttons(DOWN); ! 607: if(!(mouse.buttons&n)){ ! 608: r.origin.x=r.origin.y=r.corner.x=r.corner.y=0; ! 609: buttons(UP); ! 610: goto Return; ! 611: } ! 612: p1=mouse.xy; ! 613: p2=p1; ! 614: r=canon(p1, p2); ! 615: outline(r); ! 616: for(; mouse.buttons&n; jnap(2)){ ! 617: outline(r); ! 618: p2=mouse.xy; ! 619: r=canon(p1, p2); ! 620: outline(r); ! 621: } ! 622: outline(r); /* undraw for the last time */ ! 623: Return: ! 624: cursswitch(0); ! 625: return r; ! 626: } ! 627: ! 628: Rectangle ! 629: getrect(n) ! 630: { ! 631: return getrectb(8>>n); ! 632: } ! 633: ! 634: #define scale(x, inmin, inmax, outmin, outmax)\ ! 635: (outmin + muldiv(x-inmin,outmax-outmin,inmax-inmin)) ! 636: ! 637: #define bound(x, low, high) min(high, max( low, x )) ! 638: ! 639: #define DISPLAY 16 ! 640: #define DELTA 6 ! 641: #define BARWIDTH 18 ! 642: ! 643: static char **table; ! 644: static char * ! 645: tablegen(i) ! 646: { ! 647: return table[i]; ! 648: } ! 649: ! 650: menuhit(m, but) ! 651: register Menu *m; ! 652: { ! 653: register int width, i, j, top, newtop, hit, newhit, items, lines, length; ! 654: Point p, q, savep, baro, barc; ! 655: Rectangle sr, tr, mr; /* scroll, text, menu */ ! 656: register Bitmap *b; ! 657: register char *s, *(*generator)(), *from, *to; ! 658: char fill[64]; ! 659: Font *font = &defont; ! 660: int spacing = font->max_bounds.ascent + font->max_bounds.descent; ! 661: ! 662: #define sro sr.origin ! 663: #define src sr.corner ! 664: #define tro tr.origin ! 665: #define trc tr.corner ! 666: #define mro mr.origin ! 667: #define mrc mr.corner ! 668: ! 669: generator = (table=m->item) ? tablegen : m->generator; ! 670: p = mouse.xy; ! 671: length = width = items = 0; ! 672: for( ; s=(*generator)(items); ++items) { ! 673: length = max(length, strlen(s)); ! 674: width = max(width, strwidth(font,s)); ! 675: } ! 676: if(items == 0){ ! 677: while(button(but)); ! 678: return -1; ! 679: } ! 680: width += 10; ! 681: sro.x = sro.y = src.x = tro.x = mro.x = mro.y = 0; ! 682: if(items <= DISPLAY) ! 683: lines = items; ! 684: else{ ! 685: lines = DISPLAY; ! 686: tro.x = src.x = BARWIDTH; ! 687: sro.x = sro.y = 1; ! 688: } ! 689: tro.y = 1; ! 690: mrc = trc = add(Pt(tro.x, mro.y), Pt(width, min(items, lines)*spacing+2)); ! 691: trc.y = src.y = mrc.y-1; ! 692: newtop = bound(m->prevtop, 0, items-lines); ! 693: p.y -= bound(m->prevhit, 0, lines-1)*spacing+spacing/2; ! 694: p.x = bound(p.x-(src.x+width/2), 0, display.rect.corner.x-mrc.x); ! 695: p.y = bound(p.y, 0, display.rect.corner.y-mrc.y); ! 696: sr = raddp(sr, p); ! 697: tr = raddp(tr, p); ! 698: mr = raddp(mr, p); ! 699: b = balloc(mr); ! 700: if(b) ! 701: bitblt(&display, mr, b, mro, F_STORE); ! 702: rectf(&display, mr, F_OR); ! 703: PaintMenu: ! 704: rectf(&display, inset(mr, 1), F_CLR); ! 705: top = newtop; ! 706: if(items > DISPLAY){ ! 707: baro.y = scale(top, 0, items, sro.y, src.y); ! 708: baro.x = sr.origin.x; ! 709: barc.y = scale(top+DISPLAY, 0, items, sro.y, src.y); ! 710: barc.x = sr.corner.x; ! 711: rectf(&display, Rpt(baro,barc), F_XOR); ! 712: } ! 713: for(p=tro, i=top; i < min(top+lines, items); ++i){ ! 714: q = p; ! 715: from = generator(i); ! 716: for(to = &fill[0]; *from; ++from) ! 717: if(*from & 0x80) ! 718: for(j=length-(strlen(from+1)+(to-&fill[0])); j-->0;) ! 719: *to++ = *from & 0x7F; ! 720: else ! 721: *to++ = *from; ! 722: *to = '\0'; ! 723: q.x += (width-strwidth(font,fill))/2; ! 724: string(font, fill, &display, q, F_XOR); ! 725: p.y += spacing; ! 726: } ! 727: savep = mouse.xy; ! 728: for(newhit = hit = -1; button(but); jnap(2)){ ! 729: if(ptinrect(p = mouse.xy, sr)){ ! 730: if(ptinrect(savep,tr)){ ! 731: p.y = (baro.y+barc.y)/2; ! 732: cursset(p); ! 733: } ! 734: newtop = scale(p.y, sro.y, src.y, 0, items); ! 735: newtop = bound(newtop-DISPLAY/2, 0, items-DISPLAY); ! 736: if(newtop != top) ! 737: goto PaintMenu; ! 738: }else if(ptinrect(savep,sr)){ ! 739: register dx, dy; ! 740: if(abs(dx = p.x-savep.x) < DELTA) ! 741: dx = 0; ! 742: if(abs(dy = p.y-savep.y) < DELTA) ! 743: dy = 0; ! 744: if(abs(dy) >= abs(dx)) ! 745: dx = 0; ! 746: else ! 747: dy = 0; ! 748: cursset(p = add(savep, Pt(dx,dy))); ! 749: } ! 750: savep = p; ! 751: newhit = -1; ! 752: if(ptinrect(p, tr)){ ! 753: newhit = bound((p.y-tro.y)/spacing, 0, lines-1); ! 754: if(newhit!=hit && hit>=0 ! 755: && abs(tro.y+spacing*newhit+spacing/2-p.y) > spacing/3) ! 756: newhit = hit; ! 757: } ! 758: if(newhit != hit){ ! 759: flip(tr, hit, spacing); ! 760: flip(tr, hit = newhit, spacing); ! 761: } ! 762: if(newhit==0 && top>0){ ! 763: newtop = top-1; ! 764: p.y += spacing; ! 765: cursset(p); ! 766: goto PaintMenu; ! 767: } ! 768: if(newhit==DISPLAY-1 && top<items-lines){ ! 769: newtop = top+1; ! 770: p.y -= spacing; ! 771: cursset(p); ! 772: goto PaintMenu; ! 773: } ! 774: } ! 775: if(b){ ! 776: bitblt(b, b->rect, &display, b->rect.origin, F_STORE); ! 777: bfree(b); ! 778: } ! 779: if(hit>=0){ ! 780: m->prevhit = hit; ! 781: m->prevtop = top; ! 782: return hit+top; ! 783: }else ! 784: return -1; ! 785: } ! 786: ! 787: static ! 788: flip(r,n,spacing) ! 789: Rectangle r; ! 790: { ! 791: if(n<0) ! 792: return; ! 793: ++r.origin.x; ! 794: r.corner.y = (r.origin.y += spacing*n) + spacing; ! 795: --r.corner.x; ! 796: rectf(&display, r, F_XOR); ! 797: } ! 798: ! 799: void ! 800: point(b,p,f) ! 801: Bitmap *b; ! 802: Point p; ! 803: Code f; ! 804: { ! 805: if (b->flag & BI_PIXMAP) ! 806: p = sub(p, b->rect.origin); ! 807: XDrawPoint(dpy, b->dr, gcs[f], p.x, p.y); ! 808: } ! 809: ! 810: #define PBSIZE 100 ! 811: ! 812: static XPoint xp[PBSIZE]; ! 813: static xpcnt; ! 814: static Code fc; ! 815: static ispixmap; ! 816: static Bitmap *bitm; ! 817: ! 818: #define flushpt() if (xpcnt) flushpoints(); ! 819: ! 820: points(p) ! 821: Point p; ! 822: { ! 823: register XPoint *x; ! 824: ! 825: if (ispixmap) ! 826: p = sub(p, bitm->rect.origin); ! 827: x = &xp[xpcnt]; ! 828: x->x = p.x; ! 829: x->y = p.y; ! 830: if (++xpcnt == PBSIZE) ! 831: flushpoints(); ! 832: } ! 833: ! 834: initpoints(b, f) ! 835: Bitmap *b; ! 836: Code f; ! 837: { ! 838: if (b->flag & BI_PIXMAP) ! 839: ispixmap = 1; ! 840: else ! 841: ispixmap = 0; ! 842: bitm = b; ! 843: fc = f; ! 844: } ! 845: ! 846: endpoints() ! 847: { ! 848: flushpt(); ! 849: XSync(dpy, 0); ! 850: } ! 851: ! 852: flushpoints() ! 853: { ! 854: if (xpcnt) { ! 855: XDrawPoints(dpy, bitm->dr, gcs[fc], xp, xpcnt, CoordModeOrigin); ! 856: xpcnt = 0; ! 857: } ! 858: } ! 859: ! 860: /* ! 861: * Buffer for keyboard input ! 862: */ ! 863: #define RCVBUFSIZE 1024 ! 864: ! 865: static unsigned char rcvbuffer[RCVBUFSIZE]; ! 866: ! 867: static struct { ! 868: unsigned char *buf; ! 869: unsigned char *in; ! 870: unsigned char *out; ! 871: int cnt; ! 872: int size; ! 873: }rcvbuf = { rcvbuffer, rcvbuffer, rcvbuffer, 0, RCVBUFSIZE }; ! 874: ! 875: ! 876: rcvchar() ! 877: { ! 878: int i; ! 879: ! 880: if (!rcvbuf.cnt) ! 881: return -1; ! 882: i = *rcvbuf.out++; ! 883: if (rcvbuf.out == &rcvbuf.buf[rcvbuf.size]) ! 884: rcvbuf.out = rcvbuf.buf; ! 885: if (--rcvbuf.cnt == 0) ! 886: P->state &= ~RCV; ! 887: return(i); ! 888: } ! 889: ! 890: rcvfill() ! 891: { ! 892: register i; ! 893: ! 894: if (rcvbuf.cnt == rcvbuf.size) ! 895: return; ! 896: if (rcvbuf.in < rcvbuf.out) ! 897: i = rcvbuf.out - rcvbuf.in; ! 898: else ! 899: i = &rcvbuf.buf[rcvbuf.size] - rcvbuf.in; ! 900: i = read(0, rcvbuf.in, i); ! 901: if (i <= 0) ! 902: return; ! 903: P->state |= RCV; ! 904: rcvbuf.cnt += i; ! 905: rcvbuf.in += i; ! 906: if (rcvbuf.in == &rcvbuf.buf[rcvbuf.size]) ! 907: rcvbuf.in = rcvbuf.buf; ! 908: } ! 909: ! 910: void ! 911: request(r) ! 912: int r; ! 913: { ! 914: int i=1; ! 915: if (r & RCV) { ! 916: /* need non-blocking I/O on stdout */ ! 917: #ifdef BSD ! 918: ioctl(1, FIONBIO, &i); ! 919: #else ! 920: ioctl(1, FIOWNBLK, 0); ! 921: #endif ! 922: } ! 923: /* for now, assume MOUSE|KBD requested */ ! 924: } ! 925: ! 926: void ! 927: segment(b,p,q,f) ! 928: Bitmap *b; ! 929: Point p, q; ! 930: Code f; ! 931: { ! 932: if (b->flag & BI_PIXMAP) { ! 933: p = sub(p, b->rect.origin); ! 934: q = sub(q, b->rect.origin); ! 935: } ! 936: XDrawLine(dpy, b->dr, gcs[f], p.x, p.y, q.x, q.y); ! 937: } ! 938: ! 939: #ifndef BSD ! 940: #define EWOULDBLOCK EBUSY ! 941: #endif ! 942: ! 943: sendnchars(n,p) ! 944: char *p; ! 945: int n; ! 946: { ! 947: int i; ! 948: int maxfd, rmask, wmask; ! 949: ! 950: while (n) { ! 951: i = write(1, p, n); ! 952: if (i > 0) { ! 953: n -= i; ! 954: p += i; ! 955: continue; ! 956: } ! 957: if (i < 0 && errno == EWOULDBLOCK) { ! 958: maxfd = dpy->fd + 1; ! 959: do { ! 960: while (XPending(dpy)) ! 961: handleinput(); ! 962: rmask = (1 << dpy->fd) | 1; ! 963: wmask = 2; ! 964: #ifdef BSD ! 965: select(maxfd, &rmask, &wmask, 0, 0); ! 966: #else ! 967: select(maxfd, &rmask, &wmask, 0x6fffffff); ! 968: #endif ! 969: if (rmask & 1) ! 970: rcvfill(); ! 971: if (rmask & (1 << dpy->fd)) ! 972: handleinput(); ! 973: } while (!wmask); ! 974: } ! 975: else ! 976: exit(1); ! 977: } ! 978: } ! 979: #define MAXROOT 0xb504 ! 980: sqrt(x) ! 981: register long x; ! 982: { ! 983: register long high=MAXROOT; ! 984: register long low=0; ! 985: register long current=MAXROOT/2; ! 986: if(x<=0) ! 987: return 0; ! 988: if(x>=MAXROOT*MAXROOT) ! 989: return(MAXROOT); ! 990: while(high>low+1){ ! 991: if(current*current==x) ! 992: return (current); ! 993: if(current*current>x) ! 994: high=current; ! 995: else ! 996: low=current; ! 997: current=(high+low)>>1; ! 998: } ! 999: return(current); ! 1000: } ! 1001: ! 1002: wait(resource) ! 1003: { ! 1004: int maxfd, smask, i; ! 1005: ! 1006: maxfd = dpy->fd + 1; ! 1007: for(;;) { ! 1008: if (P->state & resource) ! 1009: break; ! 1010: if (XPending(dpy)) ! 1011: goto xin; ! 1012: if (resource & CPU) ! 1013: break; ! 1014: smask = (1 << dpy->fd) | 1; ! 1015: #ifdef BSD ! 1016: select(maxfd, &smask, 0, 0, 0); ! 1017: #else ! 1018: select(maxfd, &smask, 0, 0x6fffffff); ! 1019: #endif ! 1020: if (smask & 1) ! 1021: rcvfill(); ! 1022: if (smask & (1 << dpy->fd)) { ! 1023: xin: ! 1024: handleinput(); ! 1025: /* We always have the mouse and cpu */ ! 1026: if (resource & (MOUSE|CPU)) ! 1027: break; ! 1028: } ! 1029: } ! 1030: return P->state; ! 1031: } ! 1032: ! 1033: int ! 1034: own() ! 1035: { ! 1036: return P->state|MOUSE; ! 1037: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.