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