|  | #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	protodebug; | 
|  | 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"); | 
|  | if(protodebug) print("mouse\n"); | 
|  | mousectl = initmouse(nil, display->image); | 
|  | if(mousectl == nil){ | 
|  | fprint(2, "samterm: mouse init failed: %r\n"); | 
|  | threadexitsall("mouse"); | 
|  | } | 
|  | mousep = &mousectl->m; | 
|  | if(protodebug) print("kbd\n"); | 
|  | keyboardctl = initkeyboard(nil); | 
|  | if(keyboardctl == nil){ | 
|  | fprint(2, "samterm: keyboard init failed: %r\n"); | 
|  | threadexitsall("kbd"); | 
|  | } | 
|  | if(protodebug) print("hoststart\n"); | 
|  | hoststart(); | 
|  | if(protodebug) print("plumbstart\n"); | 
|  | if(plumbstart() < 0){ | 
|  | if(protodebug) print("extstart\n"); | 
|  | extstart(); | 
|  | } | 
|  | if(protodebug) print("initio done\n"); | 
|  | } | 
|  |  | 
|  | 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; | 
|  |  | 
|  | if(protodebug) print("waitforio %c%c%c%c%c\n", | 
|  | "h-"[alts[RHost].op == CHANNOP], | 
|  | "k-"[alts[RKeyboard].op == CHANNOP], | 
|  | "m-"[alts[RMouse].op == CHANNOP], | 
|  | "p-"[alts[RPlumb].op == CHANNOP], | 
|  | "R-"[alts[RResize].op == CHANNOP]); | 
|  |  | 
|  | alts[NRes].op = CHANEND; | 
|  |  | 
|  | if(got & ~block) | 
|  | return got & ~block; | 
|  | flushimage(display, 1); | 
|  | type = alt(alts); | 
|  | switch(type){ | 
|  | case RHost: | 
|  | if(0) print("hostalt recv %d %d\n", i, hostbuf[i].n); | 
|  | 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; | 
|  | } |