Subversion Repositories planix.SVN

Rev

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

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