Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <cursor.h>
#include <event.h>
#include <bio.h>
#include "proof.h"

static  int     checkmouse(void);
static  int     buttondown(void);
static  char    *getmousestr(void);
static  char    *getkbdstr(int);

extern  Cursor  blot;
extern  char    *track;

Mouse   mouse;

void
mapscreen(void)
{
        if(initdraw(0, 0, "proof") < 0){
                fprint(2, "proof: initdraw failed: %r\n");
                exits("initdraw");
        }
        einit(Ekeyboard|Emouse);
}

void
clearscreen(void)
{
        draw(screen, screen->r, display->black, nil, ZP);
}

void
screenprint(char *fmt, ...)
{
        char buf[100];
        Point p;
        va_list args;

        va_start(args, fmt);
        vseprint(buf, &buf[sizeof buf], fmt, args);
        va_end(args);
        p = Pt(screen->clipr.min.x+40, screen->clipr.max.y-40);
        string(screen, p, display->black, ZP, font, buf);
}

#define Viewkey 0xb2

char *
getcmdstr(void)
{
        Event ev;
        int e;
        static ulong timekey = 0;
        ulong tracktm = 0;
        Dir *dir;

        if(track){
                if(timekey == 0)
                        timekey = etimer(0, 5000);
                dir = dirstat(track);
                if(dir != nil){
                        tracktm = dir->mtime;
                        free(dir);
                }
        }
        for (;;) {
                e = event(&ev);
                if(resized){
                        resized = 0;
                        return "p";
                }
                if ((e & Emouse) && ev.mouse.buttons) {
                        mouse = ev.mouse;
                        return getmousestr();
                } else if (e & Ekeyboard)
                        return getkbdstr(ev.kbdc);      /* sadly, no way to unget */
                else if (e & timekey) {
                        if((dir = dirstat(track)) != nil){
                                if(tracktm < dir->mtime){
                                        free(dir);
                                        return "q";
                                }
                                free(dir);
                        }
                }
        }
}

static char *
getkbdstr(int c0)
{
        static char buf[100];
        char *p;
        int c;

        if (c0 == '\n')
                return "";
        buf[0] = c0;
        buf[1] = 0;
        screenprint("%s", buf);
        for (p = buf+1; (c = ekbd()) != '\n' && c != '\r' && c != -1 && c != Viewkey; ) {
                if (c == '\b' && p > buf) {
                        *--p = ' ';
                } else {
                        *p++ = c;
                        *p = 0;
                }
                screenprint("%s", buf);
        }
        *p = 0;
        return buf;
}


#define button3(b)      ((b) & 4)
#define button2(b)      ((b) & 2)
#define button1(b)      ((b) & 1)
#define button23(b)     ((b) & 6)
#define button123(b)    ((b) & 7)

#define butcvt(b)       (1 << ((b) - 1))

static int buttondown(void)     /* report state of buttons, if any */
{
        if (!ecanmouse())       /* no event pending */
                return 0;
        mouse = emouse();       /* something, but it could be motion */
        return mouse.buttons & 7;
}

int waitdown(void)      /* wait until some button is down */
{
        while (!(mouse.buttons & 7))
                mouse = emouse();
        return mouse.buttons & 7;
}

int waitup(void)
{
        while (mouse.buttons & 7)
                mouse = emouse();
        return mouse.buttons & 7;
}

char *m3[]      = { "next", "prev", "page n", "again", "bigger", "smaller", "pan", "quit?", 0 };
char *m2[]      = { 0 };

enum { Next = 0, Prev, Page, Again, Bigger, Smaller, Pan, Quit };

Menu    mbut3   = { m3, 0, 0 };
Menu    mbut2   = { m2, 0, 0 };

int     last_hit;
int     last_but;

char *pan(void)
{
        Point dd, xy, lastxy, min, max;

        esetcursor(&blot);
        waitdown();
        xy = mouse.xy;
        do{
                lastxy = mouse.xy;
                mouse = emouse();
                dd = subpt(mouse.xy, lastxy);
                min = addpt(screen->clipr.min, dd);
                max = addpt(screen->clipr.max, dd);
                draw(screen, rectaddpt(screen->r, subpt(mouse.xy, lastxy)),
                        screen, nil, screen->r.min);
                if(mouse.xy.x < lastxy.x)       /* moved left, clear right */
                        draw(screen, Rect(max.x, screen->r.min.y, screen->r.max.x, screen->r.max.y),
                                display->white, nil, ZP);
                else    /* moved right, clear left*/
                        draw(screen, Rect(screen->r.min.x, screen->r.min.y, min.x, screen->r.max.y),
                                display->white, nil, ZP);
                if(mouse.xy.y < lastxy.y)       /* moved up, clear down */
                        draw(screen, Rect(screen->r.min.x, max.y, screen->r.max.x, screen->r.max.y),
                                display->white, nil, ZP);
                else            /* moved down, clear up */
                        draw(screen, Rect(screen->r.min.x, screen->r.min.y, screen->r.max.x, min.y),
                                display->white, nil, ZP);
                flushimage(display, 1);
        }while(mouse.buttons);

        xyoffset = addpt(xyoffset, subpt(mouse.xy, xy));

        esetcursor(0);
        return "p";
}

static char *
getmousestr(void)
{
        static char buf[64];

        checkmouse();
        if (last_but == 1)
                return "p";     /* repaint after panning */
        if (last_but == 2) {
                return "c";
        } else if (last_but == 3) {
                switch (last_hit) {
                case Next:
                        return "";
                case Prev:
                        return "-1";
                case Page:
                        screenprint("page? ");
                        return "c";
                case Again:
                        return "p";
                case Bigger:
                        snprint(buf, sizeof buf, "m%g", mag * 1.1);
                        return buf;
                case Smaller:
                        snprint(buf, sizeof buf, "m%g", mag / 1.1);
                        return buf;
                case Pan:
                        return pan();
                case Quit:
                        return "q";
                default:
                        return "c";
                }
        } else {                /* button 1 or bail out */
                return "c";
        }
}

static int
checkmouse(void)        /* return button touched if any */
{
        int c, b;
        char *p;
        extern int confirm(int);

        b = waitdown();
        last_but = 0;
        last_hit = -1;
        c = 0;
        if (button3(b)) {
                last_hit = emenuhit(3, &mouse, &mbut3);
                last_but = 3;
        } else if (button2(b)) {
                last_hit = emenuhit(2, &mouse, &mbut2);
                last_but = 2;
        } else {                /* button1() */
                pan();
                last_but = 1;
        }
        waitup();
        if (last_but == 3 && last_hit >= 0) {
                p = m3[last_hit];
                c = p[strlen(p) - 1];
        }
        if (c == '?' && !confirm(last_but))
                last_hit = -1;
        return last_but;
}

Cursor deadmouse = {
        { 0, 0},        /* offset */
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
          0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
          0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
          0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
          0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
};

Cursor blot ={
        { 0, 0 },
        { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
          0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
          0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
          0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
        { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
          0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
          0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
          0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }
};

Cursor skull ={
        { 0, 0 },
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
          0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
          0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
          0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
          0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
          0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
          0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
};

confirm(int but)        /* ask for confirmation if menu item ends with '?' */
{
        int c;
        static int but_cvt[8] = { 0, 1, 2, 0, 3, 0, 0, 0 };

        esetcursor(&skull);
        c = waitdown();
        waitup();
        esetcursor(0);
        return but == but_cvt[c];
}