tkeyboard(7): document X compose sequences - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit b567422f98b815a45fa8e7144057a8834e98616b
 (DIR) parent 4f52e8afe9e41647cd1742c6fff47ed928ff6c1c
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Sun,  2 Jan 2011 15:39:09 -0500
       
       keyboard(7): document X compose sequences
       
       Add -x flag to mklatinkbd to generate file for $HOME/.XCompose.
       
       Thanks to Anthony Martin, Tony Lainson, and Kris Maglione for legwork.
       
       R=rsc
       http://codereview.appspot.com/3811043
       
       Diffstat:
         M man/man7/keyboard.7                 |      51 +++++++++++++++++++++++++++++++
         M src/cmd/devdraw/mkfile              |       1 +
         M src/cmd/devdraw/mklatinkbd.c        |     130 +++++++++++++++++++++++++------
         M src/cmd/devdraw/x11-itrans.c        |       3 ++-
       
       4 files changed, 162 insertions(+), 23 deletions(-)
       ---
 (DIR) diff --git a/man/man7/keyboard.7 b/man/man7/keyboard.7
       t@@ -171,6 +171,57 @@ yields £.
        .PP
        Note the difference between ß (ss) and µ (micron) and
        the Greek β and μ.
       +.SS "X WINDOWS
       +Under X Windows, both the Alt key and the ``Multi key''
       +can begin a compose sequence in a Plan 9 program.
       +.PP
       +It is also possible to configure X Windows to use the
       +same keystroke mappings as the Plan 9 programs.
       +First, generate an XCompose sequence list by using
       +.IR mklatinkbd :
       +.IP
       +.EX
       +mklatinkbd -x $PLAN9/lib/keyboard >$HOME/.XCompose
       +.EE
       +.LP
       +Second, configure a ``Multi key'' by running
       +.IP
       +.EX
       +xmodmap -e 'keysym Super_L = Multi_key'
       +.EE
       +.LP
       +(The name
       +.L Super_L
       +typically denotes the Windows key on recent keyboards.)
       +.PP
       +Third, set these environment variables so that GTK- and QT-based programs
       +will use the compose sequences:
       +.IP
       +.EX
       +export GTK_IM_MODULE=xim
       +export QT_IM_MODULE=xim
       +.EE
       +.LP
       +Finally, start a new GTK- or QT-based program:
       +.IP
       +.EX
       +gnome-terminal &
       +.EE
       +.LP
       +In that terminal, typing the key sequence
       +.RB ` Windows
       +.B *
       +.BR a '
       +should be interpreted as the Greek letter
       +.LR α .
       +.PP
       +If using the GNOME Window Manager, put the
       +.B xmodmap
       +and
       +.B export
       +commands into the file
       +.B $HOME/.gnomerc
       +to run them automatically at startup.
        .SH FILES
        .TP
        .B \*9/lib/keyboard
 (DIR) diff --git a/src/cmd/devdraw/mkfile b/src/cmd/devdraw/mkfile
       t@@ -48,3 +48,4 @@ $O.macargv: macargv.$O
                $LD -o $target $prereq
        
        install: $MACARGV
       +install: mklatinkbd.install
 (DIR) diff --git a/src/cmd/devdraw/mklatinkbd.c b/src/cmd/devdraw/mklatinkbd.c
       t@@ -9,6 +9,7 @@
        #include <ctype.h>
        
        int rflag;
       +int xflag;
        
        enum {
                MAXLD = 2,        /* latin1.c assumes this is 2 */
       t@@ -115,39 +116,56 @@ cprints(Biobuf *b, char *p)
                        cprintchar(b, *p++);
        }
        
       +void
       +xprint(Biobuf *b, int c)
       +{
       +}
        
        void
        printtrie(Biobuf *b, Trie *t)
        {
                int i;
       +        char *p;
        
                for(i=0; i<256; i++)
                        if(t->link[i])
                                printtrie(b, t->link[i]);
       +        if(t->n == 0)
       +                return;
       +        
       +        if(xflag) {
       +                for(i=0; i<256; i++) {
       +                        if(t->r[i] == 0)
       +                                continue;
       +                        Bprint(b, "<Multi_key>");
       +                        for(p=t->seq; *p; p++)
       +                                Bprint(b, " %k", *p);
       +                        Bprint(b, " %k : \"%C\" U%04X\n", i, t->r[i], t->r[i]);
       +                }
       +                return;                        
       +        }
        
       -        if(t->n > 0) {
       -                Bprint(b, "\t\"");
       -                cprints(b, t->seq);
       -                Bprint(b, "\", \"");
       +        Bprint(b, "\t\"");
       +        cprints(b, t->seq);
       +        Bprint(b, "\", \"");
       +        for(i=0; i<256; i++)
       +                if(t->r[i])
       +                        cprintchar(b, i);
       +        Bprint(b, "\",\t");
       +        if(rflag) {
       +                Bprint(b, "{");
                        for(i=0; i<256; i++)
                                if(t->r[i])
       -                                cprintchar(b, i);
       -                Bprint(b, "\",\t");
       -                if(rflag) {
       -                        Bprint(b, "{");
       -                        for(i=0; i<256; i++)
       -                                if(t->r[i])
       -                                        Bprint(b, " 0x%.4ux,", t->r[i]);
       -                        Bprint(b, " }");
       -                } else {
       -                        Bprint(b, "L\"");
       -                        for(i=0; i<256; i++)
       -                                if(t->r[i])
       -                                        Bprint(b, "%C", t->r[i]);
       -                        Bprint(b, "\"");
       -                }
       -                Bprint(b, ",\n");
       -        }        
       +                                Bprint(b, " 0x%.4ux,", t->r[i]);
       +                Bprint(b, " }");
       +        } else {
       +                Bprint(b, "L\"");
       +                for(i=0; i<256; i++)
       +                        if(t->r[i])
       +                                Bprint(b, "%C", t->r[i]);
       +                Bprint(b, "\"");
       +        }
       +        Bprint(b, ",\n");
        }
        
        void
       t@@ -207,15 +225,21 @@ usage(void)
                exits("usage");
        }
        
       +int kfmt(Fmt*);
       +
        void
        main(int argc, char **argv)
        {
       +        int i;
                Biobuf bout;
        
                ARGBEGIN{
                case 'r':        /* print rune values */
                        rflag = 1;
                        break;
       +        case 'x':
       +                xflag = 1;
       +                break;
                default:
                        usage();
                }ARGEND
       t@@ -223,10 +247,72 @@ main(int argc, char **argv)
                if(argc > 1)
                        usage();
        
       -        readfile(argc == 1 ? argv[0] : "/fd/0");
       +        fmtinstall('k', kfmt);
       +        readfile(argc == 1 ? argv[0] : "/dev/stdin");
        
                Binit(&bout, 1, OWRITE);
       +        if(xflag) {
       +                Bprint(&bout, "# Generated by mklatinkbd -x; do not edit.\n");
       +                for(i=0x20; i<0x10000; i++)
       +                        Bprint(&bout, "<Multi_key> <X> <%x> <%x> <%x> <%x> : \"%C\" U%04X\n",
       +                                (i>>12)&0xf, (i>>8)&0xf, (i>>4)&0xf, i&0xf, i, i);
       +        }
                if(root)
                        printtrie(&bout, root);
                exits(0);
        }
       +
       +// X11 key names
       +
       +struct {
       +        int c;
       +        char *s;
       +} xkey[] = {
       +        ' ', "space",
       +        '!',  "exclam",
       +        '"',  "quotedbl",
       +        '#',  "numbersign",
       +        '$',  "dollar",
       +        '%',  "percent",
       +        '&',  "ampersand",
       +        '\'', "apostrophe",
       +        '(',  "parenleft",
       +        ')',  "parenright",
       +        '*',  "asterisk",
       +        '+',  "plus",
       +        ',',  "comma",
       +        '-',  "minus",
       +        '.',  "period",
       +        '/',  "slash",
       +        ':',  "colon",
       +        ';',  "semicolon",
       +        '<',  "less",
       +        '=',  "equal",
       +        '>',  "greater",
       +        '?',  "question",
       +        '@',  "at",
       +        '[',  "bracketleft",
       +        '\\', "backslash",
       +        ',',  "bracketright",
       +        '^',  "asciicircum",
       +        '_',  "underscore",
       +        '`',  "grave",
       +        '{',  "braceleft",
       +        '|',  "bar",
       +        '}',  "braceright",
       +        '~',  "asciitilde",
       +};
       +
       +int
       +kfmt(Fmt *f)
       +{
       +        int i, c;
       +
       +        c = va_arg(f->args, int);
       +        for(i=0; xkey[i].s; i++)
       +                if(xkey[i].c == c)
       +                        return fmtprint(f, "<%s>", xkey[i].s);
       +        return fmtprint(f, "<%c>", c);
       +}
       +
       +
 (DIR) diff --git a/src/cmd/devdraw/x11-itrans.c b/src/cmd/devdraw/x11-itrans.c
       t@@ -37,7 +37,7 @@ __xtoplan9kbd(XEvent *e)
                needstack(64*1024);        /* X has some *huge* buffers in openobject */
                        /* and they're even bigger on SuSE */
                XLookupString((XKeyEvent*)e,NULL,0,&k,NULL);
       -        if(k == XK_Multi_key || k == NoSymbol)
       +        if(k == k == NoSymbol)
                        return -1;
        
                if(k&0xFF00){
       t@@ -113,6 +113,7 @@ __xtoplan9kbd(XEvent *e)
                        case XK_Meta_L:        /* Shift Alt on PCs */
                        case XK_Alt_R:
                        case XK_Meta_R:        /* Shift Alt on PCs */
       +                case XK_Multi_key:
                                k = Kalt;
                                break;
                        default:                /* not ISO-1 or tty control */