void pipectl(void *v) { Window *w; Event *e; w = v; proccreate(wineventproc, w, STACK); windormant(w); winsetaddr(w, "0", 0); for(;;){ e = recvp(w->cevent); switch(e->c1){ default: Unknown: fprint(2, "unknown message %c%c\n", e->c1, e->c2); break; case 'E': /* write to body; can't affect us */ break; case 'F': /* generated by our actions; ignore */ break; case 'K': /* ignore */ break; case 'M': switch(e->c2){ case 'x': case 'X': execevent(w, e, pipecommand); break; case 'l': /* reflect all searches back to acme */ case 'L': if(e->flag & 2) recvp(w->cevent); winwriteevent(w, e); break; case 'I': /* modify away; we don't care */ case 'i': case 'D': case 'd': break; default: goto Unknown; } } } }
void mainctl(void *v) { Window *w; Event *e; int delta, pendingS, pendingK; uint32_t hostpt, endpt; char tmp[32]; w = v; proccreate(wineventproc, w, STACK); hostpt = 0; endpt = 0; winsetaddr(w, "0", 0); pendingS = 0; pendingK = 0; for(;;){ if(debug) fprint(2, "input range %lud-%lud\n", hostpt, endpt); e = recvp(w->cevent); if(debug) fprint(2, "msg: %C %C %d %d %d %d %q\n", e->c1 ? e->c1 : ' ', e->c2 ? e->c2 : ' ', e->q0, e->q1, e->flag, e->nb, e->b); switch(e->c1){ default: Unknown: fprint(2, "unknown message %c%c\n", e->c1, e->c2); break; case 'C': /* input needed for /dev/cons */ if(pendingS) pendingK = 1; else hostpt += sendinput(w, hostpt, &endpt); break; case 'S': /* output to stdout */ sprint(tmp, "#%lud", hostpt); winsetaddr(w, tmp, 0); write(w->data, e->b, e->nb); pendingS += e->nr; break; case 'E': /* write to tag or body; body happens due to sendit */ delta = e->q1-e->q0; if(e->c2=='I'){ endpt += delta; if(e->q0 < hostpt) hostpt += delta; else hostpt += sendinput(w, hostpt, &endpt); break; } if(!islower(e->c2)) fprint(2, "win msg: %C %C %d %d %d %d %q\n", e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b); break; case 'F': /* generated by our actions (specifically case 'S' above) */ delta = e->q1-e->q0; if(e->c2=='D'){ /* we know about the delete by _sendinput */ break; } if(e->c2=='I'){ pendingS -= e->q1 - e->q0; if(pendingS < 0) fprint(2, "win: pendingS = %d\n", pendingS); if(e->q0 != hostpt) fprint(2, "win: insert at %d expected %lud\n", e->q0, hostpt); endpt += delta; hostpt += delta; sendp(writechan, nil); if(pendingS == 0 && pendingK){ pendingK = 0; hostpt += sendinput(w, hostpt, &endpt); } break; } if(!islower(e->c2)) fprint(2, "win msg: %C %C %d %d %d %d %q\n", e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b); break; case 'K': delta = e->q1-e->q0; switch(e->c2){ case 'D': endpt -= delta; if(e->q1 < hostpt) hostpt -= delta; else if(e->q0 < hostpt) hostpt = e->q0; break; case 'I': delta = e->q1 - e->q0; endpt += delta; if(endpt < e->q1) /* just in case */ endpt = e->q1; if(e->q0 < hostpt) hostpt += delta; if(e->nr>0 && e->r[e->nr-1]==0x7F){ write(notepg, "interrupt", 9); hostpt = endpt; break; } if(e->q0 >= hostpt && hasboundary(e->r, e->nr)){ /* * If we are between the S message (which * we processed by inserting text in the * window) and the F message notifying us * that the text has been inserted, then our * impression of the hostpt and acme's * may be different. This could be seen if you * hit enter a bunch of times in a con * session. To work around the unreliability, * only send input if we don't have an S pending. * The same race occurs between when a character * is typed and when we get notice of it, but * since characters tend to be typed at the end * of the buffer, we don't run into it. There's * no workaround possible for this typing race, * since we can't tell when the user has typed * something but we just haven't been notified. */ if(pendingS) pendingK = 1; else hostpt += sendinput(w, hostpt, &endpt); } break; } break; case 'M': /* mouse */ delta = e->q1-e->q0; switch(e->c2){ case 'x': case 'X': execevent(w, e, command); break; case 'l': /* reflect all searches back to acme */ case 'L': if(e->flag & 2) recvp(w->cevent); winwriteevent(w, e); break; case 'I': endpt += delta; if(e->q0 < hostpt) hostpt += delta; else hostpt += sendinput(w, hostpt, &endpt); break; case 'D': endpt -= delta; if(e->q1 < hostpt) hostpt -= delta; else if(e->q0 < hostpt) hostpt = e->q0; break; case 'd': /* modify away; we don't care */ case 'i': break; default: goto Unknown; } } } }