| #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; | 
 | } |