diff options
Diffstat (limited to 'samterm/io.c')
| -rw-r--r-- | samterm/io.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/samterm/io.c b/samterm/io.c new file mode 100644 index 0000000..68211d8 --- /dev/null +++ b/samterm/io.c @@ -0,0 +1,332 @@ +#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(); + plumbstart(); +} + +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; + if(display->bufp > display->buf) + 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; +} + +void +frscroll(Frame *f, int n) +{ + Flayer *l = which; + Text *t = l->user1; + long p; + + if(nbrecv(mousectl->c, &mousectl->Mouse) < 0) + panic("mouse"); + + if(n < 0){ + if(sel > l->origin+f->p0){ + l->p0 = l->origin+f->p0; + l->p1 = sel; + }else{ + l->p0 = sel; + l->p1 = l->origin+f->p0; + } + scrorigin(l, 1, -n+1); + }else if(n == 0){ + sleep(25); + return; + }else{ + if(sel >= l->origin+f->p1){ + l->p0 = l->origin+f->p1; + l->p1 = sel; + }else{ + l->p0 = sel; + l->p1 = l->origin+f->p1; + } + p = l->origin; + if(l->origin+f->nchars != t->rasp.nrunes) + p += frcharofpt(f, Pt(l->scroll.max.x, l->scroll.min.y + n * f->font->height)); + scrorigin(l, 2, p); + } + + /* + * we must pull io from host while we are in frame(2) + */ + do{ + block = ~(1 << RHost); + waitforio(); + rcv(); + }while(t->lock); +} + +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; +} |