Annotation of researchv10no/cmd/movie/libj.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.