Blob
- Date:
- Message:
- devdraw, libdraw: handle keyboard runes > U+FFFF Runes in Plan 9 were limited to the 16-bit BMP when I drew up the RPC protocol between graphical programs and devdraw a long time ago. Now that they can be 32-bit, use a 32-bit wire encoding too. A new message number to avoid problems with other clients (like 9fans.net/go). Add keyboard shortcut alt : , for U+1F602, face with tears of joy, to test that it all works.
- Actions:
- History | Blame | Raw File
1 /*2 * Parse /lib/keyboard to create latin1.h table for kernel.3 * mklatinkbd -r prints an array of integers rather than a Rune string literal.4 */6 #include <u.h>7 #include <libc.h>8 #include <bio.h>9 #include <ctype.h>11 int rflag;12 int xflag;14 enum {15 MAXLD = 2, /* latin1.c assumes this is 2 */16 };18 char *head = ""19 "/*\n"20 " * This is automatically generated by %s from /lib/keyboard\n"21 " * Edit /lib/keyboard instead.\n"22 " */\n";24 /*25 * latin1.c assumes that strlen(ld) is at most 2.26 * It also assumes that latintab[i].ld can be a prefix of latintab[j].ld27 * only when j < i. We ensure this by sorting the output by prefix length.28 * The so array is indexed by the character value.29 */31 typedef struct Trie Trie;32 struct Trie {33 int n; /* of characters r */34 char seq[MAXLD+1+1];35 Rune r[256];36 Trie *link[256];37 };39 Trie *root;41 Trie*42 mktrie(char *seq)43 {44 uchar *q;45 Trie **tp;47 if(root == nil) {48 root = malloc(sizeof *root);49 memset(root, 0, sizeof *root);50 }52 assert(seq[0] != '\0');54 tp = &root;55 for(q=(uchar*)seq; *(q+1) != '\0'; q++) {56 tp = &(*tp)->link[*q];57 if(*tp == nil) {58 *tp = malloc(sizeof(**tp));59 assert(*tp != nil);60 memset(*tp, 0, sizeof(**tp));61 strcpy((*tp)->seq, seq);62 (*tp)->seq[q+1-(uchar*)seq] = '\0';63 }64 }66 assert(*tp != nil);67 return *tp;68 }70 /* add character sequence s meaning rune r */71 void72 insert(char *s, Rune r)73 {74 uchar lastc;75 int len;76 Trie *t;78 len = strlen(s);79 lastc = (uchar)s[len-1];81 t = mktrie(s);82 if(t->r[lastc]) {83 fprint(2, "warning: table duplicate: %s is %C and %C\n", s, t->r[lastc], r);84 return;85 }86 t->r[lastc] = r;87 t->n++;88 }90 void91 cprintchar(Biobuf *b, int c)92 {93 /* print a byte c safe for a C string. */94 switch(c) {95 case '\'':96 case '\"':97 case '\\':98 Bprint(b, "\\%c", c);99 break;100 case '\t':101 Bprint(b, "\\t");102 break;103 default:104 if(isascii(c) && isprint(c))105 Bprint(b, "%c", c);106 else107 Bprint(b, "\\x%.2x", c);108 break;109 }110 }112 void113 cprints(Biobuf *b, char *p)114 {115 while(*p != '\0')116 cprintchar(b, *p++);117 }119 void120 xprint(Biobuf *b, int c)121 {122 }124 void125 printtrie(Biobuf *b, Trie *t)126 {127 int i;128 char *p;130 for(i=0; i<256; i++)131 if(t->link[i])132 printtrie(b, t->link[i]);133 if(t->n == 0)134 return;136 if(xflag) {137 for(i=0; i<256; i++) {138 if(t->r[i] == 0)139 continue;140 Bprint(b, "<Multi_key>");141 for(p=t->seq; *p; p++)142 Bprint(b, " %k", *p);143 Bprint(b, " %k : \"%C\" U%04X\n", i, t->r[i], t->r[i]);144 }145 return;146 }148 Bprint(b, "\t\"");149 cprints(b, t->seq);150 Bprint(b, "\", \"");151 for(i=0; i<256; i++)152 if(t->r[i])153 cprintchar(b, i);154 Bprint(b, "\",\t");155 if(rflag) {156 Bprint(b, "{");157 for(i=0; i<256; i++)158 if(t->r[i])159 Bprint(b, " 0x%.4ux,", t->r[i]);160 Bprint(b, " }");161 } else {162 Bprint(b, "L\"");163 for(i=0; i<256; i++)164 if(t->r[i])165 Bprint(b, "%C", t->r[i]);166 Bprint(b, "\"");167 }168 Bprint(b, ",\n");169 }171 void172 readfile(char *fname)173 {174 Biobuf *b;175 char *line, *p;176 char *seq;177 int inseq;178 int lineno;179 Rune r;181 if((b = Bopen(fname, OREAD)) == 0) {182 fprint(2, "cannot open \"%s\": %r\n", fname);183 exits("open");184 }186 lineno = 0;187 while((line = Brdline(b, '\n')) != 0) {188 lineno++;189 if(line[0] == '#')190 continue;192 r = strtol(line, nil, 16);193 p = strchr(line, ' ');194 if(r == 0 || (p != line+4 && p != line+5) || p[0] != ' ' || (p == line+4 && p[1] != ' ')) {195 fprint(2, "%s:%d: cannot parse line\n", fname, lineno);196 continue;197 }199 p = line+6;200 /* 00AE Or rO ® registered trade mark sign */201 for(inseq=1, seq=p; (uchar)*p < Runeself; p++) {202 if(*p == '\0' || isspace(*p)) {203 if(inseq && p-seq >= 2) {204 *p = '\0';205 inseq = 0;206 insert(seq, r);207 *p = ' ';208 }209 if(*p == '\0')210 break;211 } else {212 if(!inseq) {213 seq = p;214 inseq = 1;215 }216 }217 }218 }219 }221 void222 usage(void)223 {224 fprint(2, "usage: mklatinkbd [-r] [/lib/keyboard]\n");225 exits("usage");226 }228 int kfmt(Fmt*);230 void231 main(int argc, char **argv)232 {233 int i;234 Biobuf bout;236 ARGBEGIN{237 case 'r': /* print rune values */238 rflag = 1;239 break;240 case 'x':241 xflag = 1;242 break;243 default:244 usage();245 }ARGEND247 if(argc > 1)248 usage();250 fmtinstall('k', kfmt);251 readfile(argc == 1 ? argv[0] : "/dev/stdin");253 Binit(&bout, 1, OWRITE);254 if(xflag) {255 Bprint(&bout, "# Generated by mklatinkbd -x; do not edit.\n");256 for(i=0x20; i<0x10000; i++)257 Bprint(&bout, "<Multi_key> <X> <%x> <%x> <%x> <%x> : \"%C\" U%04X\n",258 (i>>12)&0xf, (i>>8)&0xf, (i>>4)&0xf, i&0xf, i, i);259 }260 if(root)261 printtrie(&bout, root);262 exits(0);263 }265 // X11 key names267 struct {268 int c;269 char *s;270 } xkey[] = {271 ' ', "space",272 '!', "exclam",273 '"', "quotedbl",274 '#', "numbersign",275 '$', "dollar",276 '%', "percent",277 '&', "ampersand",278 '\'', "apostrophe",279 '(', "parenleft",280 ')', "parenright",281 '*', "asterisk",282 '+', "plus",283 ',', "comma",284 '-', "minus",285 '.', "period",286 '/', "slash",287 ':', "colon",288 ';', "semicolon",289 '<', "less",290 '=', "equal",291 '>', "greater",292 '?', "question",293 '@', "at",294 '[', "bracketleft",295 '\\', "backslash",296 ',', "bracketright",297 '^', "asciicircum",298 '_', "underscore",299 '`', "grave",300 '{', "braceleft",301 '|', "bar",302 '}', "braceright",303 '~', "asciitilde",304 0, 0305 };307 int308 kfmt(Fmt *f)309 {310 int i, c;312 c = va_arg(f->args, int);313 for(i=0; xkey[i].s; i++)314 if(xkey[i].c == c)315 return fmtprint(f, "<%s>", xkey[i].s);316 return fmtprint(f, "<%c>", c);317 }