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