xref: /plan9-contrib/sys/src/9k/port/devkbmap.c (revision d9ae653d2530813571752880d2314526c14f3139)
1*d9ae653dSDavid du Colombier /*
2*d9ae653dSDavid du Colombier  *  keyboard map
3*d9ae653dSDavid du Colombier  */
4*d9ae653dSDavid du Colombier 
5*d9ae653dSDavid du Colombier #include	"u.h"
6*d9ae653dSDavid du Colombier #include	"../port/lib.h"
7*d9ae653dSDavid du Colombier #include	"mem.h"
8*d9ae653dSDavid du Colombier #include	"dat.h"
9*d9ae653dSDavid du Colombier #include	"fns.h"
10*d9ae653dSDavid du Colombier #include	"../port/error.h"
11*d9ae653dSDavid du Colombier 
12*d9ae653dSDavid du Colombier enum{
13*d9ae653dSDavid du Colombier 	Qdir,
14*d9ae653dSDavid du Colombier 	Qdata,
15*d9ae653dSDavid du Colombier };
16*d9ae653dSDavid du Colombier Dirtab kbmaptab[]={
17*d9ae653dSDavid du Colombier 	".",		{Qdir, 0, QTDIR},	0,	0555,
18*d9ae653dSDavid du Colombier 	"kbmap",	{Qdata, 0},		0,	0600,
19*d9ae653dSDavid du Colombier };
20*d9ae653dSDavid du Colombier #define	NKBFILE	sizeof(kbmaptab)/sizeof(kbmaptab[0])
21*d9ae653dSDavid du Colombier 
22*d9ae653dSDavid du Colombier #define	KBLINELEN	(3*NUMSIZE+1)	/* t code val\n */
23*d9ae653dSDavid du Colombier 
24*d9ae653dSDavid du Colombier static Chan *
kbmapattach(char * spec)25*d9ae653dSDavid du Colombier kbmapattach(char *spec)
26*d9ae653dSDavid du Colombier {
27*d9ae653dSDavid du Colombier 	return devattach(L'κ', spec);
28*d9ae653dSDavid du Colombier }
29*d9ae653dSDavid du Colombier 
30*d9ae653dSDavid du Colombier static Walkqid*
kbmapwalk(Chan * c,Chan * nc,char ** name,int nname)31*d9ae653dSDavid du Colombier kbmapwalk(Chan *c, Chan *nc, char **name, int nname)
32*d9ae653dSDavid du Colombier {
33*d9ae653dSDavid du Colombier 	return devwalk(c, nc, name, nname, kbmaptab, NKBFILE, devgen);
34*d9ae653dSDavid du Colombier }
35*d9ae653dSDavid du Colombier 
36*d9ae653dSDavid du Colombier static long
kbmapstat(Chan * c,uchar * dp,long n)37*d9ae653dSDavid du Colombier kbmapstat(Chan *c, uchar *dp, long n)
38*d9ae653dSDavid du Colombier {
39*d9ae653dSDavid du Colombier 	return devstat(c, dp, n, kbmaptab, NKBFILE, devgen);
40*d9ae653dSDavid du Colombier }
41*d9ae653dSDavid du Colombier 
42*d9ae653dSDavid du Colombier static Chan*
kbmapopen(Chan * c,int omode)43*d9ae653dSDavid du Colombier kbmapopen(Chan *c, int omode)
44*d9ae653dSDavid du Colombier {
45*d9ae653dSDavid du Colombier 	if(!iseve())
46*d9ae653dSDavid du Colombier 		error(Eperm);
47*d9ae653dSDavid du Colombier 	return devopen(c, omode, kbmaptab, NKBFILE, devgen);
48*d9ae653dSDavid du Colombier }
49*d9ae653dSDavid du Colombier 
50*d9ae653dSDavid du Colombier static void
kbmapclose(Chan * c)51*d9ae653dSDavid du Colombier kbmapclose(Chan *c)
52*d9ae653dSDavid du Colombier {
53*d9ae653dSDavid du Colombier 	if(c->aux){
54*d9ae653dSDavid du Colombier 		free(c->aux);
55*d9ae653dSDavid du Colombier 		c->aux = nil;
56*d9ae653dSDavid du Colombier 	}
57*d9ae653dSDavid du Colombier }
58*d9ae653dSDavid du Colombier 
59*d9ae653dSDavid du Colombier static long
kbmapread(Chan * c,void * a,long n,vlong offset)60*d9ae653dSDavid du Colombier kbmapread(Chan *c, void *a, long n, vlong offset)
61*d9ae653dSDavid du Colombier {
62*d9ae653dSDavid du Colombier 	char *bp;
63*d9ae653dSDavid du Colombier 	char tmp[KBLINELEN+1];
64*d9ae653dSDavid du Colombier 	int t, sc;
65*d9ae653dSDavid du Colombier 	Rune r;
66*d9ae653dSDavid du Colombier 
67*d9ae653dSDavid du Colombier 	if(c->qid.type == QTDIR)
68*d9ae653dSDavid du Colombier 		return devdirread(c, a, n, kbmaptab, NKBFILE, devgen);
69*d9ae653dSDavid du Colombier 
70*d9ae653dSDavid du Colombier 	switch((int)(c->qid.path)){
71*d9ae653dSDavid du Colombier 	case Qdata:
72*d9ae653dSDavid du Colombier 		if(kbdgetmap(offset/KBLINELEN, &t, &sc, &r)) {
73*d9ae653dSDavid du Colombier 			bp = tmp;
74*d9ae653dSDavid du Colombier 			bp += readnum(0, bp, NUMSIZE, t, NUMSIZE);
75*d9ae653dSDavid du Colombier 			bp += readnum(0, bp, NUMSIZE, sc, NUMSIZE);
76*d9ae653dSDavid du Colombier 			bp += readnum(0, bp, NUMSIZE, r, NUMSIZE);
77*d9ae653dSDavid du Colombier 			*bp++ = '\n';
78*d9ae653dSDavid du Colombier 			*bp = 0;
79*d9ae653dSDavid du Colombier 			n = readstr(offset%KBLINELEN, a, n, tmp);
80*d9ae653dSDavid du Colombier 		} else
81*d9ae653dSDavid du Colombier 			n = 0;
82*d9ae653dSDavid du Colombier 		break;
83*d9ae653dSDavid du Colombier 	default:
84*d9ae653dSDavid du Colombier 		n=0;
85*d9ae653dSDavid du Colombier 		break;
86*d9ae653dSDavid du Colombier 	}
87*d9ae653dSDavid du Colombier 	return n;
88*d9ae653dSDavid du Colombier }
89*d9ae653dSDavid du Colombier 
90*d9ae653dSDavid du Colombier static long
kbmapwrite(Chan * c,void * a,long n,vlong)91*d9ae653dSDavid du Colombier kbmapwrite(Chan *c, void *a, long n, vlong)
92*d9ae653dSDavid du Colombier {
93*d9ae653dSDavid du Colombier 	char line[100], *lp, *b;
94*d9ae653dSDavid du Colombier 	int key, m, l;
95*d9ae653dSDavid du Colombier 	Rune r;
96*d9ae653dSDavid du Colombier 
97*d9ae653dSDavid du Colombier 	if(c->qid.type == QTDIR)
98*d9ae653dSDavid du Colombier 		error(Eperm);
99*d9ae653dSDavid du Colombier 
100*d9ae653dSDavid du Colombier 	switch((int)(c->qid.path)){
101*d9ae653dSDavid du Colombier 	case Qdata:
102*d9ae653dSDavid du Colombier 		b = a;
103*d9ae653dSDavid du Colombier 		l = n;
104*d9ae653dSDavid du Colombier 		lp = line;
105*d9ae653dSDavid du Colombier 		if(c->aux){
106*d9ae653dSDavid du Colombier 			strcpy(line, c->aux);
107*d9ae653dSDavid du Colombier 			lp = line+strlen(line);
108*d9ae653dSDavid du Colombier 			free(c->aux);
109*d9ae653dSDavid du Colombier 			c->aux = nil;
110*d9ae653dSDavid du Colombier 		}
111*d9ae653dSDavid du Colombier 		while(--l >= 0) {
112*d9ae653dSDavid du Colombier 			*lp++  = *b++;
113*d9ae653dSDavid du Colombier 			if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
114*d9ae653dSDavid du Colombier 				*lp = 0;
115*d9ae653dSDavid du Colombier 				if(*line == 0)
116*d9ae653dSDavid du Colombier 					error(Ebadarg);
117*d9ae653dSDavid du Colombier 				if(*line == '\n' || *line == '#'){
118*d9ae653dSDavid du Colombier 					lp = line;
119*d9ae653dSDavid du Colombier 					continue;
120*d9ae653dSDavid du Colombier 				}
121*d9ae653dSDavid du Colombier 				lp = line;
122*d9ae653dSDavid du Colombier 				while(*lp == ' ' || *lp == '\t')
123*d9ae653dSDavid du Colombier 					lp++;
124*d9ae653dSDavid du Colombier 				m = strtoul(line, &lp, 0);
125*d9ae653dSDavid du Colombier 				key = strtoul(lp, &lp, 0);
126*d9ae653dSDavid du Colombier 				while(*lp == ' ' || *lp == '\t')
127*d9ae653dSDavid du Colombier 					lp++;
128*d9ae653dSDavid du Colombier 				r = 0;
129*d9ae653dSDavid du Colombier 				if(*lp == '\'' && lp[1])
130*d9ae653dSDavid du Colombier 					chartorune(&r, lp+1);
131*d9ae653dSDavid du Colombier 				else if(*lp == '^' && lp[1]){
132*d9ae653dSDavid du Colombier 					chartorune(&r, lp+1);
133*d9ae653dSDavid du Colombier 					if(0x40 <= r && r < 0x60)
134*d9ae653dSDavid du Colombier 						r -= 0x40;
135*d9ae653dSDavid du Colombier 					else
136*d9ae653dSDavid du Colombier 						error(Ebadarg);
137*d9ae653dSDavid du Colombier 				}else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
138*d9ae653dSDavid du Colombier 					r = 0xF900+lp[1]-'0';
139*d9ae653dSDavid du Colombier 				else if(*lp>='0' && *lp<='9') /* includes 0x... */
140*d9ae653dSDavid du Colombier 					r = strtoul(lp, &lp, 0);
141*d9ae653dSDavid du Colombier 				else
142*d9ae653dSDavid du Colombier 					error(Ebadarg);
143*d9ae653dSDavid du Colombier 				kbdputmap(m, key, r);
144*d9ae653dSDavid du Colombier 				lp = line;
145*d9ae653dSDavid du Colombier 			}
146*d9ae653dSDavid du Colombier 		}
147*d9ae653dSDavid du Colombier 		if(lp != line){
148*d9ae653dSDavid du Colombier 			l = lp-line;
149*d9ae653dSDavid du Colombier 			c->aux = lp = smalloc(l+1);
150*d9ae653dSDavid du Colombier 			memmove(lp, line, l);
151*d9ae653dSDavid du Colombier 			lp[l] = 0;
152*d9ae653dSDavid du Colombier 		}
153*d9ae653dSDavid du Colombier 		break;
154*d9ae653dSDavid du Colombier 	default:
155*d9ae653dSDavid du Colombier 		error(Ebadusefd);
156*d9ae653dSDavid du Colombier 	}
157*d9ae653dSDavid du Colombier 	return n;
158*d9ae653dSDavid du Colombier }
159*d9ae653dSDavid du Colombier 
160*d9ae653dSDavid du Colombier Dev kbmapdevtab = {
161*d9ae653dSDavid du Colombier 	L'κ',
162*d9ae653dSDavid du Colombier 	"kbmap",
163*d9ae653dSDavid du Colombier 
164*d9ae653dSDavid du Colombier 	devreset,
165*d9ae653dSDavid du Colombier 	devinit,
166*d9ae653dSDavid du Colombier 	devshutdown,
167*d9ae653dSDavid du Colombier 	kbmapattach,
168*d9ae653dSDavid du Colombier 	kbmapwalk,
169*d9ae653dSDavid du Colombier 	kbmapstat,
170*d9ae653dSDavid du Colombier 	kbmapopen,
171*d9ae653dSDavid du Colombier 	devcreate,
172*d9ae653dSDavid du Colombier 	kbmapclose,
173*d9ae653dSDavid du Colombier 	kbmapread,
174*d9ae653dSDavid du Colombier 	devbread,
175*d9ae653dSDavid du Colombier 	kbmapwrite,
176*d9ae653dSDavid du Colombier 	devbwrite,
177*d9ae653dSDavid du Colombier 	devremove,
178*d9ae653dSDavid du Colombier 	devwstat,
179*d9ae653dSDavid du Colombier };
180