Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}