]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/samterm/io.c
samterm: avoid flushimage when theres nothing new to flush
[plan9front.git] / sys / src / cmd / samterm / io.c
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 {
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
51 getmouse(void)
52 {
53         if(readmouse(mousectl) < 0)
54                 panic("mouse");
55 }
56
57 void
58 mouseunblock(void)
59 {
60         got &= ~(1<<RMouse);
61 }
62
63 void
64 kbdblock(void)
65 {               /* ca suffit */
66         block = (1<<RKeyboard)|(1<<RPlumb);
67 }
68
69 int
70 button(int but)
71 {
72         getmouse();
73         return mousep->buttons&(1<<(but-1));
74 }
75
76 void
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
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         if(display->bufp > display->buf)
133                 flushimage(display, 1);
134         type = alt(alts);
135         switch(type){
136         case RHost:
137                 hostp = hostbuf[i].data;
138                 hoststop = hostbuf[i].data + hostbuf[i].n;
139                 block = 0;
140                 break;
141         case RPlumb:
142                 externload(i);
143                 break;
144         case RKeyboard:
145                 kbdc = r;
146                 break;
147         case RMouse:
148                 break;
149         case RResize:
150                 resized = 1;
151                 /* do the resize in line if we've finished initializing and we're not in a blocking state */
152                 if(hasunlocked && block==0 && RESIZED())
153                         resize();
154                 goto again;
155         }
156         got |= 1<<type;
157         return got; 
158 }
159
160 int
161 rcvchar(void)
162 {
163         int c;
164
165         if(!(got & (1<<RHost)))
166                 return -1;
167         c = *hostp++;
168         if(hostp == hoststop)
169                 got &= ~(1<<RHost);
170         return c;
171 }
172
173 char*
174 rcvstring(void)
175 {
176         *hoststop = 0;
177         got &= ~(1<<RHost);
178         return (char*)hostp;
179 }
180
181 int
182 getch(void)
183 {
184         int c;
185
186         while((c = rcvchar()) == -1){
187                 block = ~(1<<RHost);
188                 waitforio();
189                 block = 0;
190         }
191         return c;
192 }
193
194 int
195 externchar(void)
196 {
197         Rune r;
198
199     loop:
200         if(got & ((1<<RPlumb) & ~block)){
201                 plumbp += chartorune(&r, (char*)plumbp);
202                 if(plumbp >= plumbstop){
203                         got &= ~(1<<RPlumb);
204                         free(plumbbase);
205                 }
206                 if(r == 0)
207                         goto loop;
208                 return r;
209         }
210         return -1;
211 }
212
213 int kpeekc = -1;
214 int
215 ecankbd(void)
216 {
217         Rune r;
218
219         if(kpeekc >= 0)
220                 return 1;
221         if(nbrecv(keyboardctl->c, &r) > 0){
222                 kpeekc = r;
223                 return 1;
224         }
225         return 0;
226 }
227
228 int
229 ekbd(void)
230 {
231         int c;
232         Rune r;
233
234         if(kpeekc >= 0){
235                 c = kpeekc;
236                 kpeekc = -1;
237                 return c;
238         }
239         if(recv(keyboardctl->c, &r) < 0){
240                 fprint(2, "samterm: keybard recv error: %r\n");
241                 panic("kbd");
242         }
243         return r;
244 }
245
246 int
247 kbdchar(void)
248 {
249         int c, i;
250
251         c = externchar();
252         if(c > 0)
253                 return c;
254         if(got & (1<<RKeyboard)){
255                 c = kbdc;
256                 kbdc = -1;
257                 got &= ~(1<<RKeyboard);
258                 return c;
259         }
260         while(plumbc!=nil && nbrecv(plumbc, &i)>0){
261                 externload(i);
262                 c = externchar();
263                 if(c > 0)
264                         return c;
265         }
266         if(!ecankbd())
267                 return -1;
268         return ekbd();
269 }
270
271 int
272 qpeekc(void)
273 {
274         return kbdc;
275 }
276
277 int
278 RESIZED(void)
279 {
280         if(resized){
281                 if(getwindow(display, Refnone) < 0)
282                         panic("can't reattach to window");
283                 resized = 0;
284                 return 1;
285         }
286         return 0;
287 }