ref: 69d4e9e10a45517ad32d399bfbf61390d5a43208
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 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; }