diff options
author | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-05-28 08:16:01 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-05-28 08:16:01 +0000 |
commit | fbbb449cc0bd35ebb89b87d5b46ed2874246876e (patch) | |
tree | 73dc04ae8e0dd22becec50be198b25a300c67f77 /sys | |
parent | 98f4157b5a2f9bce37939e2ea807b631943d969c (diff) |
big /dev/kbd change, new format, support Alt+Stuff (key composing)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/man/8/kbdfs | 53 | ||||
-rw-r--r-- | sys/src/cmd/aux/kbdfs/kbdfs.c (renamed from sys/src/cmd/aux/kbdfs.c) | 184 | ||||
-rw-r--r-- | sys/src/cmd/aux/kbdfs/mkfile | 16 | ||||
-rw-r--r-- | sys/src/cmd/aux/kbdfs/mkfile.mklatin | 7 | ||||
-rw-r--r-- | sys/src/cmd/aux/kbdfs/mklatin.c (renamed from sys/src/cmd/aux/mklatinkbd.c) | 0 | ||||
-rw-r--r-- | sys/src/cmd/aux/mkfile | 3 | ||||
-rw-r--r-- | sys/src/cmd/rio/rio.c | 6 | ||||
-rw-r--r-- | sys/src/cmd/rio/wind.c | 18 | ||||
-rw-r--r-- | sys/src/games/doom/i_video.c | 46 |
9 files changed, 236 insertions, 97 deletions
diff --git a/sys/man/8/kbdfs b/sys/man/8/kbdfs index 7149cbd62..733953bdf 100644 --- a/sys/man/8/kbdfs +++ b/sys/man/8/kbdfs @@ -152,26 +152,41 @@ This is used on serial consoles. .SS Keyboard A read on the .BR kbd -file returns a null terminated, variable-length, +file returns the character +.B k, +.B K +or +.B c +followed by a null terminated, variable-length, .SM UTF -encoded string of all the keys that are currently pressed (key is -down) on the keyboard. This includes all keys that have a keyboard -mapping and modifier keys. No key is treated specially. A new event -is generated on each state change or at keyboard repeat rate and put -in a buffer. Each -.IR read (2) -will return a single event or block until there are new events -available. The read data is always terminated with a null-byte, -so when all keys are released (all keys are up), a single -null-byte will be returned. Newly pressed keys are appended to the -string before the null-byte. Key releases remove the -character from the string. Change on a modifier key like +encoded string. The +.B k +message is send when a key is pressed down +and +.B K +when a key is released. The following string contains all the keycodes +of the keys that are currently pressed down in decomposed form. +This includes all keys that have a keyboard mapping and modifier keys. +Some keys may produce multiple characters like .B Shift -or -.B Num -will not change -the characters already present in the string, but will -take effect on newly pressed keys. Opening the +and +.B a +will produce +.B Shift, +.B a, +.B A +in the string. The string following the +.B c +message contains the single character that would have been appeared +on the +.BR cons +file instead. The +.B c +message will be resent at the keyboard repeat rate. +Each +.IR read (2) +will return a single message or block until there are new messages +available. Opening the .BR kbd file disables input processing on the .BR cons @@ -222,4 +237,4 @@ to represent a control character. .SH FILES .B /dev/lib/kbmap/* .SH SOURCE -.B /sys/src/cmd/aux/kbdfs.c +.B /sys/src/cmd/aux/kbdfs diff --git a/sys/src/cmd/aux/kbdfs.c b/sys/src/cmd/aux/kbdfs/kbdfs.c index 1a0a0fa3d..2da4f958f 100644 --- a/sys/src/cmd/aux/kbdfs.c +++ b/sys/src/cmd/aux/kbdfs/kbdfs.c @@ -101,6 +101,7 @@ Channel *reqchan; /* Req* */ Channel *ctlchan; /* int */ Channel *rawchan; /* Rune */ +Channel *runechan; /* Rune */ Channel *linechan; /* char * */ Channel *kbdchan; /* char* */ @@ -354,7 +355,7 @@ utfconv(Rune *r, int n) void keyproc(void *) { - Rune rb[Nscan*2]; + Rune rb[Nscan*2+1]; int cb[Nscan]; Key key; int i, nb; @@ -364,42 +365,35 @@ keyproc(void *) nb = 0; while(recv(keychan, &key) > 0){ - if(key.down){ - switch(key.r){ - case 0: - case Kcaps: - case Knum: - case Kshift: - case Kalt: - case Kctl: - case Kaltgr: - break; - default: - nbsend(rawchan, &key.r); - } - } + if(key.down && key.r) + nbsend(rawchan, &key.r); + rb[0] = 0; for(i=0; i<nb && cb[i] != key.c; i++) ; if(!key.down){ while(i < nb && cb[i] == key.c){ memmove(cb+i, cb+i+1, (nb-i+1) * sizeof(cb[0])); - memmove(rb+i, rb+i+1, (nb-i+1) * sizeof(rb[0])); + memmove(rb+i+1, rb+i+2, (nb-i+1) * sizeof(rb[0])); nb--; + rb[0] = 'K'; } } else if(i == nb && nb < nelem(cb) && key.b){ cb[nb] = key.c; - rb[nb] = key.b; + rb[nb+1] = key.b; nb++; if(nb < nelem(cb) && key.r && key.b != key.r){ cb[nb] = key.c; - rb[nb] = key.r; + rb[nb+1] = key.r; nb++; } + rb[0] = 'k'; + } + if(rb[0]){ + s = utfconv(rb, nb+1); + if(nbsendp(kbdchan, s) <= 0) + free(s); } - s = utfconv(rb, nb); - if(nbsendp(kbdchan, s) <= 0) - free(s); } } @@ -429,7 +423,7 @@ consproc(void *) } if(cr = (r == '\r')) r = '\n'; - send(rawchan, &r); + send(runechan, &r); } } n = x - p; @@ -438,6 +432,101 @@ consproc(void *) } } +static int +nextrune(Channel *ch, Rune *r) +{ + while(recv(ch, r) > 0){ + switch(*r){ + case 0: + case Kcaps: + case Knum: + case Kshift: + case Kctl: + case Kaltgr: + /* ignore these special keys */ + continue; + + case Kalt: + /* latin escape! */ + return 1; + } + return 0; + } + return -1; +} + +/* + * Read runes from rawchan, possibly compose special characters + * and output the new runes to runechan + */ +void +runeproc(void *) +{ + static struct { + char *ld; /* must be seen before using this conversion */ + char *si; /* options for last input characters */ + Rune *so; /* the corresponding Rune for each si entry */ + } tab[] = { +#include "latin1.h" + }; + Rune r, rr; + int i, j; + + threadsetname("runeproc"); + + while((i = nextrune(rawchan, &r)) >= 0){ + if(i == 0){ +Forward: + send(runechan, &r); + continue; + } + + /* latin sequence */ + if(nextrune(rawchan, &r)) + continue; + + if(r == 'X'){ + r = 0; + for(i = 0; i<4; i++){ + if(nextrune(rawchan, &rr)) + break; + r <<= 4; + if(rr >= '0' && rr <= '9') + r |= (rr - '0'); + else if(rr >= 'a' && rr <= 'f') + r |= 10 + (rr - 'a'); + else if(rr >= 'A' && rr <= 'F') + r |= 10 + (rr - 'A'); + else + break; + } + if(i == 4 && r > 0) + goto Forward; + } else { + if(nextrune(rawchan, &rr)) + continue; + for(i = 0; i<nelem(tab); i++){ + if(tab[i].ld[0] != r) + continue; + if(tab[i].ld[1] == 0) + break; + if(tab[i].ld[1] == rr){ + nextrune(rawchan, &rr); + break; + } + } + if(i == nelem(tab) || rr == 0) + continue; + for(j = 0; tab[i].si[j]; j++){ + if(tab[i].si[j] != rr) + continue; + r = tab[i].so[j]; + goto Forward; + } + } + } +} + /* * Cook lines for cons */ @@ -496,7 +585,7 @@ ctlproc(void *) Req *h; Req **t; } qcons, qkbd, *q; - enum { Areq, Actl, Araw, Aline, Akbd, Aend }; + enum { Areq, Actl, Arune, Aline, Akbd, Aend }; Alt a[Aend+1]; Req *req; Fid *fid; @@ -510,12 +599,13 @@ ctlproc(void *) cook = chancreate(sizeof(Rune), 0); if(scanfd >= 0) - proccreate(scanproc, nil, STACK); + proccreate(scanproc, nil, STACK); /* scanfd -> keychan */ if(consfd >= 0) - proccreate(consproc, nil, STACK); + proccreate(consproc, nil, STACK); /* consfd -> runechan */ - threadcreate(keyproc, nil, STACK); - threadcreate(lineproc, cook, STACK); + threadcreate(keyproc, nil, STACK); /* keychan -> rawchan, kbdchan */ + threadcreate(runeproc, nil, STACK); /* rawchan -> runechan */ + threadcreate(lineproc, cook, STACK); /* cook -> linechan */ raw = 0; @@ -536,9 +626,9 @@ ctlproc(void *) a[Actl].v = &c; a[Actl].op = CHANRCV; - a[Araw].c = rawchan; - a[Araw].v = &r; - a[Araw].op = CHANRCV; + a[Arune].c = runechan; + a[Arune].v = &r; + a[Arune].op = CHANRCV; a[Aline].c = linechan; a[Aline].v = &s; @@ -553,9 +643,15 @@ ctlproc(void *) for(;;){ s = nil; - a[Araw].op = (b == nil) ? CHANRCV : CHANNOP; - a[Aline].op = (b == nil) ? CHANRCV : CHANNOP; - a[Akbd].op = qkbd.h || !kbdopen ? CHANRCV : CHANNOP; + if(kbdopen){ + a[Arune].op = qkbd.h ? CHANRCV : CHANNOP; + a[Akbd].op = qkbd.h ? CHANRCV : CHANNOP; + a[Aline].op = CHANNOP; + }else{ + a[Arune].op = (b == nil) ? CHANRCV : CHANNOP; + a[Akbd].op = CHANRCV; + a[Aline].op = (b == nil) ? CHANRCV : CHANNOP; + } switch(alt(a)){ case Areq: @@ -604,8 +700,15 @@ ctlproc(void *) } break; - case Araw: - if(raw || kbdopen){ + case Arune: + if(kbdopen){ + s = emalloc9p(UTFmax+2); + s[0] = 'c'; + s[1+runetochar(s+1, &r)] = 0; + goto Havekbd; + } + + if(raw){ s = emalloc9p(UTFmax+1); s[runetochar(s, &r)] = 0; } else { @@ -620,11 +723,6 @@ ctlproc(void *) e = s + strlen(s); Havereq: - if(kbdopen){ - free(b); - b = nil; - break; - } while(b && (req = qcons.h)){ if((qcons.h = req->aux) == nil) qcons.t = &qcons.h; @@ -643,6 +741,7 @@ ctlproc(void *) break; case Akbd: + Havekbd: if(req = qkbd.h){ if((qkbd.h = req->aux) == nil) qkbd.t = &qkbd.h; @@ -1166,11 +1265,12 @@ threadmain(int argc, char** argv) keychan = chancreate(sizeof(Key), 8); reqchan = chancreate(sizeof(Req*), 0); ctlchan = chancreate(sizeof(int), 0); - rawchan = chancreate(sizeof(Rune), 32); + rawchan = chancreate(sizeof(Rune), 16); + runechan = chancreate(sizeof(Rune), 32); linechan = chancreate(sizeof(char*), 16); kbdchan = chancreate(sizeof(char*), 16); - if(!(keychan && reqchan && ctlchan && rawchan && linechan && kbdchan)) + if(!(keychan && reqchan && ctlchan && rawchan && runechan && linechan && kbdchan)) sysfatal("allocating chans"); elevate(); diff --git a/sys/src/cmd/aux/kbdfs/mkfile b/sys/src/cmd/aux/kbdfs/mkfile new file mode 100644 index 000000000..dea627845 --- /dev/null +++ b/sys/src/cmd/aux/kbdfs/mkfile @@ -0,0 +1,16 @@ +</$objtype/mkfile + +BIN=/$objtype/bin/aux + +TARG=kbdfs +OFILES=kbdfs.$O +HFILES=latin1.h +CLEANFILES=latin1.h mklatin.$cputype + +</sys/src/cmd/mkone + +mklatin.$cputype: mkfile.mklatin + @{objtype=$cputype mk -f $prereq $target} + +latin1.h: mklatin.$cputype /lib/keyboard + $prereq >$target diff --git a/sys/src/cmd/aux/kbdfs/mkfile.mklatin b/sys/src/cmd/aux/kbdfs/mkfile.mklatin new file mode 100644 index 000000000..ba34ac12c --- /dev/null +++ b/sys/src/cmd/aux/kbdfs/mkfile.mklatin @@ -0,0 +1,7 @@ +</$objtype/mkfile + +mklatin.$cputype: mklatin.$O + $LD $LDFLAGS -o $target $prereq + +</sys/src/cmd/mkone + diff --git a/sys/src/cmd/aux/mklatinkbd.c b/sys/src/cmd/aux/kbdfs/mklatin.c index 64787f00f..64787f00f 100644 --- a/sys/src/cmd/aux/mklatinkbd.c +++ b/sys/src/cmd/aux/kbdfs/mklatin.c diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile index d46602c63..943ae06f2 100644 --- a/sys/src/cmd/aux/mkfile +++ b/sys/src/cmd/aux/mkfile @@ -17,11 +17,9 @@ TARG=\ disksim\ getflags\ icanhasmsi\ - kbdfs\ lines\ listen\ listen1\ - mklatinkbd\ ms2\ msexceltables\ mswordstrings\ @@ -57,6 +55,7 @@ UPDATE=\ DIRS=mnihongo\ flashfs\ gps\ + kbdfs\ na\ vga\ realemu diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index 1550213ef..a101ee256 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -1234,10 +1234,8 @@ kbdproc(void *arg) e = p + n; while(p < e && fullrune(p, e - p)){ p += chartorune(&r, p); - if(r){ - chanprint(c, "%C", r); - chanprint(c, ""); - } + if(r) + chanprint(c, "c%C", r); } n = e - p; memmove(buf, p, n); diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c index 104c19e93..92b63c177 100644 --- a/sys/src/cmd/rio/wind.c +++ b/sys/src/cmd/rio/wind.c @@ -292,20 +292,16 @@ winctl(void *arg) } switch(alt(alts)){ case WKbd: - if(utflen(kbds) >= utflen(kbdq[kbdqw] ? kbdq[kbdqw] : "")){ - Rune r; - - i = 0; - r = 0; - while(kbds[i]) - i += chartorune(&r, kbds+i); - if(!w->kbdopen) - wkeyctl(w, r); - } if(w->kbdopen){ i = (kbdqw+1) % nelem(kbdq); if(i != kbdqr) kbdqw = i; + } else if(*kbds == 'c'){ + Rune r; + + chartorune(&r, kbds+1); + if(r) + wkeyctl(w, r); } free(kbdq[kbdqw]); kbdq[kbdqw] = kbds; @@ -319,7 +315,7 @@ winctl(void *arg) sendp(krm.ck, kbdq[i]); kbdq[i] = nil; }else - sendp(krm.ck, strdup("")); + sendp(krm.ck, strdup("K")); continue; case WMouse: diff --git a/sys/src/games/doom/i_video.c b/sys/src/games/doom/i_video.c index dcf31a993..34543bc96 100644 --- a/sys/src/games/doom/i_video.c +++ b/sys/src/games/doom/i_video.c @@ -217,32 +217,40 @@ kbdproc(void *) sysfatal("can't open kbd: %r"); buf2[0] = 0; + buf2[1] = 0; while((n = read(kfd, buf, sizeof(buf))) > 0){ buf[n-1] = 0; - s = buf; - while(*s){ - s += chartorune(&r, s); - if(utfrune(buf2, r) == nil){ - e.type = ev_keydown; - if(e.data1 = runetokey(r)){ - e.data2 = *s == 0 ? e.data1 : -1; - e.data3 = *s ? e.data1 : -1; - D_PostEvent(&e); + switch(buf[0]){ + case 'k': + s = buf+1; + while(*s){ + s += chartorune(&r, s); + if(utfrune(buf2+1, r) == nil){ + if(e.data1 = runetokey(r)){ + e.data2 = *s == 0 ? e.data1 : -1; + e.data3 = -1; + e.type = ev_keydown; + D_PostEvent(&e); + } } } - } - s = buf2; - while(*s){ - s += chartorune(&r, s); - if(utfrune(buf, r) == nil){ - e.type = ev_keyup; - if(e.data1 = runetokey(r)){ - e.data2 = -1; - e.data3 = -1; - D_PostEvent(&e); + break; + case 'K': + s = buf2+1; + while(*s){ + s += chartorune(&r, s); + if(utfrune(buf+1, r) == nil){ + if(e.data1 = runetokey(r)){ + e.data2 = e.data3 = -1; + e.type = ev_keyup; + D_PostEvent(&e); + } } } + break; + default: + continue; } strcpy(buf2, buf); } |