Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <keyboard.h>
#include <frame.h>
#include "flayer.h"
#include "samterm.h"

int     cursorfd;
int     plumbfd = -1;
int     input;
int     got;
int     block;
int     kbdc;
int     resized;
uchar   *hostp;
uchar   *hoststop;
uchar   *plumbbase;
uchar   *plumbp;
uchar   *plumbstop;
Channel *plumbc;
Channel *hostc;
Mousectl        *mousectl;
Mouse   *mousep;
Keyboardctl *keyboardctl;
void    panic(char*);

void
initio(void)
{
        threadsetname("main");
        mousectl = initmouse(nil, display->image);
        if(mousectl == nil){
                fprint(2, "samterm: mouse init failed: %r\n");
                threadexitsall("mouse");
        }
        mousep = mousectl;
        keyboardctl = initkeyboard(nil);
        if(keyboardctl == nil){
                fprint(2, "samterm: keyboard init failed: %r\n");
                threadexitsall("kbd");
        }
        hoststart();
        if(plumbstart() < 0)
                extstart();
}

void
getmouse(void)
{
        if(readmouse(mousectl) < 0)
                panic("mouse");
}

void
mouseunblock(void)
{
        got &= ~(1<<RMouse);
}

void
kbdblock(void)
{               /* ca suffit */
        block = (1<<RKeyboard)|(1<<RPlumb);
}

int
button(int but)
{
        getmouse();
        return mousep->buttons&(1<<(but-1));
}

void
externload(int i)
{
        plumbbase = malloc(plumbbuf[i].n);
        if(plumbbase == 0)
                return;
        memmove(plumbbase, plumbbuf[i].data, plumbbuf[i].n);
        plumbp = plumbbase;
        plumbstop = plumbbase + plumbbuf[i].n;
        got |= 1<<RPlumb;
}

int
waitforio(void)
{
        Alt alts[NRes+1];
        Rune r;
        int i;
        ulong type;

again:

        alts[RPlumb].c = plumbc;
        alts[RPlumb].v = &i;
        alts[RPlumb].op = CHANRCV;
        if((block & (1<<RPlumb)) || plumbc == nil)
                alts[RPlumb].op = CHANNOP;

        alts[RHost].c = hostc;
        alts[RHost].v = &i;
        alts[RHost].op = CHANRCV;
        if(block & (1<<RHost))
                alts[RHost].op = CHANNOP;

        alts[RKeyboard].c = keyboardctl->c;
        alts[RKeyboard].v = &r;
        alts[RKeyboard].op = CHANRCV;
        if(block & (1<<RKeyboard))
                alts[RKeyboard].op = CHANNOP;

        alts[RMouse].c = mousectl->c;
        alts[RMouse].v = &mousectl->Mouse;
        alts[RMouse].op = CHANRCV;
        if(block & (1<<RMouse))
                alts[RMouse].op = CHANNOP;

        alts[RResize].c = mousectl->resizec;
        alts[RResize].v = nil;
        alts[RResize].op = CHANRCV;
        if(block & (1<<RResize))
                alts[RResize].op = CHANNOP;

        alts[NRes].op = CHANEND;

        if(got & ~block)
                return got & ~block;
        flushimage(display, 1);
        type = alt(alts);
        switch(type){
        case RHost:
                hostp = hostbuf[i].data;
                hoststop = hostbuf[i].data + hostbuf[i].n;
                block = 0;
                break;
        case RPlumb:
                externload(i);
                break;
        case RKeyboard:
                kbdc = r;
                break;
        case RMouse:
                break;
        case RResize:
                resized = 1;
                /* do the resize in line if we've finished initializing and we're not in a blocking state */
                if(hasunlocked && block==0 && RESIZED())
                        resize();
                goto again;
        }
        got |= 1<<type;
        return got; 
}

int
rcvchar(void)
{
        int c;

        if(!(got & (1<<RHost)))
                return -1;
        c = *hostp++;
        if(hostp == hoststop)
                got &= ~(1<<RHost);
        return c;
}

char*
rcvstring(void)
{
        *hoststop = 0;
        got &= ~(1<<RHost);
        return (char*)hostp;
}

int
getch(void)
{
        int c;

        while((c = rcvchar()) == -1){
                block = ~(1<<RHost);
                waitforio();
                block = 0;
        }
        return c;
}

int
externchar(void)
{
        Rune r;

    loop:
        if(got & ((1<<RPlumb) & ~block)){
                plumbp += chartorune(&r, (char*)plumbp);
                if(plumbp >= plumbstop){
                        got &= ~(1<<RPlumb);
                        free(plumbbase);
                }
                if(r == 0)
                        goto loop;
                return r;
        }
        return -1;
}

int kpeekc = -1;
int
ecankbd(void)
{
        Rune r;

        if(kpeekc >= 0)
                return 1;
        if(nbrecv(keyboardctl->c, &r) > 0){
                kpeekc = r;
                return 1;
        }
        return 0;
}

int
ekbd(void)
{
        int c;
        Rune r;

        if(kpeekc >= 0){
                c = kpeekc;
                kpeekc = -1;
                return c;
        }
        if(recv(keyboardctl->c, &r) < 0){
                fprint(2, "samterm: keybard recv error: %r\n");
                panic("kbd");
        }
        return r;
}

int
kbdchar(void)
{
        int c, i;

        c = externchar();
        if(c > 0)
                return c;
        if(got & (1<<RKeyboard)){
                c = kbdc;
                kbdc = -1;
                got &= ~(1<<RKeyboard);
                return c;
        }
        while(plumbc!=nil && nbrecv(plumbc, &i)>0){
                externload(i);
                c = externchar();
                if(c > 0)
                        return c;
        }
        if(!ecankbd())
                return -1;
        return ekbd();
}

int
qpeekc(void)
{
        return kbdc;
}

int
RESIZED(void)
{
        if(resized){
                if(getwindow(display, Refnone) < 0)
                        panic("can't reattach to window");
                resized = 0;
                return 1;
        }
        return 0;
}