180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <draw.h>
480ee5cbfSDavid du Colombier #include <thread.h>
580ee5cbfSDavid du Colombier #include <mouse.h>
680ee5cbfSDavid du Colombier #include <keyboard.h>
780ee5cbfSDavid du Colombier #include <control.h>
880ee5cbfSDavid du Colombier
980ee5cbfSDavid du Colombier typedef struct Keyboard Keyboard;
1080ee5cbfSDavid du Colombier
1180ee5cbfSDavid du Colombier enum{
1280ee5cbfSDavid du Colombier SRegular = 0,
1380ee5cbfSDavid du Colombier SShift = 1,
1480ee5cbfSDavid du Colombier SCaps = 2,
1580ee5cbfSDavid du Colombier SMask = 3,
1680ee5cbfSDavid du Colombier Nstate = 4,
1780ee5cbfSDavid du Colombier SControl = 4,
1880ee5cbfSDavid du Colombier };
1980ee5cbfSDavid du Colombier
2080ee5cbfSDavid du Colombier struct Keyboard
2180ee5cbfSDavid du Colombier {
2280ee5cbfSDavid du Colombier Control;
2380ee5cbfSDavid du Colombier CImage *image;
2480ee5cbfSDavid du Colombier CImage *mask;
2580ee5cbfSDavid du Colombier CImage *light;
2680ee5cbfSDavid du Colombier CImage *textcolor;
2780ee5cbfSDavid du Colombier CImage *bordercolor;
2880ee5cbfSDavid du Colombier CFont *font;
2980ee5cbfSDavid du Colombier CFont *ctlfont;
3080ee5cbfSDavid du Colombier Image *im[Nstate];
3180ee5cbfSDavid du Colombier int border;
3280ee5cbfSDavid du Colombier int lastbut;
3380ee5cbfSDavid du Colombier int state;
3480ee5cbfSDavid du Colombier char *key;
3580ee5cbfSDavid du Colombier };
3680ee5cbfSDavid du Colombier
3780ee5cbfSDavid du Colombier enum{
3880ee5cbfSDavid du Colombier EBorder,
3980ee5cbfSDavid du Colombier EBordercolor,
4080ee5cbfSDavid du Colombier EFocus,
4180ee5cbfSDavid du Colombier EFont,
4280ee5cbfSDavid du Colombier EFormat,
439a747e4fSDavid du Colombier EHide,
4480ee5cbfSDavid du Colombier EImage,
4580ee5cbfSDavid du Colombier ELight,
4680ee5cbfSDavid du Colombier EMask,
4780ee5cbfSDavid du Colombier ERect,
489a747e4fSDavid du Colombier EReveal,
4980ee5cbfSDavid du Colombier EShow,
509a747e4fSDavid du Colombier ESize,
5180ee5cbfSDavid du Colombier };
5280ee5cbfSDavid du Colombier
5380ee5cbfSDavid du Colombier static char *cmds[] = {
5480ee5cbfSDavid du Colombier [EBorder] = "border",
5580ee5cbfSDavid du Colombier [EBordercolor] = "bordercolor",
5680ee5cbfSDavid du Colombier [EFocus] = "focus",
5780ee5cbfSDavid du Colombier [EFont] = "font",
5880ee5cbfSDavid du Colombier [EFormat] = "format",
599a747e4fSDavid du Colombier [EHide] = "hide",
6080ee5cbfSDavid du Colombier [EImage] = "image",
6180ee5cbfSDavid du Colombier [ELight] = "light",
6280ee5cbfSDavid du Colombier [EMask] = "mask",
6380ee5cbfSDavid du Colombier [ERect] = "rect",
649a747e4fSDavid du Colombier [EReveal] = "reveal",
6580ee5cbfSDavid du Colombier [EShow] = "show",
669a747e4fSDavid du Colombier [ESize] = "size",
6780ee5cbfSDavid du Colombier nil
6880ee5cbfSDavid du Colombier };
6980ee5cbfSDavid du Colombier
7080ee5cbfSDavid du Colombier enum
7180ee5cbfSDavid du Colombier {
7280ee5cbfSDavid du Colombier Nrow = 5
7380ee5cbfSDavid du Colombier };
7480ee5cbfSDavid du Colombier
7580ee5cbfSDavid du Colombier static uchar wid [Nrow][16] = {
7680ee5cbfSDavid du Colombier {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 30, },
7780ee5cbfSDavid du Colombier {24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, },
7880ee5cbfSDavid du Colombier {32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, },
7980ee5cbfSDavid du Colombier {40, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, },
8080ee5cbfSDavid du Colombier {30, 30, 80, 40, 42, 24, },
8180ee5cbfSDavid du Colombier };
8280ee5cbfSDavid du Colombier
8380ee5cbfSDavid du Colombier static char *keyregular[Nrow] = {
8480ee5cbfSDavid du Colombier "`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0",
8580ee5cbfSDavid du Colombier "->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0[\0]\0Del\0\0",
8680ee5cbfSDavid du Colombier "Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0;\0'\0Enter\0\0",
8780ee5cbfSDavid du Colombier "Shift\0z\0x\0c\0v\0b\0n\0m\0,\0.\0/\0Shift\0\0",
8880ee5cbfSDavid du Colombier "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
8980ee5cbfSDavid du Colombier };
9080ee5cbfSDavid du Colombier
9180ee5cbfSDavid du Colombier static char *keyshift[Nrow] = {
9280ee5cbfSDavid du Colombier "~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0",
9380ee5cbfSDavid du Colombier "->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0{\0}\0Del\0\0",
9480ee5cbfSDavid du Colombier "Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0:\0\"\0Enter\0\0",
9580ee5cbfSDavid du Colombier "Shift\0Z\0X\0C\0V\0B\0N\0M\0<\0>\0?\0Shift\0\0",
9680ee5cbfSDavid du Colombier "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
9780ee5cbfSDavid du Colombier };
9880ee5cbfSDavid du Colombier
9980ee5cbfSDavid du Colombier static char *keycaps[Nrow] = {
10080ee5cbfSDavid du Colombier "`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0",
10180ee5cbfSDavid du Colombier "->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0[\0]\0Del\0\0",
10280ee5cbfSDavid du Colombier "Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0;\0'\0Enter\0\0",
10380ee5cbfSDavid du Colombier "Shift\0Z\0X\0C\0V\0B\0N\0M\0,\0.\0/\0Shift\0\0",
10480ee5cbfSDavid du Colombier "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
10580ee5cbfSDavid du Colombier };
10680ee5cbfSDavid du Colombier
10780ee5cbfSDavid du Colombier static char *keycapsshift[Nrow] = {
10880ee5cbfSDavid du Colombier "~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0",
10980ee5cbfSDavid du Colombier "->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0{\0}\0Del\0\0",
11080ee5cbfSDavid du Colombier "Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0:\0\"\0Enter\0\0",
11180ee5cbfSDavid du Colombier "Shift\0z\0x\0c\0v\0b\0n\0m\0<\0>\0?\0Shift\0\0",
11280ee5cbfSDavid du Colombier "Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"
11380ee5cbfSDavid du Colombier };
11480ee5cbfSDavid du Colombier
11580ee5cbfSDavid du Colombier struct{
11680ee5cbfSDavid du Colombier char *name;
11780ee5cbfSDavid du Colombier int val;
11880ee5cbfSDavid du Colombier }keytab[] = {
11980ee5cbfSDavid du Colombier "Shift", 0,
12080ee5cbfSDavid du Colombier "Ctrl", 0,
12180ee5cbfSDavid du Colombier "Alt", 0,
12280ee5cbfSDavid du Colombier "Caps", 0,
12380ee5cbfSDavid du Colombier "Del", '\177',
12480ee5cbfSDavid du Colombier "Enter", '\n',
12580ee5cbfSDavid du Colombier "Esc", '\033',
12680ee5cbfSDavid du Colombier "<-", '\b',
12780ee5cbfSDavid du Colombier "->", '\t',
12880ee5cbfSDavid du Colombier "Scrib", 0x10000,
12980ee5cbfSDavid du Colombier "Menu", 0x10001,
13080ee5cbfSDavid du Colombier nil, 0,
13180ee5cbfSDavid du Colombier };
13280ee5cbfSDavid du Colombier
13380ee5cbfSDavid du Colombier static char **keyset[Nstate] = {
13480ee5cbfSDavid du Colombier keyregular,
13580ee5cbfSDavid du Colombier keyshift,
13680ee5cbfSDavid du Colombier keycaps,
13780ee5cbfSDavid du Colombier keycapsshift,
13880ee5cbfSDavid du Colombier };
13980ee5cbfSDavid du Colombier
14080ee5cbfSDavid du Colombier static void keyboardshow(Keyboard*);
14180ee5cbfSDavid du Colombier static void keyup(Keyboard*, Point);
14280ee5cbfSDavid du Colombier static void keydown(Keyboard*, Point);
14380ee5cbfSDavid du Colombier static void keyresize(Keyboard*);
14480ee5cbfSDavid du Colombier
14580ee5cbfSDavid du Colombier static void
keyboardmouse(Control * c,Mouse * m)1469a747e4fSDavid du Colombier keyboardmouse(Control *c, Mouse *m)
14780ee5cbfSDavid du Colombier {
14880ee5cbfSDavid du Colombier Keyboard *k;
14980ee5cbfSDavid du Colombier
1509a747e4fSDavid du Colombier k = (Keyboard *)c;
1519a747e4fSDavid du Colombier if(m->buttons==1)
1529a747e4fSDavid du Colombier keydown(k, m->xy);
1539a747e4fSDavid du Colombier else if(k->lastbut==1 && m->buttons==0)
1549a747e4fSDavid du Colombier keyup(k, m->xy);
1559a747e4fSDavid du Colombier k->lastbut = m->buttons;
15680ee5cbfSDavid du Colombier }
15780ee5cbfSDavid du Colombier
15880ee5cbfSDavid du Colombier static void
keyboardfree(Control * c)1599a747e4fSDavid du Colombier keyboardfree(Control *c)
16080ee5cbfSDavid du Colombier {
16180ee5cbfSDavid du Colombier int i;
1629a747e4fSDavid du Colombier Keyboard *k;
16380ee5cbfSDavid du Colombier
1649a747e4fSDavid du Colombier k = (Keyboard *)c;
16580ee5cbfSDavid du Colombier _putctlimage(k->image);
16680ee5cbfSDavid du Colombier _putctlimage(k->mask);
16780ee5cbfSDavid du Colombier _putctlimage(k->light);
16880ee5cbfSDavid du Colombier _putctlimage(k->textcolor);
16980ee5cbfSDavid du Colombier _putctlimage(k->bordercolor);
17080ee5cbfSDavid du Colombier _putctlfont(k->font);
17180ee5cbfSDavid du Colombier _putctlfont(k->ctlfont);
17280ee5cbfSDavid du Colombier for(i=0; i<nelem(k->im); i++)
17380ee5cbfSDavid du Colombier freeimage(k->im[i]);
17480ee5cbfSDavid du Colombier free(k->format);
17580ee5cbfSDavid du Colombier }
17680ee5cbfSDavid du Colombier
17780ee5cbfSDavid du Colombier static int
keyboardy(Keyboard * k,int row)17880ee5cbfSDavid du Colombier keyboardy(Keyboard *k, int row)
17980ee5cbfSDavid du Colombier {
18080ee5cbfSDavid du Colombier int dy;
18180ee5cbfSDavid du Colombier
18280ee5cbfSDavid du Colombier if(row >= Nrow)
18380ee5cbfSDavid du Colombier return k->rect.max.y-k->border;
18480ee5cbfSDavid du Colombier dy = Dy(k->rect)-2*k->border;
18580ee5cbfSDavid du Colombier return k->rect.min.y+k->border+(row*dy+Nrow-1)/Nrow;
18680ee5cbfSDavid du Colombier }
18780ee5cbfSDavid du Colombier
18880ee5cbfSDavid du Colombier static char*
whichkey(Keyboard * k,Point p,int * rowp,int * colp,Rectangle * rp)18980ee5cbfSDavid du Colombier whichkey(Keyboard *k, Point p, int *rowp, int *colp, Rectangle *rp)
19080ee5cbfSDavid du Colombier {
19180ee5cbfSDavid du Colombier uchar *wp;
19280ee5cbfSDavid du Colombier char *kp;
19380ee5cbfSDavid du Colombier int row, col, dx, dy, x, n, maxx;
19480ee5cbfSDavid du Colombier Rectangle r;
19580ee5cbfSDavid du Colombier
19680ee5cbfSDavid du Colombier r = insetrect(k->rect, k->border);
19780ee5cbfSDavid du Colombier if(!ptinrect(p, r))
19880ee5cbfSDavid du Colombier return nil;
19980ee5cbfSDavid du Colombier maxx = r.max.x;
20080ee5cbfSDavid du Colombier dx = Dx(r);
20180ee5cbfSDavid du Colombier dy = Dy(r);
20280ee5cbfSDavid du Colombier row = (p.y - r.min.y)*Nrow/dy;
20380ee5cbfSDavid du Colombier if(row >= Nrow)
20480ee5cbfSDavid du Colombier row = Nrow-1;
20580ee5cbfSDavid du Colombier r.min.y = keyboardy(k, row);
20680ee5cbfSDavid du Colombier r.max.y = keyboardy(k, row+1);
20780ee5cbfSDavid du Colombier x = r.min.x;
20880ee5cbfSDavid du Colombier kp = keyset[k->state&SMask][row];
20980ee5cbfSDavid du Colombier wp = wid[row];
21080ee5cbfSDavid du Colombier for(col=0; *kp; col++,kp+=n+1){
21180ee5cbfSDavid du Colombier n = strlen(kp);
21280ee5cbfSDavid du Colombier r.min.x = x;
21380ee5cbfSDavid du Colombier r.max.x = x + (wp[col]*dx+255)/256;
21480ee5cbfSDavid du Colombier if(kp[n+1] == '\0')
21580ee5cbfSDavid du Colombier r.max.x = maxx;
21680ee5cbfSDavid du Colombier if(r.max.x > p.x)
21780ee5cbfSDavid du Colombier break;
21880ee5cbfSDavid du Colombier x = r.max.x;
21980ee5cbfSDavid du Colombier }
22080ee5cbfSDavid du Colombier *rp = insetrect(r, 1);
22180ee5cbfSDavid du Colombier *rowp = row;
22280ee5cbfSDavid du Colombier *colp = col;
22380ee5cbfSDavid du Colombier return kp;
22480ee5cbfSDavid du Colombier }
22580ee5cbfSDavid du Colombier
22680ee5cbfSDavid du Colombier static Rectangle
keyrect(Keyboard * k,int row,int col)22780ee5cbfSDavid du Colombier keyrect(Keyboard *k, int row, int col)
22880ee5cbfSDavid du Colombier {
22980ee5cbfSDavid du Colombier uchar *wp;
23080ee5cbfSDavid du Colombier char *kp;
23180ee5cbfSDavid du Colombier int i, x, n, dx;
23280ee5cbfSDavid du Colombier Rectangle r;
23380ee5cbfSDavid du Colombier Point p;
23480ee5cbfSDavid du Colombier
23580ee5cbfSDavid du Colombier r = insetrect(k->rect, k->border);
23680ee5cbfSDavid du Colombier p = r.min;
23780ee5cbfSDavid du Colombier dx = Dx(r);
23880ee5cbfSDavid du Colombier r.min.y = keyboardy(k, row);
23980ee5cbfSDavid du Colombier r.max.y = keyboardy(k, row+1);
24080ee5cbfSDavid du Colombier x = r.min.x;
24180ee5cbfSDavid du Colombier kp = keyset[0][row];
24280ee5cbfSDavid du Colombier wp = wid[row];
24380ee5cbfSDavid du Colombier for(i=0; *kp; i++,kp+=n+1){
24480ee5cbfSDavid du Colombier n = strlen(kp);
24580ee5cbfSDavid du Colombier r.min.x = x;
24680ee5cbfSDavid du Colombier r.max.x = x + (wp[i]*dx+255)/256;
24780ee5cbfSDavid du Colombier if(kp[n+1] == '\0')
24880ee5cbfSDavid du Colombier r.max.x = p.x+dx;
24980ee5cbfSDavid du Colombier if(i >= col)
25080ee5cbfSDavid du Colombier break;
25180ee5cbfSDavid du Colombier x = r.max.x;
25280ee5cbfSDavid du Colombier }
25380ee5cbfSDavid du Colombier return insetrect(r, 1);
25480ee5cbfSDavid du Colombier }
25580ee5cbfSDavid du Colombier
25680ee5cbfSDavid du Colombier static void
keydraw(Keyboard * k,int state)25780ee5cbfSDavid du Colombier keydraw(Keyboard *k, int state)
25880ee5cbfSDavid du Colombier {
25980ee5cbfSDavid du Colombier Point p, q;
26080ee5cbfSDavid du Colombier int row, col, x, dx, dy, nexty, n;
26180ee5cbfSDavid du Colombier uchar *wp;
26280ee5cbfSDavid du Colombier char *kp;
26380ee5cbfSDavid du Colombier Rectangle r;
26480ee5cbfSDavid du Colombier Font *f, *f1, *f2;
26580ee5cbfSDavid du Colombier Image *im;
26680ee5cbfSDavid du Colombier
26780ee5cbfSDavid du Colombier freeimage(k->im[state]);
26880ee5cbfSDavid du Colombier k->im[state] = nil;
26980ee5cbfSDavid du Colombier if(Dx(k->rect)-2*k->border <= 0)
27080ee5cbfSDavid du Colombier return;
27180ee5cbfSDavid du Colombier
2729a747e4fSDavid du Colombier im = allocimage(display, k->rect, screen->chan, 0, ~0);
27380ee5cbfSDavid du Colombier if(im == nil)
27480ee5cbfSDavid du Colombier return;
27580ee5cbfSDavid du Colombier k->im[state] = im;
27680ee5cbfSDavid du Colombier
27780ee5cbfSDavid du Colombier r = insetrect(k->rect, k->border);
27880ee5cbfSDavid du Colombier border(im, k->rect, k->border, k->bordercolor->image, ZP);
27980ee5cbfSDavid du Colombier draw(im, r, k->image->image, nil, ZP);
28080ee5cbfSDavid du Colombier dx = Dx(r);
28180ee5cbfSDavid du Colombier dy = Dy(r);
28280ee5cbfSDavid du Colombier p = r.min;
28380ee5cbfSDavid du Colombier f1 = k->font->font;
28480ee5cbfSDavid du Colombier f2 = k->ctlfont->font;
28580ee5cbfSDavid du Colombier nexty = p.y;
28680ee5cbfSDavid du Colombier for(row=0; row<Nrow; row++){
28780ee5cbfSDavid du Colombier x = p.x;
28880ee5cbfSDavid du Colombier kp = keyset[state][row];
28980ee5cbfSDavid du Colombier wp = wid[row];
29080ee5cbfSDavid du Colombier r.min.y = nexty;
29180ee5cbfSDavid du Colombier nexty = keyboardy(k, row+1);
29280ee5cbfSDavid du Colombier r.max.y = nexty;
29380ee5cbfSDavid du Colombier for(col=0; *kp; col++,kp+=n+1){
29480ee5cbfSDavid du Colombier r.min.x = x;
29580ee5cbfSDavid du Colombier r.max.x = x + (wp[col]*dx+255)/256;
29680ee5cbfSDavid du Colombier n = strlen(kp);
29780ee5cbfSDavid du Colombier if(kp[n+1] == '\0')
29880ee5cbfSDavid du Colombier r.max.x = p.x+dx;
29980ee5cbfSDavid du Colombier if(row == Nrow-1)
30080ee5cbfSDavid du Colombier r.max.y = p.y+dy;
30180ee5cbfSDavid du Colombier if(n > 1)
30280ee5cbfSDavid du Colombier f = f2;
30380ee5cbfSDavid du Colombier else
30480ee5cbfSDavid du Colombier f = f1;
30580ee5cbfSDavid du Colombier q = _ctlalignpoint(r, stringnwidth(f, kp, n), f->height, Acenter);
30680ee5cbfSDavid du Colombier _string(im, q, k->textcolor->image,
30780ee5cbfSDavid du Colombier ZP, f, kp, nil, n, r,
308*ac57dd0bSDavid du Colombier nil, ZP, SoverD);
30980ee5cbfSDavid du Colombier x = r.max.x;
31080ee5cbfSDavid du Colombier if(kp[n+1])
31180ee5cbfSDavid du Colombier draw(im, Rect(x, r.min.y, x+1, r.max.y),
31280ee5cbfSDavid du Colombier k->textcolor->image, nil, ZP);
31380ee5cbfSDavid du Colombier }
31480ee5cbfSDavid du Colombier if(row != Nrow-1)
31580ee5cbfSDavid du Colombier draw(im, Rect(p.x, r.max.y, p.x+dx, r.max.y+1),
31680ee5cbfSDavid du Colombier k->textcolor->image, nil, ZP);
31780ee5cbfSDavid du Colombier }
31880ee5cbfSDavid du Colombier }
31980ee5cbfSDavid du Colombier
32080ee5cbfSDavid du Colombier static void
keyresize(Keyboard * k)32180ee5cbfSDavid du Colombier keyresize(Keyboard *k)
32280ee5cbfSDavid du Colombier {
32380ee5cbfSDavid du Colombier int i;
32480ee5cbfSDavid du Colombier
32580ee5cbfSDavid du Colombier for(i=0; i<Nstate; i++)
32680ee5cbfSDavid du Colombier keydraw(k, i);
32780ee5cbfSDavid du Colombier }
32880ee5cbfSDavid du Colombier
32980ee5cbfSDavid du Colombier static void
keyboardshow(Keyboard * k)33080ee5cbfSDavid du Colombier keyboardshow(Keyboard *k)
33180ee5cbfSDavid du Colombier {
33280ee5cbfSDavid du Colombier Rectangle r;
33380ee5cbfSDavid du Colombier
3349a747e4fSDavid du Colombier if (k->hidden)
3359a747e4fSDavid du Colombier return;
33680ee5cbfSDavid du Colombier if(k->im[0]==nil || !eqrect(k->im[0]->r, k->rect))
33780ee5cbfSDavid du Colombier keyresize(k);
33880ee5cbfSDavid du Colombier if(k->im[k->state&SMask] == nil)
33980ee5cbfSDavid du Colombier return;
34080ee5cbfSDavid du Colombier draw(k->screen, k->rect, k->im[k->state&SMask], nil, k->rect.min);
34180ee5cbfSDavid du Colombier if(k->state & SShift){
34280ee5cbfSDavid du Colombier r = keyrect(k, 3, 0);
34380ee5cbfSDavid du Colombier draw(k->screen, r, k->light->image, k->mask->image, ZP);
34480ee5cbfSDavid du Colombier r = keyrect(k, 3, 11);
34580ee5cbfSDavid du Colombier draw(k->screen, r, k->light->image, k->mask->image, ZP);
34680ee5cbfSDavid du Colombier }
34780ee5cbfSDavid du Colombier if(k->state & SCaps){
34880ee5cbfSDavid du Colombier r = keyrect(k, 2, 0);
34980ee5cbfSDavid du Colombier draw(k->screen, r, k->light->image, k->mask->image, ZP);
35080ee5cbfSDavid du Colombier }
35180ee5cbfSDavid du Colombier if(k->state & SControl){
35280ee5cbfSDavid du Colombier r = keyrect(k, 4, 0);
35380ee5cbfSDavid du Colombier draw(k->screen, r, k->light->image, k->mask->image, ZP);
35480ee5cbfSDavid du Colombier }
35580ee5cbfSDavid du Colombier flushimage(display, 1);
35680ee5cbfSDavid du Colombier }
35780ee5cbfSDavid du Colombier
35880ee5cbfSDavid du Colombier static void
keydown(Keyboard * k,Point p)35980ee5cbfSDavid du Colombier keydown(Keyboard *k, Point p)
36080ee5cbfSDavid du Colombier {
36180ee5cbfSDavid du Colombier int row, col;
36280ee5cbfSDavid du Colombier Rectangle r;
36380ee5cbfSDavid du Colombier char *s;
36480ee5cbfSDavid du Colombier
36580ee5cbfSDavid du Colombier s = whichkey(k, p, &row, &col, &r);
36680ee5cbfSDavid du Colombier if(s == k->key)
36780ee5cbfSDavid du Colombier return;
36880ee5cbfSDavid du Colombier keyboardshow(k);
36980ee5cbfSDavid du Colombier if(s != nil)
37080ee5cbfSDavid du Colombier draw(k->screen, r, k->light->image, k->mask->image, ZP);
37180ee5cbfSDavid du Colombier flushimage(display, 1);
37280ee5cbfSDavid du Colombier k->key = s;
37380ee5cbfSDavid du Colombier }
37480ee5cbfSDavid du Colombier
37580ee5cbfSDavid du Colombier static int
keylookup(char * s)37680ee5cbfSDavid du Colombier keylookup(char *s)
37780ee5cbfSDavid du Colombier {
37880ee5cbfSDavid du Colombier int i;
37980ee5cbfSDavid du Colombier
38080ee5cbfSDavid du Colombier for(i=0; keytab[i].name; i++)
38180ee5cbfSDavid du Colombier if(strcmp(s, keytab[i].name) == 0)
38280ee5cbfSDavid du Colombier return keytab[i].val;
38380ee5cbfSDavid du Colombier return s[0];
38480ee5cbfSDavid du Colombier }
38580ee5cbfSDavid du Colombier
38680ee5cbfSDavid du Colombier static void
keyup(Keyboard * k,Point p)38780ee5cbfSDavid du Colombier keyup(Keyboard *k, Point p)
38880ee5cbfSDavid du Colombier {
38980ee5cbfSDavid du Colombier int row, col;
39080ee5cbfSDavid du Colombier Rectangle r;
39180ee5cbfSDavid du Colombier char *s;
39280ee5cbfSDavid du Colombier int val;
39380ee5cbfSDavid du Colombier
39480ee5cbfSDavid du Colombier s = whichkey(k, p, &row, &col, &r);
39580ee5cbfSDavid du Colombier if(s == nil)
39680ee5cbfSDavid du Colombier return;
39780ee5cbfSDavid du Colombier val = keylookup(s);
39880ee5cbfSDavid du Colombier if(k->state & SControl)
39980ee5cbfSDavid du Colombier if(' '<val && val<0177)
40080ee5cbfSDavid du Colombier val &= ~0x60;
40180ee5cbfSDavid du Colombier if(strcmp(s, "Alt") == 0)
4029a747e4fSDavid du Colombier {;}
40380ee5cbfSDavid du Colombier if(strcmp(s, "Ctrl") == 0){
40480ee5cbfSDavid du Colombier k->state ^= SControl;
40580ee5cbfSDavid du Colombier }else
40680ee5cbfSDavid du Colombier k->state &= ~SControl;
40780ee5cbfSDavid du Colombier if(strcmp(s, "Shift")==0 || strcmp(s, "Caps")==0){
40880ee5cbfSDavid du Colombier if(strcmp(s, "Shift") == 0)
40980ee5cbfSDavid du Colombier k->state ^= SShift;
41080ee5cbfSDavid du Colombier if(strcmp(s, "Caps") == 0)
41180ee5cbfSDavid du Colombier k->state ^= SCaps;
41280ee5cbfSDavid du Colombier }else
41380ee5cbfSDavid du Colombier k->state &= ~SShift;
41480ee5cbfSDavid du Colombier keyboardshow(k);
41580ee5cbfSDavid du Colombier if(val)
4169a747e4fSDavid du Colombier chanprint(k->event, k->format, k->name, val);
41780ee5cbfSDavid du Colombier k->key = nil;
41880ee5cbfSDavid du Colombier }
41980ee5cbfSDavid du Colombier
42080ee5cbfSDavid du Colombier static void
keyboardctl(Control * c,CParse * cp)4219a747e4fSDavid du Colombier keyboardctl(Control *c, CParse *cp)
42280ee5cbfSDavid du Colombier {
42380ee5cbfSDavid du Colombier int cmd;
42480ee5cbfSDavid du Colombier Rectangle r;
42580ee5cbfSDavid du Colombier Keyboard *k;
42680ee5cbfSDavid du Colombier
42780ee5cbfSDavid du Colombier k = (Keyboard*)c;
4289a747e4fSDavid du Colombier cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
42980ee5cbfSDavid du Colombier switch(cmd){
43080ee5cbfSDavid du Colombier default:
4319a747e4fSDavid du Colombier ctlerror("%q: unrecognized message '%s'", k->name, cp->str);
43280ee5cbfSDavid du Colombier break;
43380ee5cbfSDavid du Colombier case EBorder:
4349a747e4fSDavid du Colombier _ctlargcount(k, cp, 2);
4359a747e4fSDavid du Colombier if(cp->iargs[1] < 0)
4369a747e4fSDavid du Colombier ctlerror("%q: bad border: %c", k->name, cp->str);
4379a747e4fSDavid du Colombier k->border = cp->iargs[1];
43880ee5cbfSDavid du Colombier break;
43980ee5cbfSDavid du Colombier case EBordercolor:
4409a747e4fSDavid du Colombier _ctlargcount(k, cp, 2);
4419a747e4fSDavid du Colombier _setctlimage(k, &k->bordercolor, cp->args[1]);
44280ee5cbfSDavid du Colombier break;
44380ee5cbfSDavid du Colombier case EFocus:
44480ee5cbfSDavid du Colombier /* ignore focus change */
44580ee5cbfSDavid du Colombier break;
44680ee5cbfSDavid du Colombier case EFont:
4479a747e4fSDavid du Colombier if(cp->nargs!=2 && cp->nargs!=3)
4489a747e4fSDavid du Colombier ctlerror("%q: bad font message '%s'", k->name, cp->str);
4499a747e4fSDavid du Colombier _setctlfont(k, &k->font, cp->args[1]);
4509a747e4fSDavid du Colombier if(cp->nargs == 3)
4519a747e4fSDavid du Colombier _setctlfont(k, &k->ctlfont, cp->args[2]);
45280ee5cbfSDavid du Colombier else
4539a747e4fSDavid du Colombier _setctlfont(k, &k->ctlfont, cp->args[1]);
45480ee5cbfSDavid du Colombier break;
45580ee5cbfSDavid du Colombier case EFormat:
4569a747e4fSDavid du Colombier _ctlargcount(k, cp, 2);
4579a747e4fSDavid du Colombier k->format = ctlstrdup(cp->args[1]);
4589a747e4fSDavid du Colombier break;
4599a747e4fSDavid du Colombier case EHide:
4609a747e4fSDavid du Colombier _ctlargcount(k, cp, 1);
4619a747e4fSDavid du Colombier k->hidden = 1;
46280ee5cbfSDavid du Colombier break;
46380ee5cbfSDavid du Colombier case EImage:
4649a747e4fSDavid du Colombier _ctlargcount(k, cp, 2);
4659a747e4fSDavid du Colombier _setctlimage(k, &k->image, cp->args[1]);
46680ee5cbfSDavid du Colombier break;
46780ee5cbfSDavid du Colombier case ELight:
4689a747e4fSDavid du Colombier _ctlargcount(k, cp, 2);
4699a747e4fSDavid du Colombier _setctlimage(k, &k->light, cp->args[1]);
47080ee5cbfSDavid du Colombier break;
47180ee5cbfSDavid du Colombier case EMask:
4729a747e4fSDavid du Colombier _ctlargcount(k, cp, 2);
4739a747e4fSDavid du Colombier _setctlimage(k, &k->mask, cp->args[1]);
47480ee5cbfSDavid du Colombier break;
47580ee5cbfSDavid du Colombier case ERect:
4769a747e4fSDavid du Colombier _ctlargcount(k, cp, 5);
4779a747e4fSDavid du Colombier r.min.x = cp->iargs[1];
4789a747e4fSDavid du Colombier r.min.y = cp->iargs[2];
4799a747e4fSDavid du Colombier r.max.x = cp->iargs[3];
4809a747e4fSDavid du Colombier r.max.y = cp->iargs[4];
48180ee5cbfSDavid du Colombier if(Dx(r)<0 || Dy(r)<0)
4829a747e4fSDavid du Colombier ctlerror("%q: bad rectangle: %s", k->name, cp->str);
48380ee5cbfSDavid du Colombier k->rect = r;
48480ee5cbfSDavid du Colombier keyboardshow(k);
48580ee5cbfSDavid du Colombier break;
4869a747e4fSDavid du Colombier case EReveal:
4879a747e4fSDavid du Colombier _ctlargcount(k, cp, 1);
4889a747e4fSDavid du Colombier k->hidden = 0;
4899a747e4fSDavid du Colombier keyboardshow(k);
4909a747e4fSDavid du Colombier break;
4919a747e4fSDavid du Colombier case EShow:
4929a747e4fSDavid du Colombier _ctlargcount(k, cp, 1);
4939a747e4fSDavid du Colombier keyboardshow(k);
4949a747e4fSDavid du Colombier break;
4959a747e4fSDavid du Colombier case ESize:
4969a747e4fSDavid du Colombier if (cp->nargs == 3)
4979a747e4fSDavid du Colombier r.max = Pt(0x7fffffff, 0x7fffffff);
4989a747e4fSDavid du Colombier else{
4999a747e4fSDavid du Colombier _ctlargcount(k, cp, 5);
5009a747e4fSDavid du Colombier r.max.x = cp->iargs[3];
5019a747e4fSDavid du Colombier r.max.y = cp->iargs[4];
50280ee5cbfSDavid du Colombier }
5039a747e4fSDavid du Colombier r.min.x = cp->iargs[1];
5049a747e4fSDavid du Colombier r.min.y = cp->iargs[2];
5059a747e4fSDavid du Colombier 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)
5069a747e4fSDavid du Colombier ctlerror("%q: bad sizes: %s", k->name, cp->str);
5079a747e4fSDavid du Colombier k->size.min = r.min;
5089a747e4fSDavid du Colombier k->size.max = r.max;
5099a747e4fSDavid du Colombier break;
5109a747e4fSDavid du Colombier }
5119a747e4fSDavid du Colombier }
5129a747e4fSDavid du Colombier
5139a747e4fSDavid du Colombier Control*
createkeyboard(Controlset * cs,char * name)5149a747e4fSDavid du Colombier createkeyboard(Controlset *cs, char *name)
5159a747e4fSDavid du Colombier {
5169a747e4fSDavid du Colombier Keyboard *k;
5179a747e4fSDavid du Colombier
5189a747e4fSDavid du Colombier k = (Keyboard *)_createctl(cs, "keyboard", sizeof(Keyboard), name);
5199a747e4fSDavid du Colombier k->image = _getctlimage("white");
5209a747e4fSDavid du Colombier k->mask = _getctlimage("opaque");
5219a747e4fSDavid du Colombier k->light = _getctlimage("yellow");
5229a747e4fSDavid du Colombier k->bordercolor = _getctlimage("black");
5239a747e4fSDavid du Colombier k->textcolor = _getctlimage("black");
5249a747e4fSDavid du Colombier k->font = _getctlfont("font");
5259a747e4fSDavid du Colombier k->ctlfont = _getctlfont("font");
5269a747e4fSDavid du Colombier k->format = ctlstrdup("%q: value 0x%x");
5279a747e4fSDavid du Colombier k->border = 0;
5289a747e4fSDavid du Colombier k->lastbut = 0;
5299a747e4fSDavid du Colombier k->key = nil;
5309a747e4fSDavid du Colombier k->state = SRegular;
5319a747e4fSDavid du Colombier k->ctl = keyboardctl;
5329a747e4fSDavid du Colombier k->mouse = keyboardmouse;
5339a747e4fSDavid du Colombier k->exit = keyboardfree;
5349a747e4fSDavid du Colombier k->size = Rect(246, 2 + 5 * (k->font->font->height + 1), 512, 256);
5359a747e4fSDavid du Colombier return k;
53680ee5cbfSDavid du Colombier }
537