ref: cd747191012d0420ac631340d962da1f80cef0a5
dir: /sys/src/cmd/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 == 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; }