1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <cursor.h>
7 #include <keyboard.h>
8 #include <frame.h>
9 #include "flayer.h"
10 #include "samterm.h"
11 
12 int	protodebug;
13 int	cursorfd;
14 int	plumbfd = -1;
15 int	input;
16 int	got;
17 int	block;
18 int	kbdc;
19 int	resized;
20 uchar	*hostp;
21 uchar	*hoststop;
22 uchar	*plumbbase;
23 uchar	*plumbp;
24 uchar	*plumbstop;
25 Channel	*plumbc;
26 Channel	*hostc;
27 Mousectl	*mousectl;
28 Mouse	*mousep;
29 Keyboardctl *keyboardctl;
30 void	panic(char*);
31 
32 void
initio(void)33 initio(void)
34 {
35 	threadsetname("main");
36 	if(protodebug) print("mouse\n");
37 	mousectl = initmouse(nil, display->image);
38 	if(mousectl == nil){
39 		fprint(2, "samterm: mouse init failed: %r\n");
40 		threadexitsall("mouse");
41 	}
42 	mousep = &mousectl->m;
43 	if(protodebug) print("kbd\n");
44 	keyboardctl = initkeyboard(nil);
45 	if(keyboardctl == nil){
46 		fprint(2, "samterm: keyboard init failed: %r\n");
47 		threadexitsall("kbd");
48 	}
49 	if(protodebug) print("hoststart\n");
50 	hoststart();
51 	if(protodebug) print("plumbstart\n");
52 	if(plumbstart() < 0){
53 		if(protodebug) print("extstart\n");
54 		extstart();
55 	}
56 	if(protodebug) print("initio done\n");
57 }
58 
59 void
getmouse(void)60 getmouse(void)
61 {
62 	if(readmouse(mousectl) < 0)
63 		panic("mouse");
64 }
65 
66 void
mouseunblock(void)67 mouseunblock(void)
68 {
69 	got &= ~(1<<RMouse);
70 }
71 
72 void
kbdblock(void)73 kbdblock(void)
74 {		/* ca suffit */
75 	block = (1<<RKeyboard)|(1<<RPlumb);
76 }
77 
78 int
button(int but)79 button(int but)
80 {
81 	getmouse();
82 	return mousep->buttons&(1<<(but-1));
83 }
84 
85 void
externload(int i)86 externload(int i)
87 {
88 	drawtopwindow();
89 	plumbbase = malloc(plumbbuf[i].n);
90 	if(plumbbase == 0)
91 		return;
92 	memmove(plumbbase, plumbbuf[i].data, plumbbuf[i].n);
93 	plumbp = plumbbase;
94 	plumbstop = plumbbase + plumbbuf[i].n;
95 	got |= 1<<RPlumb;
96 }
97 
98 int
waitforio(void)99 waitforio(void)
100 {
101 	Alt alts[NRes+1];
102 	Rune r;
103 	int i;
104 	ulong type;
105 
106 again:
107 	alts[RPlumb].c = plumbc;
108 	alts[RPlumb].v = &i;
109 	alts[RPlumb].op = CHANRCV;
110 	if((block & (1<<RPlumb)) || plumbc == nil)
111 		alts[RPlumb].op = CHANNOP;
112 
113 	alts[RHost].c = hostc;
114 	alts[RHost].v = &i;
115 	alts[RHost].op = CHANRCV;
116 	if(block & (1<<RHost))
117 		alts[RHost].op = CHANNOP;
118 
119 	alts[RKeyboard].c = keyboardctl->c;
120 	alts[RKeyboard].v = &r;
121 	alts[RKeyboard].op = CHANRCV;
122 	if(block & (1<<RKeyboard))
123 		alts[RKeyboard].op = CHANNOP;
124 
125 	alts[RMouse].c = mousectl->c;
126 	alts[RMouse].v = &mousectl->m;
127 	alts[RMouse].op = CHANRCV;
128 	if(block & (1<<RMouse))
129 		alts[RMouse].op = CHANNOP;
130 
131 	alts[RResize].c = mousectl->resizec;
132 	alts[RResize].v = nil;
133 	alts[RResize].op = CHANRCV;
134 	if(block & (1<<RResize))
135 		alts[RResize].op = CHANNOP;
136 
137 	if(protodebug) print("waitforio %c%c%c%c%c\n",
138 		"h-"[alts[RHost].op == CHANNOP],
139 		"k-"[alts[RKeyboard].op == CHANNOP],
140 		"m-"[alts[RMouse].op == CHANNOP],
141 		"p-"[alts[RPlumb].op == CHANNOP],
142 		"R-"[alts[RResize].op == CHANNOP]);
143 
144 	alts[NRes].op = CHANEND;
145 
146 	if(got & ~block)
147 		return got & ~block;
148 	flushimage(display, 1);
149 	type = alt(alts);
150 	switch(type){
151 	case RHost:
152 		if(0) print("hostalt recv %d %d\n", i, hostbuf[i].n);
153 		hostp = hostbuf[i].data;
154 		hoststop = hostbuf[i].data + hostbuf[i].n;
155 		block = 0;
156 		break;
157 	case RPlumb:
158 		externload(i);
159 		break;
160 	case RKeyboard:
161 		kbdc = r;
162 		break;
163 	case RMouse:
164 		break;
165 	case RResize:
166 		resized = 1;
167 		/* do the resize in line if we've finished initializing and we're not in a blocking state */
168 		if(hasunlocked && block==0 && RESIZED())
169 			resize();
170 		goto again;
171 	}
172 	got |= 1<<type;
173 	return got;
174 }
175 
176 int
rcvchar(void)177 rcvchar(void)
178 {
179 	int c;
180 
181 	if(!(got & (1<<RHost)))
182 		return -1;
183 	c = *hostp++;
184 	if(hostp == hoststop)
185 		got &= ~(1<<RHost);
186 	return c;
187 }
188 
189 char*
rcvstring(void)190 rcvstring(void)
191 {
192 	*hoststop = 0;
193 	got &= ~(1<<RHost);
194 	return (char*)hostp;
195 }
196 
197 int
getch(void)198 getch(void)
199 {
200 	int c;
201 
202 	while((c = rcvchar()) == -1){
203 		block = ~(1<<RHost);
204 		waitforio();
205 		block = 0;
206 	}
207 	return c;
208 }
209 
210 int
externchar(void)211 externchar(void)
212 {
213 	Rune r;
214 
215     loop:
216 	if(got & ((1<<RPlumb) & ~block)){
217 		plumbp += chartorune(&r, (char*)plumbp);
218 		if(plumbp >= plumbstop){
219 			got &= ~(1<<RPlumb);
220 			free(plumbbase);
221 		}
222 		if(r == 0)
223 			goto loop;
224 		return r;
225 	}
226 	return -1;
227 }
228 
229 int kpeekc = -1;
230 int
ecankbd(void)231 ecankbd(void)
232 {
233 	Rune r;
234 
235 	if(kpeekc >= 0)
236 		return 1;
237 	if(nbrecv(keyboardctl->c, &r) > 0){
238 		kpeekc = r;
239 		return 1;
240 	}
241 	return 0;
242 }
243 
244 int
ekbd(void)245 ekbd(void)
246 {
247 	int c;
248 	Rune r;
249 
250 	if(kpeekc >= 0){
251 		c = kpeekc;
252 		kpeekc = -1;
253 		return c;
254 	}
255 	if(recv(keyboardctl->c, &r) < 0){
256 		fprint(2, "samterm: keybard recv error: %r\n");
257 		panic("kbd");
258 	}
259 	return r;
260 }
261 
262 int
kbdchar(void)263 kbdchar(void)
264 {
265 	int c, i;
266 
267 	c = externchar();
268 	if(c > 0)
269 		return c;
270 	if(got & (1<<RKeyboard)){
271 		c = kbdc;
272 		kbdc = -1;
273 		got &= ~(1<<RKeyboard);
274 		return c;
275 	}
276 	while(plumbc!=nil && nbrecv(plumbc, &i)>0){
277 		externload(i);
278 		c = externchar();
279 		if(c > 0)
280 			return c;
281 	}
282 	if(!ecankbd())
283 		return -1;
284 	return ekbd();
285 }
286 
287 int
qpeekc(void)288 qpeekc(void)
289 {
290 	return kbdc;
291 }
292 
293 int
RESIZED(void)294 RESIZED(void)
295 {
296 	if(resized){
297 		if(getwindow(display, Refnone) < 0)
298 			panic("can't reattach to window");
299 		resized = 0;
300 		return 1;
301 	}
302 	return 0;
303 }
304