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