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

1.1       root        1: #include <suntool/sunview.h>
                      2: #include <suntool/canvas.h>
                      3: #include <fcntl.h>
                      4: 
                      5: 
                      6: /* from jerq.h... */
                      7: 
                      8: typedef struct Point {
                      9:        short   x;
                     10:        short   y;
                     11: } Point;
                     12: 
                     13: int muldiv(x,y,d) { return (x * y) / d; }
                     14: 
                     15: Point pt(x, y) { Point p; p.x = x; p.y = y; return p; }
                     16: Point Pt(x, y) { Point p; p.x = x; p.y = y; return p; }
                     17: Point add(p1, p2) Point p1, p2; { p1.x += p2.x; p1.y += p2.y; return p1; }
                     18: Point sub(p1, p2) Point p1, p2; { p1.x -= p2.x; p1.y -= p2.y; return p1; }
                     19: 
                     20: typedef struct Rectangle {
                     21:        Point origin;
                     22:        Point corner;
                     23: } Rectangle;
                     24: 
                     25: Rectangle raddp(r, p) Rectangle r; Point p;
                     26: {
                     27:        r.origin = add(r.origin, p);
                     28:        r.corner = add(r.corner, p);
                     29:        return r;
                     30: }
                     31: 
                     32: Rectangle Rpt(p1,p2) Point p1, p2;
                     33: {
                     34:        Rectangle r;
                     35:        r.origin.x = p1.x; r.origin.y = p1.y;
                     36:        r.corner.x = p2.x; r.corner.y = p2.y;
                     37:        return r;
                     38: }
                     39: 
                     40: Rectangle Rect4(x1,y1,x2,y2)
                     41: {
                     42:        Rectangle r;
                     43:        r.origin.x = x1; r.origin.y = y1;
                     44:        r.corner.x = x2; r.corner.y = y2;
                     45:        return r;
                     46: }
                     47: 
                     48: Rectangle inset(r, n) Rectangle r;
                     49: {
                     50:        r.origin.x += n; r.origin.y += n;
                     51:        r.corner.x -= n; r.corner.y -= n;
                     52:        return r;
                     53: }
                     54: 
                     55: int eqpt(p1, p2) Point p1, p2; { return p1.x == p2.x && p1.y == p2.y; }
                     56: 
                     57: Rectangle      Drect;
                     58: #define        Do      Drect.origin
                     59: #define        Dc      Drect.corner
                     60: 
                     61: Rectangle      getrect23();
                     62: Rectangle      display;        /* not used */
                     63: int    defont;
                     64: 
                     65: /* bitblt function codes */
                     66: #define        F_STORE (PIX_SRC)       /* target = source */
                     67: #define        F_OR    (PIX_SRC|PIX_DST)       /* target |= source */
                     68: #define        F_CLR   (PIX_NOT(PIX_SRC)&(PIX_DST))    /* target &= ~source */
                     69: #define        F_XOR   (PIX_SRC^PIX_DST)       /* target ^= source */
                     70: 
                     71: Cursor *cursor,normalcursor,bullseye,coffeecup,sweep,deadmouse,lockarrow;
                     72: 
                     73: #include "anim.h"
                     74: 
                     75: typedef unsigned char uchar;
                     76: 
                     77: #define        PUT     { char buf[100]; sprintf(buf,
                     78: #define        END     ); putstring(buf); }
                     79: #define        readpoint(p)    { p.x = readint(); p.y = readint(); }
                     80: #define        readpair(p1,p2) { readpoint(p1); readpoint(p2); }
                     81: 
                     82: /* holds data for all input objects */
                     83: 
                     84: unsigned memsize;              /* bytes */
                     85: uchar  *inbuf;                 /* input collected here */
                     86: uchar  *input;                 /* leave a null at front */
                     87: uchar  *inp;                   /* next free slot in input */
                     88: int    nobj    = 0;            /* number of objects in input */
                     89: int    overflow = 0;           /* 1 => too much input */
                     90: 
                     91: long   slot[2000];             /* slots */
                     92: int    slotnum;
                     93: 
                     94: extern uchar   *savechar(), *draw_obj(), *click_obj(), *step_obj();
                     95: extern uchar   *prev_obj(), *next_obj();
                     96: 
                     97: extern Point readpt(), fetchpt(), scalept();
                     98: int    xmax, ymax;
                     99: 
                    100: #define        MAXVIEW 10
                    101: char   *viewname[MAXVIEW];
                    102: typedef struct {
                    103:        Rectangle vr;
                    104:        int     xmax;
                    105:        int     ymax;
                    106: } View;
                    107: View   viewpt[MAXVIEW];
                    108: int    curview = 0;
                    109: int    nview   = 0;
                    110: #define        INSET   4       /* picture inset from frame */
                    111: 
                    112: #define        AW      8       /* arrowhead width and height */
                    113: #define        AH      10
                    114: 
                    115: #define        MARGINPCT       6
                    116: int    margin  = MARGINPCT;    /* percent margin around edges */
                    117: 
                    118: #define        MAXCLICK        20
                    119: char   *clickname[MAXCLICK];           /* click names */
                    120: int    clickval[MAXCLICK];             /* 1 => click on this */
                    121: int    clicking = 0;                   /* number of active clicks */
                    122: int    nclick  = 0;
                    123: 
                    124: char   buf[200];
                    125: char   *pbuf;
                    126: 
                    127: #define        Again   0               /* Menu items -- must be 0.. */
                    128: #define        Faster  (Again+1)
                    129: #define        Slower  (Faster+1)
                    130: #define        Step    (Slower+1)
                    131: #define        Forward (Step+1)
                    132: #define        Fatter  (Forward+1)
                    133: #define        Thinner (Fatter+1)
                    134: #define        Xor     (Thinner+1)
                    135: #define        File    (Xor+1)
                    136: #define        Quit    (File+1)                /* ... down this far */
                    137: #define        Backward (Quit+1)       /* subsequent names are arbitrary */
                    138: #define        Proceed (Backward+1)
                    139: #define        Hit     (Proceed+1)
                    140: #define FreeRun        (Hit+1)
                    141: 
                    142: int    delay           = 1;    /* how long to delay between things */
                    143: int    singstep        = 0;    /* single step if 1 */
                    144: #define        Fwd     1
                    145: #define        Back    0
                    146: int    dir             = Fwd;  /* 1 = fwd, 0 = backward */
                    147: int    fatness         = 0;    /* n => draw with 2n+1 lines */
                    148: int    xormode         = F_XOR;        /* otherwise OR/CLR */
                    149: 
                    150: char   *m3[]           = { "again", "faster", "slower", "1 step", "backward",
                    151:                            "fatter", "thinner", "or mode", "new file", "Quit?", 0 };
                    152: char   *stepmenu[]     = { "1 step", "run" };
                    153: char   *dirmenu[]      = { "forward", "backward" };
                    154: char   *modemenu[]     = { "or mode", "xor mode" };
                    155: 
                    156: char *m3gen(n)
                    157: {
                    158:        static char buf[20][20];
                    159:        extern int delay;
                    160: 
                    161:        if (n < 0 || n > Quit)
                    162:                return 0;
                    163:        else if (n == Faster) {
                    164:                sprintf(buf[n], "faster %d", delay);
                    165:                return buf[n];
                    166:        } else if (n == Slower) {
                    167:                sprintf(buf[n], "slower %d", delay);
                    168:                return buf[n];
                    169:        } else if (n == Step) {
                    170:                return stepmenu[singstep];
                    171:        } else if (n == Forward) {
                    172:                return dirmenu[dir];
                    173:        } else if (n == Fatter) {
                    174:                sprintf(buf[n], "fatter %d", fatness+1);
                    175:                return buf[n];
                    176:        } else if (n == Thinner) {
                    177:                sprintf(buf[n], "thinner %d", fatness+1);
                    178:                return buf[n];
                    179:        } else if (n == Xor) {
                    180:                return xormode == F_XOR ? modemenu[0] : modemenu[1];
                    181:        } else
                    182:                return m3[n];
                    183: }
                    184: 
                    185: char *m2gen(n)
                    186: {
                    187:        static char buf[20][50];
                    188: 
                    189:        if (n < 0 || n >= nview+nclick)
                    190:                return 0;
                    191:        else if (n < nview) {
                    192:                sprintf(buf[n], "view %s", viewname[n]);
                    193:                return buf[n];
                    194:        } else {
                    195:                sprintf(buf[n], "click %s%s",
                    196:                        clickname[n-nview], clickval[n-nview] ? "*" : "");
                    197:                return buf[n];
                    198:        }
                    199: }
                    200: 
                    201: Menu   mbut3;
                    202: Menu   mbut2;
                    203: int    last_hit;
                    204: int    last_but;
                    205: 
                    206: void   inevent();
                    207: 
                    208: Canvas canvas;
                    209: Pixwin *pw;
                    210: int    canvasfd;
                    211: int    height, width;  /* screen window */
                    212: 
                    213: init_params()
                    214: {
                    215:        int i;
                    216: 
                    217:        for (i = 0; i < MAXCLICK; i++)
                    218:                if (clickname[i]) {
                    219:                        free(clickname[i]);
                    220:                        clickname[i] = 0;
                    221:                        clickval[i] = 0;
                    222:                }
                    223:        for (i = 0; i < MAXVIEW; i++)
                    224:                if (viewname[i]) {
                    225:                        free(viewname[i]);
                    226:                        viewname[i] = 0;
                    227:                }
                    228:        nclick = nview = curview = nobj = clicking = overflow = slotnum = 0;
                    229: }
                    230: 
                    231: main()
                    232: {
                    233:        int i, n;
                    234:        Frame baseframe;
                    235: 
                    236:        baseframe = window_create(NULL, FRAME, FRAME_LABEL, "Anim",
                    237:                WIN_ERROR_MSG, "Can't create Anim base window", 0);
                    238:        canvas = window_create(baseframe, CANVAS, 0);
                    239:        pw = canvas_pixwin(canvas);
                    240:        canvasfd = (int)window_get(canvas, WIN_FD);
                    241:        fcntl(canvasfd, F_SETFL, FNDELAY); /* allow nonblocking reads */
                    242:        width = (int)window_get(canvas, CANVAS_WIDTH);
                    243:        height = (int)window_get(canvas, CANVAS_HEIGHT);
                    244:        Drect.origin = pt(0,0);
                    245:        Drect.corner = add(Drect.origin, pt(width,height));
                    246: 
                    247:        do_rcv();
                    248: 
                    249:        initmenus();
                    250:        initcursors();
                    251:        /* get these events by default: LOC_WINENTER, LOC_WINEXIT, LOC_MOVE,
                    252:                 MS_LEFT, MS_MIDDLE, MS_RIGHT           */
                    253:        window_set(canvas,
                    254:                WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS,
                    255:                WIN_EVENT_PROC, inevent, 0);
                    256:        window_main_loop(baseframe);
                    257:        send1char(P_QUIT); /* tell host part we're done */
                    258:        flushproto();
                    259: }
                    260: 
                    261: initmenus()
                    262: {
                    263:        int i;
                    264:        char *s;
                    265: 
                    266:        mbut2 = menu_create(MENU_DEFAULT, 1, 0);
                    267:        for (i = 0; s = m2gen(i); i++)
                    268:                menu_set(mbut2, MENU_STRING_ITEM, s, i+1, 0);
                    269:        mbut3 = menu_create(MENU_DEFAULT, 1, 0);
                    270:        for (i = 0; m3[i]; i++)
                    271:                menu_set(mbut3, MENU_STRING_ITEM, m3[i], i+1, 0);
                    272: }
                    273: 
                    274: char kbdline[100];     /* collect keyboard input here */
                    275: int kbdi = 0;          /* kbdline index */
                    276: 
                    277: void inevent(c, e)
                    278:        Canvas c;
                    279:        Event *e;
                    280: {
                    281:        int n, i, eid, ch;
                    282:        char *s;
                    283: 
                    284:        eid = event_id(e);
                    285:        switch (eid) {
                    286:        default:
                    287:                if (!event_is_ascii(e))
                    288:                        return;
                    289:                if (eid != '\n' && eid != '\r') {       /* which do we get? */
                    290:                        if (eid == '\b' && kbdi > 0)
                    291:                                kbdi--;
                    292:                        else
                    293:                                kbdline[kbdi++] = eid;
                    294:                        kbdline[kbdi] = '\0';
                    295:                        putstring(kbdline);
                    296:                        return;
                    297:                }
                    298:                kbdline[kbdi] = '\0';
                    299:                kbdi = 0;
                    300:                /* now we have a filename */
                    301:                send1char(P_FILE);
                    302:                sendstring(kbdline);
                    303:                if ((ch = readchar()) == P_FILE) {
                    304:                        do_rcv();
                    305:                } else {
                    306:                        PUT "can't open file %s", kbdline END;
                    307:                }
                    308:                return;
                    309:        case WIN_RESIZE:
                    310:                /* doesn't do much right now */
                    311:                width=(int)window_get(canvas, CANVAS_WIDTH);
                    312:                height=(int)window_get(canvas, CANVAS_HEIGHT);
                    313:                Drect.origin = pt(0,0);
                    314:                Drect.corner = add(Drect.origin, pt(width,height));
                    315:                view_setup(nview);
                    316:                return;
                    317:        case MS_LEFT:   /* button 1 */
                    318:                if (event_is_up(e))
                    319:                        return;
                    320:                last_but = 1;
                    321:                last_hit = 0;
                    322:                n = domouse();
                    323:                break;
                    324:        case MS_MIDDLE:
                    325:                if (event_is_up(e))
                    326:                        return;
                    327:                last_but = 2;
                    328:                last_hit = (int) menu_show(mbut2, canvas, e, 0) - 1;
                    329:                n = domouse();
                    330:                for (i = 0; s = m2gen(i); i++)
                    331:                        menu_set(menu_get(mbut2, MENU_NTH_ITEM, i+1),
                    332:                                MENU_STRING, s, 0);
                    333:                if (last_hit >= 0) /* start with this selected next time */
                    334:                        menu_set(mbut2, MENU_DEFAULT, last_hit+1, 0);
                    335:                break;
                    336:        case MS_RIGHT:
                    337:                if (event_is_up(e))
                    338:                        return;
                    339:                last_but = 3;
                    340:                last_hit = (int) menu_show(mbut3, canvas, e, 0) - 1;
                    341:                n = domouse();
                    342:                for (i = 0; s = m3gen(i); i++)
                    343:                        menu_set(menu_get(mbut3, MENU_NTH_ITEM, i+1),
                    344:                                MENU_STRING, s, 0);
                    345:                if (last_hit >= 0) /* start with this selected next time */
                    346:                        menu_set(mbut3, MENU_DEFAULT, last_hit+1, 0);
                    347:                break;
                    348:        }
                    349:        run_one(n);
                    350: }
                    351: 
                    352: run_one(n)
                    353: {
                    354:        static uchar *ip;
                    355:        int i;
                    356:        char *s;
                    357:        Event ev;
                    358:        Event *e= &ev;
                    359: 
                    360: again:
                    361:        if (ip == 0) {
                    362:                ip = dir == Fwd ? input : inp;
                    363:                clear();
                    364:        }
                    365:        if (n == Quit) {
                    366:                window_done(canvas);
                    367:                return;
                    368:        }
                    369:        if (n == Hit)           /* wait for another mouse hit */
                    370:                return;
                    371:        if (n == Forward) {     /* change from fwd to back -- fiddle ip */
                    372:                ip = next_obj(ip);
                    373:                return;
                    374:        }
                    375:        if (n == Backward) {
                    376:                ip = prev_obj(ip);
                    377:                return;
                    378:        }
                    379:        if (n == File) {
                    380:                putstring("filename? ");
                    381:                return;
                    382:        }
                    383:        if (n == Again) {
                    384:                clear();
                    385:                dir = Fwd;
                    386:                ip = input;
                    387:        }
                    388:        if (singstep) {
                    389:                if (clicking > 0)
                    390:                        ip = click_obj(ip, xormode, dir);
                    391:                else
                    392:                        ip = step_obj(ip, xormode, dir);
                    393:        } else {                /* free running */
                    394:                while (ip) {
                    395:                        if (clicking > 0)
                    396:                                ip = click_obj(ip, xormode, dir);
                    397:                        else
                    398:                                ip = step_obj(ip, xormode, dir);
                    399:                        if (ip && window_read_event(canvas,e)==0) {
                    400:                                /* this just about duplicates inevent */
                    401:                                switch (event_id(e)) {
                    402:                                case WIN_RESIZE:
                    403:                                        width=(int)window_get(canvas,
                    404:                                                CANVAS_WIDTH);
                    405:                                        height=(int)window_get(canvas,
                    406:                                                CANVAS_HEIGHT);
                    407:                                        Drect.origin = pt(0,0);
                    408:                                        Drect.corner = add(Drect.origin,
                    409:                                                pt(width,height));
                    410:                                        view_setup(nview);
                    411:                                        break;
                    412:                                case WIN_REPAINT:
                    413:                                        pw_repairretained(pw);
                    414:                                        break;
                    415:                                case MS_LEFT:   /* button 1 */
                    416:                                        if (event_is_up(e))
                    417:                                                break;
                    418:                                        last_but = 1;
                    419:                                        last_hit = 0;
                    420:                                        return; /* interrupt run */
                    421:                                case MS_MIDDLE:
                    422:                                        if (event_is_up(e))
                    423:                                                break;
                    424:                                        last_but = 2;
                    425:                                        last_hit = (int) menu_show(mbut2,
                    426:                                                canvas, e, 0) - 1;
                    427:                                        n = domouse();
                    428:                                        for (i = 0; s = m2gen(i); i++)
                    429:                                                menu_set(menu_get(mbut2,
                    430:                                                  MENU_NTH_ITEM, i+1),
                    431:                                                        MENU_STRING, s, 0);
                    432:                                        if (last_hit >= 0)
                    433:                                                menu_set(mbut2, MENU_DEFAULT
                    434:                                                        , last_hit+1, 0);
                    435:                                        goto again;
                    436:                                case MS_RIGHT:
                    437:                                        if (event_is_up(e))
                    438:                                                break;
                    439:                                        last_but = 3;
                    440:                                        last_hit = (int) menu_show(mbut3,
                    441:                                                canvas, e, 0) - 1;
                    442:                                        n = domouse();
                    443:                                        for (i = 0; s = m3gen(i); i++)
                    444:                                                menu_set(menu_get(mbut3,
                    445:                                                        MENU_NTH_ITEM, i+1),
                    446:                                                        MENU_STRING, s, 0);
                    447:                                        if (last_hit >= 0)
                    448:                                                menu_set(mbut3, MENU_DEFAULT
                    449:                                                        , last_hit+1, 0);
                    450:                                        goto again;
                    451:                                }
                    452:                        }
                    453:                        sleephz(delay-1);
                    454:                }
                    455:        }
                    456: }
                    457: 
                    458: domouse()
                    459: {
                    460:        int n;
                    461: 
                    462:        if (last_but == 1)
                    463:                return Proceed;
                    464:        if (last_but == 3) {
                    465:                switch (last_hit) {
                    466:                case Again:
                    467:                        return Again;
                    468:                case Faster:
                    469:                        if (delay > 1)
                    470:                                delay /= 2;
                    471:                        return Hit;
                    472:                case Slower:
                    473:                        delay *= 2;
                    474:                        return Hit;
                    475:                case Step:
                    476:                        singstep = 1 - singstep;
                    477:                        n = Step;
                    478:                        return Hit;
                    479:                case Forward:
                    480:                        dir = 1 - dir;
                    481:                        if (xormode == F_OR)
                    482:                                xormode = F_CLR;
                    483:                        else if (xormode == F_CLR)
                    484:                                xormode = F_OR;
                    485:                        return dir == Fwd ? Forward : Backward;
                    486:                case Fatter:
                    487:                        fatness++;
                    488:                        return Hit;
                    489:                case Thinner:
                    490:                        if (fatness > 0)
                    491:                                fatness--;
                    492:                        return Hit;
                    493:                case Xor:
                    494:                        if (xormode == F_OR || xormode == F_CLR)
                    495:                                xormode = F_XOR;
                    496:                        else if (dir == Fwd)
                    497:                                xormode = F_OR;
                    498:                        else
                    499:                                xormode = F_CLR;
                    500:                        return Hit;
                    501:                case File:
                    502:                        return File;
                    503:                case Quit:
                    504:                        return Quit;
                    505:                default:
                    506:                        return Hit;
                    507:                }
                    508:        } else if (last_but == 2) {
                    509:                Rectangle r, shrink();
                    510:                if (last_hit == -1)
                    511:                        return Hit;
                    512:                else if (last_hit < nview) {
                    513:                        r = getrect23();
                    514:                        if (r.origin.x == 0 && r.corner.x == 0) /* bailed out */
                    515:                                return Hit;
                    516:                        if (eqpt(r.origin, r.corner))
                    517:                                r = Drect;
                    518:                        drawrect(inset(viewpt[last_hit].vr, -(INSET+fatness)), F_CLR);
                    519:                        drawrect(r, F_OR);
                    520:                        viewpt[last_hit].vr = r = inset(r, INSET+fatness);
                    521:                        viewpt[last_hit].xmax = r.corner.x - r.origin.x;
                    522:                        viewpt[last_hit].ymax = r.corner.y - r.origin.y;
                    523:                        return Hit;
                    524: 
                    525:                } else {        /* a click */
                    526:                        if (clickval[last_hit-nview]) { /* was on, so turn off */
                    527:                                clickval[last_hit-nview] = 0;
                    528:                                clicking--;
                    529:                        } else {
                    530:                                clickval[last_hit-nview] = 1;
                    531:                                clicking++;
                    532:                        }
                    533:                        return Hit;
                    534:                }
                    535:        }
                    536: }
                    537: 
                    538: Rectangle shrink(r, pct)       /* shrink rectangle by 2*pct */
                    539:        Rectangle r;
                    540: {
                    541:        int dx = muldiv(r.corner.x-r.origin.x, pct, 100);
                    542:        int dy = muldiv(r.corner.y-r.origin.y, pct, 100);
                    543:        r.origin = add(r.origin, Pt(dx,dy));
                    544:        r.corner = sub(r.corner, Pt(dx,dy));
                    545:        return r;
                    546: }
                    547: 
                    548: view_setup(n)
                    549:        int n;
                    550: {
                    551:        int i, dx, dy;
                    552: 
                    553:        dx = (Dc.x - Do.x) / 2;
                    554:        dy = (Dc.y - Do.y) / 2;
                    555:        viewpt[0].vr = Drect;
                    556:        switch (n) {
                    557:        case 2:
                    558:                viewpt[1].vr = Drect;
                    559:                viewpt[0].vr.corner.y -= dy;
                    560:                viewpt[1].vr.origin.y += dy;
                    561:                break;
                    562:        case 3: case 4:
                    563:                viewpt[0].vr.corner = add(Drect.origin, Pt(dx,dy));
                    564:                viewpt[1].vr = raddp(viewpt[0].vr, Pt(0,dy));
                    565:                viewpt[2].vr = raddp(viewpt[0].vr, Pt(dx,0));
                    566:                viewpt[3].vr = raddp(viewpt[0].vr, Pt(dx,dy));
                    567:                break;
                    568:        }
                    569:        for (i = 0; i < n; i++) {
                    570:                viewpt[i].vr = shrink(viewpt[i].vr, MARGINPCT);
                    571:                viewpt[i].xmax = viewpt[i].vr.corner.x - viewpt[i].vr.origin.x;
                    572:                viewpt[i].ymax = viewpt[i].vr.corner.y - viewpt[i].vr.origin.y;
                    573:        }
                    574: }
                    575: 
                    576: drawrect(r, mode)
                    577:        Rectangle r;
                    578: {
                    579:        segment(&display, r.origin, Pt(r.origin.x,r.corner.y), mode);
                    580:        segment(&display, r.origin, Pt(r.corner.x,r.origin.y), mode);
                    581:        segment(&display, r.corner, Pt(r.origin.x,r.corner.y), mode);
                    582:        segment(&display, r.corner, Pt(r.corner.x,r.origin.y), mode);
                    583: }
                    584: 
                    585: segment(dp, p1, p2, mode)
                    586:        Rectangle *dp;  /* fake */
                    587:        Point p1, p2;
                    588:        int mode;
                    589: {
                    590:        pw_vector(pw, p1.x, p1.y, p2.x, p2.y, mode, 1);
                    591: }
                    592: 
                    593: point(dp, p, mode)
                    594:        Rectangle *dp;
                    595:        Point p;
                    596:        int mode;
                    597: {
                    598:        register int val;
                    599:        val = (mode==F_XOR)? pw_get(pw, p.x, p.y)^1 :
                    600:                        ((mode==F_OR)? 1 : 0);
                    601:        pw_put(pw, p.x, p.y, val);
                    602: }
                    603: 
                    604: /* return the raster op that f needs to be when SRC is inverted */
                    605: invsrc(f)
                    606:        register int f;
                    607: {
                    608:        if(f==F_XOR) f=PIX_NOT(PIX_SRC)^PIX_DST;
                    609:        else if(f==F_OR) f=PIX_NOT(PIX_SRC)|PIX_DST;
                    610:        else if(f==F_STORE) f=PIX_NOT(PIX_SRC);
                    611:        else if(f==F_CLR) f=PIX_SRC&PIX_DST;
                    612:        return f;
                    613: }
                    614: 
                    615: rectf(dp, r, mode)
                    616:        Rectangle *dp;
                    617:        Rectangle r;
                    618:        int mode;
                    619: {
                    620:        pw_writebackground(pw,r.origin.x, r.origin.y,
                    621:                r.corner.x-r.origin.x, r.corner.y-r.origin.y, invsrc(mode));
                    622: }
                    623: circle(dp, p, r, mode)
                    624:        Rectangle *dp;
                    625:        Point p;
                    626:        int r, mode;
                    627: {
                    628:        int x1=p.x;
                    629:        register y1=p.y;
                    630:        register eps = 0;       /* x^2 + y^2 - r^2 */
                    631:        register dxsq = 1;              /* (x+dx)^2-x^2*/
                    632:        register dysq = 1 - 2*r;
                    633:        register exy;
                    634:        int x0 = x1;
                    635:        register y0 = y1 - r;
                    636:        y1 += r;
                    637:        pw_batch_on(pw);
                    638:        if (mode == F_XOR) {    /* endpoints coincide */
                    639:                point(dp,Pt(x0,y0),mode);
                    640:                point(dp,Pt(x0,y1),mode);
                    641:        }
                    642:        while(y1 > y0) {
                    643:                point(dp,Pt(x0,y0),mode);
                    644:                point(dp,Pt(x0,y1),mode);
                    645:                point(dp,Pt(x1,y0),mode);
                    646:                point(dp,Pt(x1,y1),mode);
                    647:                exy = eps + dxsq + dysq;
                    648:                if(-exy <= eps+dxsq) {
                    649:                        y1--;
                    650:                        y0++;
                    651:                        eps += dysq;
                    652:                        dysq += 2;
                    653:                }
                    654:                if(exy <= -eps) {
                    655:                        x1++;
                    656:                        x0--;
                    657:                        eps += dxsq;
                    658:                        dxsq += 2;
                    659:                }
                    660:        }
                    661:        point(dp,Pt(x0,y0),mode);
                    662:        point(dp,Pt(x1,y0),mode);
                    663:        pw_batch_off(pw);
                    664: }
                    665: 
                    666: disc(dp, p, r, mode)
                    667:        Rectangle *dp;
                    668:        Point p;
                    669:        int r, mode;
                    670: {
                    671:        register x1=p.x, y1=p.y;
                    672:        register eps = 0;       /* x^2 + y^2 - r^2 */
                    673:        int dxsq = 1;           /* (x+dx)^2-x^2*/
                    674:        int dysq = 1 - 2*r;
                    675:        int exy;
                    676:        register x0 = x1;
                    677:        register y0 = y1 - r;
                    678:        x1++;           /* to offset jerq's half-open lines*/
                    679:        y1 += r;
                    680:        pw_batch_on(pw);
                    681:        while(y1 > y0) {
                    682:                exy = eps + dxsq + dysq;
                    683:                if(-exy <= eps+dxsq) {
                    684:                        rectf(dp, Rect4(x0, y0, x1, y0+1), mode);
                    685:                        rectf(dp, Rect4(x0, y1, x1, y1+1), mode);
                    686:                        y1--;
                    687:                        y0++;
                    688:                        eps += dysq;
                    689:                        dysq += 2;
                    690:                }
                    691:                if(exy <= -eps) {
                    692:                        x1++;
                    693:                        x0--;
                    694:                        eps += dxsq;
                    695:                        dxsq += 2;
                    696:                }
                    697:        }
                    698:        rectf(dp, Rect4(x0, y0, x1, y0+1), mode);
                    699:        pw_batch_off(pw);
                    700: }
                    701: 
                    702: string(fp, s, dp, p, mode)
                    703:        int *fp;        /* actually a font pointer */
                    704:        uchar *s;
                    705:        Rectangle *dp;
                    706:        Point p;
                    707:        int mode;
                    708: {
                    709:        pw_text(pw, p.x, p.y+16, mode, 0, s);
                    710: }
                    711: 
                    712: do_rcv()
                    713: {
                    714:        int c, n, b, m, i;
                    715:        uchar *ip;
                    716: 
                    717:        init_params();
                    718:        clear();
                    719:        memsize = readint();
                    720:        if ((inbuf = (uchar *) malloc(memsize)) == (uchar *) NULL) {
                    721:                PUT "can't allocate %d bytes", memsize END
                    722:                sleephz(60);
                    723:                termabort();
                    724:        }
                    725:        input = inbuf+1;        /* leave a null at front */
                    726:        inp = inbuf+1;          /* next free slot in input */
                    727:        dir = Fwd;
                    728:        PUT "%d bytes, limit %d", inp - input, memsize END
                    729: 
                    730:   top:
                    731:        switch (c = readchar()) {
                    732:        case P_INIT:    /* initialize */
                    733:                break;
                    734:        case P_ENDFILE:
                    735:                *inp = 0;
                    736:                return;
                    737:        case P_CLEAR:
                    738:                clear();
                    739:                break;
                    740:        case P_DEFINE:
                    741:                /* view, click, ... */
                    742:                c = readchar();
                    743:                assert(c == 'c' || c == 'v', "illegal define");
                    744:                i = readint();
                    745:                readstring(buf);
                    746:                if (c == 'c') {
                    747:                        clickname[i] = (char *) malloc(strlen(buf)+1);
                    748:                        strcpy(clickname[i], buf);
                    749:                        nclick++;
                    750:                } else {        /* c == 'v' */
                    751:                        viewname[i] = (char *) malloc(strlen(buf)+1);
                    752:                        strcpy(viewname[i], buf);
                    753:                        nview++;
                    754:                }
                    755:                break;
                    756:        case P_OBJECT:  /* read an object */
                    757:                ip = inp;
                    758:                if (nobj++ == 0)
                    759:                        view_setup(nview);
                    760:                if (nobj % 100 == 0)
                    761:                        PUT "%d", nobj END
                    762:                read_obj();
                    763:                draw_obj(ip, F_XOR, Fwd);
                    764:                break;
                    765:        case P_PRINT:   /* print a string */
                    766:                readstring(buf);
                    767:                putstring(buf);
                    768:                break;
                    769:        case P_ERROR:   /* host is going to exit */
                    770:                termabort();
                    771:        default:
                    772:                if (overflow)
                    773:                        break;
                    774:                putstring("do_rcv error; unrecognized command: ");
                    775:                for (pbuf = buf; c != '\n'; c = readchar())
                    776:                        *pbuf++ = c;
                    777:                *pbuf = 0;
                    778:                putstring(buf);
                    779:                break;
                    780:        }
                    781:        goto top;
                    782: }
                    783: 
                    784: clear()
                    785: {
                    786:        rectf(&display, Drect, F_CLR);  /* clear screen */
                    787: }
                    788: 
                    789: read_obj()     /* read an object, stick it in input[] */
                    790: {
                    791:        int c, n, m;
                    792:        uchar *p;
                    793: 
                    794:        if (inp > input+memsize-50) {   /* eat up at least one */
                    795:                PUT "overflow at %d bytes, limit %d", inp - input, memsize END
                    796:                overflow++;
                    797:                return;
                    798:        }
                    799:        c = readchar();
                    800:        switch (c) {
                    801:        case ' ':
                    802:        case '\n':
                    803:                break;
                    804:        case 'b':
                    805:        case 'l':
                    806:                slotnum = readint();
                    807:                slot[slotnum] = inp-input;
                    808:                p = savechar(c);
                    809:                savechar(curview = readint());
                    810:                savechar(readint());    /* options */
                    811:                savept(readpt());
                    812:                savept(readpt());
                    813:                savect(inp-p);
                    814:                break;
                    815:        case 'o':
                    816:                slotnum = readint();
                    817:                slot[slotnum] = inp-input;
                    818:                p = savechar(c);
                    819:                savechar(curview = readint());
                    820:                savechar(readint());    /* options */
                    821:                savept(readpt());
                    822:                saveint(readint());     /* radius */
                    823:                savect(inp-p);
                    824:                break;
                    825:        case 't':
                    826:                slotnum = readint();
                    827:                slot[slotnum] = inp-input;
                    828:                p = savechar(c);
                    829:                savechar(curview = readint());
                    830:                savechar(readint());    /* options */
                    831:                savept(readpt());
                    832:                n = readstring(inp+1);  /* +1 leaves a hole */
                    833:                *inp = n;               /* insert count before string */
                    834:                inp += n + 2;           /* +2 = count before and \0 on end */
                    835:                savect(inp-p);
                    836:                break;
                    837:        case 'e':
                    838:                p = savechar(c);
                    839:                savelong(slot[readint()]);
                    840:                savect(inp-p);
                    841:                break;
                    842:        case 'c':
                    843:                p = savechar(c);
                    844:                savechar(readint());
                    845:                savect(inp-p);
                    846:                break;
                    847:        }
                    848: }
                    849: 
                    850: Point readpt() /* read a Point */
                    851: {
                    852:        Point p;
                    853: 
                    854:        p.x = readint();
                    855:        p.y = readint();
                    856:        return p;
                    857: }
                    858: 
                    859: uchar *savechar(c)
                    860: {
                    861:        *inp++ = c;
                    862:        return inp-1;
                    863: }
                    864: 
                    865: savect(n)
                    866: {
                    867:        if (n > 255)
                    868:                putstring("text string too long");
                    869:        *inp++ = n;
                    870: }
                    871: 
                    872: saveint(n)
                    873: {
                    874:        *inp++ = n >> 8;
                    875:        *inp++ = n & 0377;
                    876: }
                    877: 
                    878: savelong(n)
                    879:        long n;
                    880: {
                    881:        *inp++ = n >> 24;
                    882:        *inp++ = n >> 16;
                    883:        *inp++ = n >> 8;
                    884:        *inp++ = n;
                    885: }
                    886: 
                    887: savept(p)
                    888:        Point p;
                    889: {
                    890:        *inp++ = p.x >> 8;
                    891:        *inp++ = p.x & 0377;
                    892:        *inp++ = p.y >> 8;
                    893:        *inp++ = p.y & 0377;
                    894: }
                    895: 
                    896: getpoint(ip)
                    897:        uchar *ip;
                    898: {
                    899:        return *ip << 8 | *(ip+1);
                    900: }
                    901: 
                    902: long getlong(ip)
                    903:        uchar *ip;
                    904: {
                    905:        return *ip << 24 | *(ip+1) << 16 | *(ip+2) << 8 | *(ip+3);
                    906: }
                    907: 
                    908: Point scalept(v, p)
                    909:        Point p;
                    910: {
                    911:        p.x = p.x * viewpt[v].xmax / 10000;
                    912:        p.y = viewpt[v].ymax - p.y * viewpt[v].ymax / 10000;
                    913:        return p;
                    914: }
                    915: 
                    916: scalex(v, n)
                    917: {
                    918:        return n * viewpt[v].xmax / 10000;
                    919: }
                    920: 
                    921: Point fetchpt(v, ip)
                    922:        int v;
                    923:        uchar *ip;
                    924: {
                    925:        Point pt;
                    926: 
                    927:        pt.x = *ip << 8 | *(ip+1);
                    928:        pt.y = *(ip+2) << 8 | *(ip+3);
                    929:        pt = scalept(v, pt);
                    930:        return add(pt, viewpt[v].vr.origin);
                    931: }
                    932: 
                    933: /*
                    934:   Encoding:  type, view#, opts, coords, chars, etc., # = length of group
                    935:        bvoxxyyxxyy#
                    936:        lvoxxyyxxyy#
                    937:        ovoxxyyrr#
                    938:        tvoxxyynccc0#
                    939:        ennnn#
                    940:        cn#
                    941: 
                    942: */
                    943: 
                    944: uchar *prev_obj(ip)
                    945:        uchar *ip;
                    946: {
                    947:        if (ip <= input)
                    948:                return 0;
                    949:        return ip - ip[-1] - 1;
                    950: }
                    951: 
                    952: uchar *next_obj(ip)
                    953:        uchar *ip;
                    954: {
                    955:        if (ip < input || ip >= inp)
                    956:                return 0;
                    957:        switch (*ip) {
                    958:        case 0:
                    959:                return 0;
                    960:        case 'b':
                    961:        case 'l':
                    962:                return ip + 12;
                    963:        case 'o':
                    964:                return ip + 10;
                    965:        case 't':
                    966:                return ip + ip[7] + 10;
                    967:        case 'c':
                    968:                return ip + 3;
                    969:        case 'e':
                    970:                return ip + 6;
                    971:        default:
                    972:                return 0;
                    973:        }
                    974: }
                    975: 
                    976: uchar *step_obj(ip, mode, dir) /* draw objs until one that changes something */
                    977:        uchar *ip;
                    978: {
                    979:        int c;
                    980: 
                    981:        while (ip) {
                    982:                c = *ip;
                    983:                ip = draw_obj(ip, mode, dir);
                    984:                if (c == 'b' || c == 'l' || c == 't' || c == 'e' || c == 'o')
                    985:                        return ip;
                    986:        }
                    987:        return ip;
                    988: }
                    989: 
                    990: uchar *click_obj(ip, mode, dir)        /* draw objs until matching click */
                    991:        uchar *ip;
                    992: {
                    993:        int c;
                    994:        uchar *oip;
                    995: 
                    996:        for (;;) {
                    997:                oip = ip;
                    998:                ip = draw_obj(ip, mode, dir);
                    999:                if (ip == 0 || (oip && *oip == 'c' && clickval[oip[1]]))
                   1000:                        return ip;
                   1001:        }
                   1002: }
                   1003: 
                   1004: uchar *draw_obj(ip, mode, dir) /* draw obj from coords at ip */
                   1005:        uchar *ip;
                   1006:        int mode, dir;
                   1007: {
                   1008:        int c, r, thick, n, shift, head;
                   1009:        Point p0, p1, p2;
                   1010: 
                   1011:        if (ip < input || ip >= inp)
                   1012:                return 0;
                   1013:        switch (c = *ip++) {
                   1014:        case 'b':
                   1015:                p0 = fetchpt(*ip, ip+2);
                   1016:                p1 = fetchpt(*ip, ip+6);
                   1017:                if (ip[1] == Bfill) {
                   1018:                        if (p0.y < p1.y)
                   1019:                                rectf(&display, Rpt(p0, p1), mode);
                   1020:                        else
                   1021:                                rectf(&display, Rect4(p0.x,p1.y,p1.x,p0.y), mode);
                   1022:                } else {
                   1023:                        segment(&display, p0, Pt(p0.x,p1.y), mode);
                   1024:                        segment(&display, Pt(p0.x,p1.y), p1, mode);
                   1025:                        segment(&display, p1, Pt(p1.x,p0.y), mode);
                   1026:                        segment(&display, Pt(p1.x,p0.y), p0, mode);
                   1027:                }
                   1028:                if (dir == Fwd)
                   1029:                        ip += 1+9+1;
                   1030:                else
                   1031:                        ip -= (*(ip-2) + 2);
                   1032:                break;
                   1033:        case 'l':
                   1034:                p0 = fetchpt(*ip, ip+2);
                   1035:                p1 = fetchpt(*ip, ip+6);
                   1036:                thick = ip[1]/10;       /* ought to be a macro! */
                   1037:                if (thick == Ldotted/10 || thick == Ldashed/10)
                   1038:                        thick = 1;
                   1039:                thick = 2 * thick - 1;  /* 1,3,5 */
                   1040:                fatline(p0, p1, mode, thick);
                   1041:                head = ip[1]%10;        /* ditto */
                   1042:                if (head == Larrow1 || head == Larrow3)
                   1043:                        arrow(p0, p1, AW, AH, mode);
                   1044:                if (head == Larrow2 || head == Larrow3)
                   1045:                        arrow(p1, p0, AW, AH, mode);
                   1046:                if (dir == Fwd)
                   1047:                        ip += 1+9+1;
                   1048:                else
                   1049:                        ip -= (*(ip-2) + 2);
                   1050:                break;
                   1051:        case 'o':
                   1052:                p0 = fetchpt(*ip, ip+2);
                   1053:                r = scalex(*ip, getpoint(ip+6));
                   1054:                if (ip[1] == Cnofill)
                   1055:                        circle(&display, p0, r, mode);
                   1056:                else
                   1057:                        disc(&display, p0, r, mode);
                   1058:                if (dir == Fwd)
                   1059:                        ip += 1+7+1;
                   1060:                else
                   1061:                        ip -= (*(ip-2) + 2);
                   1062:                break;
                   1063:        case 't':
                   1064:                p0 = fetchpt(*ip, ip+2);
                   1065:                n = ip[6];
                   1066:                shift = (ip[1]/10) * 10;        /* ought to be a macro! */
                   1067:                if (shift == Tljust)
                   1068:                        shift = 0;
                   1069:                else if (shift == Tcenter)
                   1070:                        shift = (9 * n) / 2;    /* 9 = char width */
                   1071:                else
                   1072:                        shift = 9 * n;
                   1073:                string(&defont, ip+7, &display, sub(p0, Pt(shift,8)), mode);
                   1074:                if (dir == Fwd)
                   1075:                        ip += 1+5 + *(ip+6)+2 + 1;
                   1076:                else
                   1077:                        ip -= (*(ip-2) + 2);
                   1078:                break;
                   1079:        case 'e':
                   1080:                erase(ip-1);
                   1081:                if (dir == Fwd)
                   1082:                        ip += 5;
                   1083:                else
                   1084:                        ip -= (*(ip-2) + 2);
                   1085:                break;
                   1086:        case 'c':
                   1087:                if (dir == Fwd)
                   1088:                        ip += 2;
                   1089:                else
                   1090:                        ip -= (*(ip-2) + 2);
                   1091:                break;
                   1092:        default:
                   1093:                ip = 0;
                   1094:                break;
                   1095:        }
                   1096:        return ip;
                   1097: }
                   1098: 
                   1099: erase(ip)
                   1100:        uchar *ip;
                   1101: {
                   1102:        long target = getlong(ip+1);    /* target label index */
                   1103:        int mode = F_XOR;
                   1104: 
                   1105:        if (xormode == F_OR || xormode == F_CLR)
                   1106:                mode = dir == Fwd ? F_CLR : F_OR;
                   1107:        draw_obj(input+target, mode, Fwd);
                   1108: }
                   1109: 
                   1110: #define abs(x) ((x) >= 0 ? (x) : -(x))
                   1111: 
                   1112: fatline(p0, p1, mode, thick)
                   1113:        Point p0, p1;
                   1114: {
                   1115:        int i, fat, beg, nl;
                   1116: 
                   1117:        fat = thick * (2 * fatness + 1);
                   1118:        beg = fat / 2;
                   1119:        if (abs(p1.x-p0.x) >= abs(p1.y-p0.y)) { /* horizontal */
                   1120:                for (nl = 0, i = -beg; nl < fat; nl++, i++)
                   1121:                        segment(&display, add(p0, Pt(0,i)), add(p1, Pt(0,i)), mode);
                   1122:        } else {
                   1123:                for (nl = 0, i = -beg; nl < fat; nl++, i++)
                   1124:                        segment(&display, add(p0, Pt(i,0)), add(p1, Pt(i,0)), mode);
                   1125:        } 
                   1126: }
                   1127: 
                   1128: arrow(p1, p2, w, h, c)
                   1129:        Point p1, p2;
                   1130:        int w, h, c;
                   1131: /*
                   1132: ** draw arrow of height,width (h,w) at p2 of segment p1,p2.
                   1133: */
                   1134: {
                   1135:        Point d;
                   1136:        int norm, qx, qy, lx, ly;
                   1137: 
                   1138:        d = sub(p2, p1);
                   1139:        /* norm = sqrt((long)d.x*d.x + (long)d.y*d.y); */
                   1140:        norm = ((long)d.x*d.x + (long)d.y*d.y) / 2;
                   1141:        if (norm == 0)  /* shouldn't happen, but ... */
                   1142:                return;
                   1143:        qx = p2.x - h*d.x/norm;
                   1144:        qy = p2.y - h*d.y/norm;
                   1145:        lx = w/2 * -d.y/norm;
                   1146:        ly = w/2 * d.x/norm;
                   1147:        /* segment(&display, p1, p2, c); */
                   1148:        segment(&display, Pt(qx+lx, qy+ly), p2, c);
                   1149:        segment(&display, Pt(qx-lx, qy-ly), p2, c);
                   1150: }
                   1151: 
                   1152: 
                   1153: putstring(a1, a2, a3, a4, a5)
                   1154:        char *a1, *a2, *a3, *a4, *a5;
                   1155: {
                   1156:        char buf[100];
                   1157: 
                   1158:        sprintf(buf, "%50s", " ");      /* cheap clear */
                   1159:        pw_text(pw, 20, 20, F_STORE, 0, buf);
                   1160:        sprintf(buf, a1, a2, a3, a4, a5);
                   1161:        pw_text(pw, 20, 20, F_STORE, 0, buf);
                   1162: }
                   1163: 
                   1164: assert(c, s)   /* poor man's assertion */
                   1165:        char *s;
                   1166: {
                   1167:        if (!c) {
                   1168:                putstring("assertion %s failed\n", s);
                   1169:                sleephz(60);
                   1170:                termabort();
                   1171:        }
                   1172: }
                   1173: 
                   1174: termabort()
                   1175: {
                   1176:        send1char(P_QUIT);
                   1177:        flushproto();
                   1178:        window_done(canvas);
                   1179:        exit(1);
                   1180: }
                   1181: 
                   1182: readbyte()
                   1183: {
                   1184:        char c;
                   1185: 
                   1186:        read(0, &c, 1);
                   1187:        return c;
                   1188: }
                   1189: 
                   1190: sendbuf(buf, p)
                   1191:        char *buf, *p;
                   1192: {
                   1193:        write(1, buf, p-buf);
                   1194: }
                   1195: 
                   1196: 
                   1197: short bullseye_bits[]={
                   1198:        0x07E0, 0x1FF8, 0x399C, 0x63C6, 0x6FF6, 0xCDB3, 0xD99B, 0xFFFF,
                   1199:        0xFFFF, 0xD99B, 0xCDB3, 0x6FF6, 0x63C6, 0x399C, 0x1FF8, 0x07E0,
                   1200: };
                   1201: short coffeecup_bits[]={
                   1202:        0x0100, 0x00E0, 0x0010, 0x03E0, 0x0400, 0x0FE0, 0x123C, 0x1FE2,
                   1203:        0x101A, 0x101A, 0x1002, 0x103C, 0x1810, 0x6FEC, 0x4004, 0x3FF8,
                   1204: };
                   1205: short sweep_bits[]={
                   1206:        0x43FF, 0xE001, 0x7001, 0x3801, 0x1D01, 0x0F01, 0x8701, 0x8F01,
                   1207:        0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0xFFFF,
                   1208: };
                   1209: short deadmouse_bits[]={
                   1210:        0x0000, 0x0114, 0xA208, 0x4100, 0x0000, 0x0008, 0x0004, 0x0082,
                   1211:        0x0441, 0xFFE1, 0x5FF1, 0x3FFE, 0x17F0, 0x03E0, 0x0000, 0x0000,
                   1212: };
                   1213: short darkgrey_bits[]={
                   1214:        0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777,
                   1215:        0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777, 0xDDDD, 0x7777,
                   1216: };
                   1217: short lockarrow_bits[]={
                   1218:        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0FC0, 0x0FC0,
                   1219:        0x03C0, 0x07C0, 0x0EC0, 0x1CC0, 0x3800, 0x7000, 0xE0DB, 0xC0DB,
                   1220: };
                   1221: mpr_static(bullseye_pr, 16, 16, 1, bullseye_bits);
                   1222: mpr_static(coffeecup_pr, 16, 16, 1, coffeecup_bits);
                   1223: mpr_static(sweep_pr, 16, 16, 1, sweep_bits);
                   1224: mpr_static(deadmouse_pr, 16, 16, 1, deadmouse_bits);
                   1225: mpr_static(lockarrow_pr, 16, 16, 1, lockarrow_bits);
                   1226: mpr_static(darkgrey, 16, 16, 1, darkgrey_bits);
                   1227: 
                   1228: initcursors()
                   1229: {
                   1230:        normalcursor=cursor_copy(window_get(canvas,WIN_CURSOR));
                   1231:        cursor_set(normalcursor,CURSOR_OP,F_XOR,0);
                   1232:        bullseye=cursor_create(CURSOR_IMAGE,&bullseye_pr,
                   1233:                CURSOR_XHOT,7,CURSOR_YHOT,7,CURSOR_OP,F_XOR,0);
                   1234:        coffeecup=cursor_create(CURSOR_IMAGE,&coffeecup_pr,
                   1235:                CURSOR_XHOT,7,CURSOR_YHOT,7,CURSOR_OP,F_XOR,0);
                   1236:        sweep=cursor_create(CURSOR_IMAGE,&sweep_pr,
                   1237:                CURSOR_XHOT,7,CURSOR_YHOT,7,CURSOR_OP,F_XOR,0);
                   1238:        deadmouse=cursor_create(CURSOR_IMAGE,&deadmouse_pr,
                   1239:                CURSOR_XHOT,7,CURSOR_YHOT,7,CURSOR_OP,F_XOR,0);
                   1240:        lockarrow=cursor_create(CURSOR_IMAGE,&lockarrow_pr,
                   1241:                CURSOR_XHOT,0,CURSOR_YHOT,0,CURSOR_OP,F_XOR,0);
                   1242:        cursor= &normalcursor;
                   1243: }
                   1244: 
                   1245: 
                   1246: Rectangle getrect23()
                   1247: {
                   1248:        static Rectangle r;
                   1249:        static Event ev;
                   1250:        register Event *e= &ev;
                   1251:        register int sweepstate=0;
                   1252:        r.origin.x=r.origin.y=r.corner.x=r.corner.y=0;
                   1253:        cursswitch(&sweep);
                   1254:        window_set(canvas, WIN_CONSUME_PICK_EVENT, LOC_DRAG, 0, 0);
                   1255:        window_release_event_lock(canvas);
                   1256:        while(sweepstate<=1){
                   1257:                if(window_read_event(canvas,e)!=0)
                   1258:                        ; /* non-blocking read */
                   1259:                switch (event_id(e)) {
                   1260:                case MS_LEFT:
                   1261:                        if(sweepstate) showr(&r); /*erase box*/
                   1262:                        sweepstate=2;
                   1263:                        break;
                   1264:                case MS_MIDDLE:
                   1265:                case MS_RIGHT:
                   1266:                        if(!sweepstate && event_is_down(e)){
                   1267:                                r.origin.x=r.corner.x=event_x(e);
                   1268:                                r.origin.y=r.corner.y=event_y(e);
                   1269:                                sweepstate=1;
                   1270:                                showr(&r);
                   1271:                        }
                   1272:                        else if(sweepstate && event_is_up(e)){
                   1273:                                r.corner.x=event_x(e);
                   1274:                                r.corner.y=event_y(e);
                   1275:                                showr(&r);
                   1276:                                sweepstate=2;
                   1277:                        }
                   1278:                        break;
                   1279:                case LOC_DRAG:
                   1280:                        showr(&r); /* erase old one */
                   1281:                        r.corner.x=event_x(e);
                   1282:                        r.corner.y=event_y(e);
                   1283:                        showr(&r);
                   1284:                        break;
                   1285:                case LOC_WINEXIT:
                   1286:                        if(sweepstate){
                   1287:                                showr(&r);
                   1288:                                r.corner.x=event_x(e);
                   1289:                                r.corner.y=event_y(e);
                   1290:                                showr(&r);
                   1291:                                sweepstate=2;
                   1292:                        }
                   1293:                        break;
                   1294:                }
                   1295:        }
                   1296:        window_set(canvas, WIN_IGNORE_PICK_EVENT, LOC_DRAG, 0);
                   1297:        cursswitch(&normalcursor);
                   1298:        return r;
                   1299: }
                   1300: showr(rp)
                   1301:        register Rectangle *rp;
                   1302: {
                   1303:        register int x0=rp->origin.x;
                   1304:        register int y0=rp->origin.y;
                   1305:        register int x1=rp->corner.x;
                   1306:        register int y1=rp->corner.y;
                   1307:        pw_batch_on(pw);
                   1308:        pw_vector(pw, x0, y0, x1, y0, PIX_SRC^PIX_DST, 1);
                   1309:        if(y1>y0) y0++; /*avoid redoing corner*/
                   1310:        else y0--;
                   1311:        pw_vector(pw, x1, y0, x1, y1, PIX_SRC^PIX_DST, 1);
                   1312:        if(x1>x0) x1--;
                   1313:        else x1++;
                   1314:        pw_vector(pw, x1, y1, x0, y1, PIX_SRC^PIX_DST, 1);
                   1315:        pw_vector(pw, x0, y1, x0, y0, PIX_SRC^PIX_DST, 1);
                   1316:        pw_batch_off(pw);
                   1317: }
                   1318: 
                   1319: cursswitch(cp)
                   1320:        Cursor *cp;
                   1321: {
                   1322:        window_set(canvas, WIN_CURSOR, cp? *cp : normalcursor, 0);
                   1323: }
                   1324: 
                   1325: 
                   1326: /* sleep, but in 1/60's of second */
                   1327: /* #include <sys/time.h> */
                   1328: #include <signal.h>
                   1329: 
                   1330: #define        mask(s) (1<<((s)-1))
                   1331: #define        setvec(vec, a) \
                   1332:        vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
                   1333: 
                   1334: static int ringring;
                   1335: 
                   1336: sleephz(n)
                   1337:        unsigned n;
                   1338: {
                   1339:        int sleepx(), omask;
                   1340:        struct itimerval itv, oitv;
                   1341:        register struct itimerval *itp = &itv;
                   1342:        struct sigvec vec, ovec;
                   1343: 
                   1344:        if (n == 0)
                   1345:                return;
                   1346:        timerclear(&itp->it_interval);
                   1347:        timerclear(&itp->it_value);
                   1348:        if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
                   1349:                return;
                   1350:        setvec(ovec, SIG_DFL);
                   1351:        omask = sigblock(0);
                   1352:        n *= 16666;
                   1353:        itp->it_value.tv_sec = n / 1000000;
                   1354:        itp->it_value.tv_usec = n % 1000000;
                   1355:        if (timerisset(&oitv.it_value)) {
                   1356:                if (timercmp(&oitv.it_value, &itp->it_value, >))
                   1357:                        oitv.it_value.tv_sec -= itp->it_value.tv_sec;
                   1358:                else {
                   1359:                        itp->it_value = oitv.it_value;
                   1360:                        /*
                   1361:                         * This is a hack, but we must have time to
                   1362:                         * return from the setitimer after the alarm
                   1363:                         * or else it'll be restarted.  And, anyway,
                   1364:                         * sleep never did anything more than this before.
                   1365:                         */
                   1366:                        oitv.it_value.tv_sec = 1;
                   1367:                        oitv.it_value.tv_usec = 0;
                   1368:                }
                   1369:        }
                   1370:        setvec(vec, sleepx);
                   1371:        (void) sigvec(SIGALRM, &vec, &ovec);
                   1372:        ringring = 0;
                   1373:        (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
                   1374:        while (!ringring)
                   1375:                sigpause(omask &~ mask(SIGALRM));
                   1376:        (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
                   1377:        (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
                   1378: }
                   1379: 
                   1380: static
                   1381: sleepx()
                   1382: {
                   1383: 
                   1384:        ringring = 1;
                   1385: }

unix.superglobalmegacorp.com

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