179 lines
3 KiB
C
179 lines
3 KiB
C
/*
|
|
* keyboard map
|
|
*/
|
|
|
|
#include "u.h"
|
|
#include "../port/lib.h"
|
|
#include "mem.h"
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
#include "../port/error.h"
|
|
|
|
enum{
|
|
Qdir,
|
|
Qdata,
|
|
};
|
|
Dirtab kbmaptab[]={
|
|
".", {Qdir, 0, QTDIR}, 0, 0555,
|
|
"kbmap", {Qdata, 0}, 0, 0600,
|
|
};
|
|
#define NKBFILE sizeof(kbmaptab)/sizeof(kbmaptab[0])
|
|
|
|
#define KBLINELEN (3*NUMSIZE+1) /* t code val\n */
|
|
|
|
static Chan *
|
|
kbmapattach(char *spec)
|
|
{
|
|
return devattach(L'κ', spec);
|
|
}
|
|
|
|
static Walkqid*
|
|
kbmapwalk(Chan *c, Chan *nc, char **name, int nname)
|
|
{
|
|
return devwalk(c, nc, name, nname, kbmaptab, NKBFILE, devgen);
|
|
}
|
|
|
|
static int
|
|
kbmapstat(Chan *c, uchar *dp, int n)
|
|
{
|
|
return devstat(c, dp, n, kbmaptab, NKBFILE, devgen);
|
|
}
|
|
|
|
static Chan*
|
|
kbmapopen(Chan *c, int omode)
|
|
{
|
|
if(!iseve())
|
|
error(Eperm);
|
|
return devopen(c, omode, kbmaptab, NKBFILE, devgen);
|
|
}
|
|
|
|
static void
|
|
kbmapclose(Chan *c)
|
|
{
|
|
if(c->aux){
|
|
free(c->aux);
|
|
c->aux = nil;
|
|
}
|
|
}
|
|
|
|
static long
|
|
kbmapread(Chan *c, void *a, long n, vlong offset)
|
|
{
|
|
char *bp;
|
|
char tmp[KBLINELEN+1];
|
|
int t, sc;
|
|
Rune r;
|
|
|
|
if(c->qid.type == QTDIR)
|
|
return devdirread(c, a, n, kbmaptab, NKBFILE, devgen);
|
|
|
|
switch((int)(c->qid.path)){
|
|
case Qdata:
|
|
if(kbdgetmap(offset/KBLINELEN, &t, &sc, &r)) {
|
|
bp = tmp;
|
|
bp += readnum(0, bp, NUMSIZE, t, NUMSIZE);
|
|
bp += readnum(0, bp, NUMSIZE, sc, NUMSIZE);
|
|
bp += readnum(0, bp, NUMSIZE, r, NUMSIZE);
|
|
*bp++ = '\n';
|
|
*bp = 0;
|
|
n = readstr(offset%KBLINELEN, a, n, tmp);
|
|
} else
|
|
n = 0;
|
|
break;
|
|
default:
|
|
n=0;
|
|
break;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
static long
|
|
kbmapwrite(Chan *c, void *a, long n, vlong)
|
|
{
|
|
char line[100], *lp, *b;
|
|
int key, m, l;
|
|
Rune r;
|
|
|
|
if(c->qid.type == QTDIR)
|
|
error(Eperm);
|
|
|
|
switch((int)(c->qid.path)){
|
|
case Qdata:
|
|
b = a;
|
|
l = n;
|
|
lp = line;
|
|
if(c->aux){
|
|
strcpy(line, c->aux);
|
|
lp = line+strlen(line);
|
|
free(c->aux);
|
|
c->aux = nil;
|
|
}
|
|
while(--l >= 0) {
|
|
*lp++ = *b++;
|
|
if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
|
|
*lp = 0;
|
|
if(*line == 0)
|
|
error(Ebadarg);
|
|
if(*line == '\n' || *line == '#'){
|
|
lp = line;
|
|
continue;
|
|
}
|
|
lp = line;
|
|
while(*lp == ' ' || *lp == '\t')
|
|
lp++;
|
|
m = strtoul(line, &lp, 0);
|
|
key = strtoul(lp, &lp, 0);
|
|
while(*lp == ' ' || *lp == '\t')
|
|
lp++;
|
|
r = 0;
|
|
if(*lp == '\'' && lp[1])
|
|
chartorune(&r, lp+1);
|
|
else if(*lp == '^' && lp[1]){
|
|
chartorune(&r, lp+1);
|
|
if(0x40 <= r && r < 0x60)
|
|
r -= 0x40;
|
|
else
|
|
error(Ebadarg);
|
|
}else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
|
|
r = 0xF900+lp[1]-'0';
|
|
else if(*lp>='0' && *lp<='9') /* includes 0x... */
|
|
r = strtoul(lp, &lp, 0);
|
|
else
|
|
error(Ebadarg);
|
|
kbdputmap(m, key, r);
|
|
lp = line;
|
|
}
|
|
}
|
|
if(lp != line){
|
|
l = lp-line;
|
|
c->aux = lp = smalloc(l+1);
|
|
memmove(lp, line, l);
|
|
lp[l] = 0;
|
|
}
|
|
break;
|
|
default:
|
|
error(Ebadusefd);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
Dev kbmapdevtab = {
|
|
L'κ',
|
|
"kbmap",
|
|
|
|
devreset,
|
|
devinit,
|
|
devshutdown,
|
|
kbmapattach,
|
|
kbmapwalk,
|
|
kbmapstat,
|
|
kbmapopen,
|
|
devcreate,
|
|
kbmapclose,
|
|
kbmapread,
|
|
devbread,
|
|
kbmapwrite,
|
|
devbwrite,
|
|
devremove,
|
|
devwstat,
|
|
};
|