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 <control.h> 8 9 typedef struct Keyboard Keyboard; 10 11 enum{ 12 SRegular = 0, 13 SShift = 1, 14 SCaps = 2, 15 SMask = 3, 16 Nstate = 4, 17 SControl = 4, 18 }; 19 20 struct Keyboard 21 { 22 Control; 23 CImage *image; 24 CImage *mask; 25 CImage *light; 26 CImage *textcolor; 27 CImage *bordercolor; 28 CFont *font; 29 CFont *ctlfont; 30 Image *im[Nstate]; 31 int border; 32 int lastbut; 33 int state; 34 char *key; 35 }; 36 37 enum{ 38 EBorder, 39 EBordercolor, 40 EFocus, 41 EFont, 42 EFormat, 43 EHide, 44 EImage, 45 ELight, 46 EMask, 47 ERect, 48 EReveal, 49 EShow, 50 ESize, 51 }; 52 53 static char *cmds[] = { 54 [EBorder] = "border", 55 [EBordercolor] = "bordercolor", 56 [EFocus] = "focus", 57 [EFont] = "font", 58 [EFormat] = "format", 59 [EHide] = "hide", 60 [EImage] = "image", 61 [ELight] = "light", 62 [EMask] = "mask", 63 [ERect] = "rect", 64 [EReveal] = "reveal", 65 [EShow] = "show", 66 [ESize] = "size", 67 nil 68 }; 69 70 enum 71 { 72 Nrow = 5 73 }; 74 75 static uchar wid [Nrow][16] = { 76 {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 30, }, 77 {24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, }, 78 {32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }, 79 {40, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }, 80 {30, 30, 80, 40, 42, 24, }, 81 }; 82 83 static char *keyregular[Nrow] = { 84 "`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0", 85 "->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0[\0]\0Del\0\0", 86 "Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0;\0'\0Enter\0\0", 87 "Shift\0z\0x\0c\0v\0b\0n\0m\0,\0.\0/\0Shift\0\0", 88 "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0" 89 }; 90 91 static char *keyshift[Nrow] = { 92 "~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0", 93 "->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0{\0}\0Del\0\0", 94 "Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0:\0\"\0Enter\0\0", 95 "Shift\0Z\0X\0C\0V\0B\0N\0M\0<\0>\0?\0Shift\0\0", 96 "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0" 97 }; 98 99 static char *keycaps[Nrow] = { 100 "`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0", 101 "->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0[\0]\0Del\0\0", 102 "Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0;\0'\0Enter\0\0", 103 "Shift\0Z\0X\0C\0V\0B\0N\0M\0,\0.\0/\0Shift\0\0", 104 "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0" 105 }; 106 107 static char *keycapsshift[Nrow] = { 108 "~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0", 109 "->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0{\0}\0Del\0\0", 110 "Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0:\0\"\0Enter\0\0", 111 "Shift\0z\0x\0c\0v\0b\0n\0m\0<\0>\0?\0Shift\0\0", 112 "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0" 113 }; 114 115 struct{ 116 char *name; 117 int val; 118 }keytab[] = { 119 "Shift", 0, 120 "Ctrl", 0, 121 "Alt", 0, 122 "Caps", 0, 123 "Del", '\177', 124 "Enter", '\n', 125 "Esc", '\033', 126 "<-", '\b', 127 "->", '\t', 128 "Scrib", 0x10000, 129 "Menu", 0x10001, 130 nil, 0, 131 }; 132 133 static char **keyset[Nstate] = { 134 keyregular, 135 keyshift, 136 keycaps, 137 keycapsshift, 138 }; 139 140 static void keyboardshow(Keyboard*); 141 static void keyup(Keyboard*, Point); 142 static void keydown(Keyboard*, Point); 143 static void keyresize(Keyboard*); 144 145 static void 146 keyboardmouse(Control *c, Mouse *m) 147 { 148 Keyboard *k; 149 150 k = (Keyboard *)c; 151 if(m->buttons==1) 152 keydown(k, m->xy); 153 else if(k->lastbut==1 && m->buttons==0) 154 keyup(k, m->xy); 155 k->lastbut = m->buttons; 156 } 157 158 static void 159 keyboardfree(Control *c) 160 { 161 int i; 162 Keyboard *k; 163 164 k = (Keyboard *)c; 165 _putctlimage(k->image); 166 _putctlimage(k->mask); 167 _putctlimage(k->light); 168 _putctlimage(k->textcolor); 169 _putctlimage(k->bordercolor); 170 _putctlfont(k->font); 171 _putctlfont(k->ctlfont); 172 for(i=0; i<nelem(k->im); i++) 173 freeimage(k->im[i]); 174 free(k->format); 175 } 176 177 static int 178 keyboardy(Keyboard *k, int row) 179 { 180 int dy; 181 182 if(row >= Nrow) 183 return k->rect.max.y-k->border; 184 dy = Dy(k->rect)-2*k->border; 185 return k->rect.min.y+k->border+(row*dy+Nrow-1)/Nrow; 186 } 187 188 static char* 189 whichkey(Keyboard *k, Point p, int *rowp, int *colp, Rectangle *rp) 190 { 191 uchar *wp; 192 char *kp; 193 int row, col, dx, dy, x, n, maxx; 194 Rectangle r; 195 196 r = insetrect(k->rect, k->border); 197 if(!ptinrect(p, r)) 198 return nil; 199 maxx = r.max.x; 200 dx = Dx(r); 201 dy = Dy(r); 202 row = (p.y - r.min.y)*Nrow/dy; 203 if(row >= Nrow) 204 row = Nrow-1; 205 r.min.y = keyboardy(k, row); 206 r.max.y = keyboardy(k, row+1); 207 x = r.min.x; 208 kp = keyset[k->state&SMask][row]; 209 wp = wid[row]; 210 for(col=0; *kp; col++,kp+=n+1){ 211 n = strlen(kp); 212 r.min.x = x; 213 r.max.x = x + (wp[col]*dx+255)/256; 214 if(kp[n+1] == '\0') 215 r.max.x = maxx; 216 if(r.max.x > p.x) 217 break; 218 x = r.max.x; 219 } 220 *rp = insetrect(r, 1); 221 *rowp = row; 222 *colp = col; 223 return kp; 224 } 225 226 static Rectangle 227 keyrect(Keyboard *k, int row, int col) 228 { 229 uchar *wp; 230 char *kp; 231 int i, x, n, dx; 232 Rectangle r; 233 Point p; 234 235 r = insetrect(k->rect, k->border); 236 p = r.min; 237 dx = Dx(r); 238 r.min.y = keyboardy(k, row); 239 r.max.y = keyboardy(k, row+1); 240 x = r.min.x; 241 kp = keyset[0][row]; 242 wp = wid[row]; 243 for(i=0; *kp; i++,kp+=n+1){ 244 n = strlen(kp); 245 r.min.x = x; 246 r.max.x = x + (wp[i]*dx+255)/256; 247 if(kp[n+1] == '\0') 248 r.max.x = p.x+dx; 249 if(i >= col) 250 break; 251 x = r.max.x; 252 } 253 return insetrect(r, 1); 254 } 255 256 static void 257 keydraw(Keyboard *k, int state) 258 { 259 Point p, q; 260 int row, col, x, dx, dy, nexty, n; 261 uchar *wp; 262 char *kp; 263 Rectangle r; 264 Font *f, *f1, *f2; 265 Image *im; 266 267 freeimage(k->im[state]); 268 k->im[state] = nil; 269 if(Dx(k->rect)-2*k->border <= 0) 270 return; 271 272 im = allocimage(display, k->rect, screen->chan, 0, ~0); 273 if(im == nil) 274 return; 275 k->im[state] = im; 276 277 r = insetrect(k->rect, k->border); 278 border(im, k->rect, k->border, k->bordercolor->image, ZP); 279 draw(im, r, k->image->image, nil, ZP); 280 dx = Dx(r); 281 dy = Dy(r); 282 p = r.min; 283 f1 = k->font->font; 284 f2 = k->ctlfont->font; 285 nexty = p.y; 286 for(row=0; row<Nrow; row++){ 287 x = p.x; 288 kp = keyset[state][row]; 289 wp = wid[row]; 290 r.min.y = nexty; 291 nexty = keyboardy(k, row+1); 292 r.max.y = nexty; 293 for(col=0; *kp; col++,kp+=n+1){ 294 r.min.x = x; 295 r.max.x = x + (wp[col]*dx+255)/256; 296 n = strlen(kp); 297 if(kp[n+1] == '\0') 298 r.max.x = p.x+dx; 299 if(row == Nrow-1) 300 r.max.y = p.y+dy; 301 if(n > 1) 302 f = f2; 303 else 304 f = f1; 305 q = _ctlalignpoint(r, stringnwidth(f, kp, n), f->height, Acenter); 306 _string(im, q, k->textcolor->image, 307 ZP, f, kp, nil, n, r, 308 nil, ZP, SoverD); 309 x = r.max.x; 310 if(kp[n+1]) 311 draw(im, Rect(x, r.min.y, x+1, r.max.y), 312 k->textcolor->image, nil, ZP); 313 } 314 if(row != Nrow-1) 315 draw(im, Rect(p.x, r.max.y, p.x+dx, r.max.y+1), 316 k->textcolor->image, nil, ZP); 317 } 318 } 319 320 static void 321 keyresize(Keyboard *k) 322 { 323 int i; 324 325 for(i=0; i<Nstate; i++) 326 keydraw(k, i); 327 } 328 329 static void 330 keyboardshow(Keyboard *k) 331 { 332 Rectangle r; 333 334 if (k->hidden) 335 return; 336 if(k->im[0]==nil || !eqrect(k->im[0]->r, k->rect)) 337 keyresize(k); 338 if(k->im[k->state&SMask] == nil) 339 return; 340 draw(k->screen, k->rect, k->im[k->state&SMask], nil, k->rect.min); 341 if(k->state & SShift){ 342 r = keyrect(k, 3, 0); 343 draw(k->screen, r, k->light->image, k->mask->image, ZP); 344 r = keyrect(k, 3, 11); 345 draw(k->screen, r, k->light->image, k->mask->image, ZP); 346 } 347 if(k->state & SCaps){ 348 r = keyrect(k, 2, 0); 349 draw(k->screen, r, k->light->image, k->mask->image, ZP); 350 } 351 if(k->state & SControl){ 352 r = keyrect(k, 4, 0); 353 draw(k->screen, r, k->light->image, k->mask->image, ZP); 354 } 355 flushimage(display, 1); 356 } 357 358 static void 359 keydown(Keyboard *k, Point p) 360 { 361 int row, col; 362 Rectangle r; 363 char *s; 364 365 s = whichkey(k, p, &row, &col, &r); 366 if(s == k->key) 367 return; 368 keyboardshow(k); 369 if(s != nil) 370 draw(k->screen, r, k->light->image, k->mask->image, ZP); 371 flushimage(display, 1); 372 k->key = s; 373 } 374 375 static int 376 keylookup(char *s) 377 { 378 int i; 379 380 for(i=0; keytab[i].name; i++) 381 if(strcmp(s, keytab[i].name) == 0) 382 return keytab[i].val; 383 return s[0]; 384 } 385 386 static void 387 keyup(Keyboard *k, Point p) 388 { 389 int row, col; 390 Rectangle r; 391 char *s; 392 int val; 393 394 s = whichkey(k, p, &row, &col, &r); 395 if(s == nil) 396 return; 397 val = keylookup(s); 398 if(k->state & SControl) 399 if(' '<val && val<0177) 400 val &= ~0x60; 401 if(strcmp(s, "Alt") == 0) 402 {;} 403 if(strcmp(s, "Ctrl") == 0){ 404 k->state ^= SControl; 405 }else 406 k->state &= ~SControl; 407 if(strcmp(s, "Shift")==0 || strcmp(s, "Caps")==0){ 408 if(strcmp(s, "Shift") == 0) 409 k->state ^= SShift; 410 if(strcmp(s, "Caps") == 0) 411 k->state ^= SCaps; 412 }else 413 k->state &= ~SShift; 414 keyboardshow(k); 415 if(val) 416 chanprint(k->event, k->format, k->name, val); 417 k->key = nil; 418 } 419 420 static void 421 keyboardctl(Control *c, CParse *cp) 422 { 423 int cmd; 424 Rectangle r; 425 Keyboard *k; 426 427 k = (Keyboard*)c; 428 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); 429 switch(cmd){ 430 default: 431 ctlerror("%q: unrecognized message '%s'", k->name, cp->str); 432 break; 433 case EBorder: 434 _ctlargcount(k, cp, 2); 435 if(cp->iargs[1] < 0) 436 ctlerror("%q: bad border: %c", k->name, cp->str); 437 k->border = cp->iargs[1]; 438 break; 439 case EBordercolor: 440 _ctlargcount(k, cp, 2); 441 _setctlimage(k, &k->bordercolor, cp->args[1]); 442 break; 443 case EFocus: 444 /* ignore focus change */ 445 break; 446 case EFont: 447 if(cp->nargs!=2 && cp->nargs!=3) 448 ctlerror("%q: bad font message '%s'", k->name, cp->str); 449 _setctlfont(k, &k->font, cp->args[1]); 450 if(cp->nargs == 3) 451 _setctlfont(k, &k->ctlfont, cp->args[2]); 452 else 453 _setctlfont(k, &k->ctlfont, cp->args[1]); 454 break; 455 case EFormat: 456 _ctlargcount(k, cp, 2); 457 k->format = ctlstrdup(cp->args[1]); 458 break; 459 case EHide: 460 _ctlargcount(k, cp, 1); 461 k->hidden = 1; 462 break; 463 case EImage: 464 _ctlargcount(k, cp, 2); 465 _setctlimage(k, &k->image, cp->args[1]); 466 break; 467 case ELight: 468 _ctlargcount(k, cp, 2); 469 _setctlimage(k, &k->light, cp->args[1]); 470 break; 471 case EMask: 472 _ctlargcount(k, cp, 2); 473 _setctlimage(k, &k->mask, cp->args[1]); 474 break; 475 case ERect: 476 _ctlargcount(k, cp, 5); 477 r.min.x = cp->iargs[1]; 478 r.min.y = cp->iargs[2]; 479 r.max.x = cp->iargs[3]; 480 r.max.y = cp->iargs[4]; 481 if(Dx(r)<0 || Dy(r)<0) 482 ctlerror("%q: bad rectangle: %s", k->name, cp->str); 483 k->rect = r; 484 keyboardshow(k); 485 break; 486 case EReveal: 487 _ctlargcount(k, cp, 1); 488 k->hidden = 0; 489 keyboardshow(k); 490 break; 491 case EShow: 492 _ctlargcount(k, cp, 1); 493 keyboardshow(k); 494 break; 495 case ESize: 496 if (cp->nargs == 3) 497 r.max = Pt(0x7fffffff, 0x7fffffff); 498 else{ 499 _ctlargcount(k, cp, 5); 500 r.max.x = cp->iargs[3]; 501 r.max.y = cp->iargs[4]; 502 } 503 r.min.x = cp->iargs[1]; 504 r.min.y = cp->iargs[2]; 505 if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y) 506 ctlerror("%q: bad sizes: %s", k->name, cp->str); 507 k->size.min = r.min; 508 k->size.max = r.max; 509 break; 510 } 511 } 512 513 Control* 514 createkeyboard(Controlset *cs, char *name) 515 { 516 Keyboard *k; 517 518 k = (Keyboard *)_createctl(cs, "keyboard", sizeof(Keyboard), name); 519 k->image = _getctlimage("white"); 520 k->mask = _getctlimage("opaque"); 521 k->light = _getctlimage("yellow"); 522 k->bordercolor = _getctlimage("black"); 523 k->textcolor = _getctlimage("black"); 524 k->font = _getctlfont("font"); 525 k->ctlfont = _getctlfont("font"); 526 k->format = ctlstrdup("%q: value 0x%x"); 527 k->border = 0; 528 k->lastbut = 0; 529 k->key = nil; 530 k->state = SRegular; 531 k->ctl = keyboardctl; 532 k->mouse = keyboardmouse; 533 k->exit = keyboardfree; 534 k->size = Rect(246, 2 + 5 * (k->font->font->height + 1), 512, 256); 535 return k; 536 } 537