io.c (4793B)
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 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 60 getmouse(void) 61 { 62 if(readmouse(mousectl) < 0) 63 panic("mouse"); 64 } 65 66 void 67 mouseunblock(void) 68 { 69 got &= ~(1<<RMouse); 70 } 71 72 void 73 kbdblock(void) 74 { /* ca suffit */ 75 block = (1<<RKeyboard)|(1<<RPlumb); 76 } 77 78 int 79 button(int but) 80 { 81 getmouse(); 82 return mousep->buttons&(1<<(but-1)); 83 } 84 85 void 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 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 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* 190 rcvstring(void) 191 { 192 *hoststop = 0; 193 got &= ~(1<<RHost); 194 return (char*)hostp; 195 } 196 197 int 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 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 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 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 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 288 qpeekc(void) 289 { 290 return kbdc; 291 } 292 293 int 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 }