mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-15 11:20:03 +00:00
288 lines
4.2 KiB
C
288 lines
4.2 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <draw.h>
|
|
#include <thread.h>
|
|
#include <mouse.h>
|
|
#include <cursor.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->m;
|
|
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)
|
|
{
|
|
drawtopwindow();
|
|
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->m;
|
|
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 i, c;
|
|
|
|
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;
|
|
}
|