ref: 7c078308937f364f85ca6b79371508127510372f
dir: /samterm/io.c/
#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){
fprint(2, "samterm: mouse init failed: %r\n");
threadexitsall("mouse");
}
mousep = mousectl;
keyboardctl = initkeyboard(nil);
if(!keyboardctl){
fprint(2, "samterm: keyboard init failed: %r\n");
threadexitsall("kbd");
}
hoststart();
plumbstart();
}
void
mouseunblock(void)
{
got &= ~(1 << RMouse);
}
void
kbdblock(void)
{ /* ca suffit */
block = (1 << RKeyboard) | (1 << RPlumb);
}
int
button(int but)
{
if(readmouse(mousectl) < 0)
panic("mouse");
return mousep->buttons & (1 << (but - 1));
}
void
externload(int i)
{
plumbbase = malloc(plumbbuf[i].n);
if(!plumbbase)
return;
memmove(plumbbase, plumbbuf[i].data, plumbbuf[i].n);
plumbp = plumbbase;
plumbstop = plumbbase + plumbbuf[i].n;
got |= 1 << RPlumb;
}
int
waitforio(int blk)
{
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 = blk? CHANEND : CHANNOBLK;
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;
if(blk)
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;
}
return got |= 1 << type;
}
void
setblock(int set)
{
block = set;
}
void
frscroll(Frame *, int n)
{
int b;
b = block;
block = ~(1 << RHost);
got = 0;
flscroll(which, n);
block = b;
got = 0;
}
int
rcvchar(void)
{
int c;
c = -1;
if(got & (1 << RHost)){
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(1);
}
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 && 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;
}