Make command handling much more extensible. - sam - An updated version of the sam text editor.
 (HTM) git clone git://vernunftzentrum.de/sam.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit d7decab5435ea7d2ad95a1c413a15a11c68df625
 (DIR) parent fae7a1407b0bb5b9104a5541307df3210c4c7fef
 (HTM) Author: Rob King <jking@deadpixi.com>
       Date:   Thu, 11 Aug 2016 22:17:44 -0500
       
       Make command handling much more extensible.
       
       Diffstat:
         README.rst                          |       8 +++++++-
         commands.h.def                      |      39 +++++++++++++++++++++++++++++++
         config.h                            |       2 ++
         config.h.def                        |       2 ++
         config.mk.def                       |      15 +++++++++++++++
         include/commands.h                  |       7 ++++++-
         libXg/gwin.c                        |     134 ++++++++-----------------------
         samterm/main.c                      |       6 +++---
       
       8 files changed, 107 insertions(+), 106 deletions(-)
       ---
 (DIR) diff --git a/README.rst b/README.rst
       @@ -21,7 +21,13 @@ Installation
        
        Basic Installation
        -------------------
       -Installation is fairly simple: edit `config.mk` and `config.h` and then run make install.
       +Installation and configuration is fairly simple:
       +
       +- Copy `config.mk.def` to `config.mk` and modify as needed.
       +- Copy `config.h.def` to `config.h` and modify as needed.
       +- Copy `commands.h.def` to `commands.h` and modify as needed.
       +- Run `make clean all`
       +- Run `make install` or, if needed, `sudo make install`
        
        The `sam` command runs sam.
        The `B` command adds a new file to a running instance of sam, or starts sam if it's not already running.
 (DIR) diff --git a/commands.h.def b/commands.h.def
       @@ -0,0 +1,39 @@
       +{COMMANDMASK, XK_e,             Kcommand, Clineup},
       +{COMMANDMASK, XK_x,             Kcommand, Clinedown},
       +{COMMANDMASK, XK_d,             Kcommand, Ccharright},
       +{COMMANDMASK, XK_s,             Kcommand, Ccharleft},
       +{COMMANDMASK, XK_u,             Kcommand, Cdelbol},
       +{COMMANDMASK, XK_w,             Kcommand, Cdelword},
       +{COMMANDMASK, XK_k,             Kcommand, Cjump},
       +
       +{0,           XK_Up,            Kcommand, Cscrollup},
       +{0,           XK_Prior,         Kcommand, Cscrollup},
       +{0,           XK_Left,          Kcommand, Cscrollup},
       +{0,           XK_Down,          Kcommand, Cscrolldown},
       +{0,           XK_Next,          Kcommand, Cscrolldown},
       +{0,           XK_Right,         Kcommand, Cscrolldown},
       +
       +{0,           XK_Escape,        Kcommand, Cescape},
       +{0,           XK_BackSpace,     Kcommand, Cdel},
       +{0,           XK_Delete,        Kcommand, Cdel},
       +
       +{0,           XK_Return,        Kraw,     '\n'},
       +{0,           XK_KP_Enter,      Kraw,     '\n'},
       +{0,           XK_Linefeed,      Kraw,     '\r'},
       +{0,           XK_Tab,           Kraw,     '\t'},
       +{0,           XK_KP_0,          Kraw,     '0'},
       +{0,           XK_KP_1,          Kraw,     '1'},
       +{0,           XK_KP_2,          Kraw,     '2'},
       +{0,           XK_KP_3,          Kraw,     '3'},
       +{0,           XK_KP_4,          Kraw,     '4'},
       +{0,           XK_KP_5,          Kraw,     '5'},
       +{0,           XK_KP_6,          Kraw,     '6'},
       +{0,           XK_KP_7,          Kraw,     '7'},
       +{0,           XK_KP_8,          Kraw,     '8'},
       +{0,           XK_KP_9,          Kraw,     '9'},
       +{0,           XK_KP_Divide,     Kraw,     '/'},
       +{0,           XK_KP_Multiply,   Kraw,     '*'},
       +{0,           XK_KP_Subtract,   Kraw,     '-'},
       +{0,           XK_KP_Add,        Kraw,     '+'},
       +{0,           XK_KP_Decimal,    Kraw,     '.'},
       +{0,           XK_hyphen,        Kraw,     '-'},
 (DIR) diff --git a/config.h b/config.h
       @@ -19,6 +19,8 @@
        #define CHARLEFT    0x13 /* Ctrl-S */
        #define CHARRIGHT   0x04 /* Ctrl-D */
        #define COMMANDKEY  0x0B /* Ctrl-K */
       +#define DELWORD     0x17 /* Ctrl-W */
       +#define DELBOL      0x15 /* Ctrl-U */
        
        /* The remote shell to use for remote connections. */
        #define RXPATH "/usr/bin/ssh"
 (DIR) diff --git a/config.h.def b/config.h.def
       @@ -19,6 +19,8 @@
        #define CHARLEFT    0x13 /* Ctrl-S */
        #define CHARRIGHT   0x04 /* Ctrl-D */
        #define COMMANDKEY  0x0B /* Ctrl-K */
       +#define DELWORD     0x17 /* Ctrl-W */
       +#define DELBOL      0x15 /* Ctrl-U */
        
        /* The remote shell to use for remote connections. */
        #define RXPATH "/usr/bin/ssh"
 (DIR) diff --git a/config.mk.def b/config.mk.def
       @@ -0,0 +1,15 @@
       +# config.mk - makefile configuration for sam
       +# copyright 2015 Rob King <jking@deadpixi.com>
       +
       +# DESTDIR is the root of the installation tree
       +DESTDIR?=/usr/local
       +
       +# BINDIR is the directory where binaries go
       +BINDIR?=$(DESTDIR)/bin
       +
       +# MANDIR is where manual pages go
       +MANDIR?=$(DESTDIR)/share/man/man1
       +
       +# FREETYPEINC should name the directory of your freetype2 includes.
       +FREETYPEINC?=/usr/include/freetype2
       +
 (DIR) diff --git a/include/commands.h b/include/commands.h
       @@ -5,10 +5,12 @@ enum{
            Knone,
            Kraw,
            Kcomposed,
       -    Kcommand
       +    Kcommand,
       +    Kend
        };
        
        enum{
       +    Cnone,
            Cescape,
            Cscrolldown,
            Cscrollup,
       @@ -20,6 +22,9 @@ enum{
            Cdelword,
            Cdelbol,
            Cdel,
       +    Csnarf,
       +    Ccut,
       +    Cpaste,
            Cmax
        }; /* virtual command keystrokes */
        
 (DIR) diff --git a/libXg/gwin.c b/libXg/gwin.c
       @@ -166,6 +166,20 @@ Mappingaction(Widget w, XEvent *e, String *p, Cardinal *np)
                                                for (c = 0; c < composing; c++) \
                                                        (*f)(compose[c], 0)
        
       +typedef struct Keymapping Keymapping;
       +struct Keymapping{
       +    int mask;
       +    int sym;
       +    int kind;
       +    int result;
       +};
       +
       +#define COMMANDMASK ControlMask
       +Keymapping keymappings[] ={
       +    #include "../commands.h"
       +    {0, 0, Kend, 0}
       +};
       +
        static void
        Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
        {
       @@ -186,8 +200,22 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
                 */
                if(e->xany.type != KeyPress)
                        return;
       -        XtTranslateKeycode(e->xany.display, (KeyCode)e->xkey.keycode,
       -                        e->xkey.state, &md, &k);
       +
       +        XtTranslateKeycode(e->xany.display, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k);
       +
       +    /* Check to see if it's a specially-handled key first. */
       +    Keymapping *m = keymappings;
       +    while (m->kind != Kend){
       +        if (e->xkey.state == m->mask && k == m->sym){
       +                f = ((GwinWidget)w)->gwin.gotchar;
       +                if(f)
       +                        (*f)(m->result, m->kind);
       +            return;
       +        }
       +
       +        m++;
       +    }
       +
                /*
                 * The following song and dance is so we can have our chosen
                 * modifier key behave like a compose key, i.e, press and release
       @@ -208,84 +236,15 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
                        }
                        return;
                }
       +
                /* Handle Multi_key separately, since it isn't a modifier */
                if(k == XK_Multi_key) {
                        composing = -1;
                        return;
                }
       -        if(k == NoSymbol)
       -                return;
       -
       -    if (k & 0xFF00){
       -        switch(k){
       -            case XK_Escape:
       -                kind = Kcommand;
       -                k = Cescape;
       -                break;
       -
       -            case XK_BackSpace:
       -            case XK_Delete:
       -                kind = Kcommand;
       -                k = Cdel;
       -                break;
       -
       -            case XK_Tab:
       -            case XK_KP_0:
       -            case XK_KP_1:
       -            case XK_KP_2:
       -            case XK_KP_3:
       -            case XK_KP_4:
       -            case XK_KP_5:
       -            case XK_KP_6:
       -            case XK_KP_7:
       -            case XK_KP_8:
       -            case XK_KP_9:
       -            case XK_KP_Divide:
       -            case XK_KP_Multiply:
       -            case XK_KP_Subtract:
       -            case XK_KP_Add:
       -            case XK_KP_Decimal:
       -                k &= 0x7F;
       -                break;
       -
       -            case XK_Linefeed:
       -                k = '\r';
       -                break;
       -
       -            case XK_KP_Enter:
       -            case XK_Return:
       -                k = '\n';
       -                break;
       -
       -            case XK_Up:
       -            case XK_Prior:
       -            case XK_Left:
       -                kind = Kcommand;
       -                k = Cscrollup;
       -                break;
       -
       -            case XK_Right:
       -            case XK_Next:
       -            case XK_Down:
       -                kind = Kcommand;
       -                k = Cscrolldown;
       -                break;
       -
       -            default:
       -                return;        /* not ISO-1 or tty control */
       -        }
       -    }
        
       -        /* Compensate for servers that call a minus a hyphen */
       -    if (k == XK_hyphen)
       -        k = XK_minus;
       -
       -        /* Do control mapping ourselves if translator doesn't */
       -    if ((e->xkey.state & ControlMask) && !(md & ControlMask))
       -        k &= 0x9f;
       -
       -    if(k == NoSymbol)
       -        return;
       +        if(k == NoSymbol || k > 0xff00)
       +                return;
        
                /* Check to see if we are in a composition sequence */
                if (!((GwinWidget)w)->gwin.compose && (e->xkey.state & Mod1Mask)
       @@ -329,33 +288,6 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
                if (composing >= -1)
                        return;
        
       -    switch (c){
       -        case LINEUP:
       -            kind = Kcommand;
       -            c = Clineup;
       -            break;
       -
       -        case LINEDOWN:
       -            kind = Kcommand;
       -            c = Clinedown;
       -            break;
       -
       -        case CHARLEFT:
       -            kind = Kcommand;
       -            c = Ccharleft;
       -            break;
       -
       -        case CHARRIGHT:
       -            kind = Kcommand;
       -            c = Ccharright;
       -            break;
       -
       -        case COMMANDKEY:
       -            kind = Kcommand;
       -            c = Cjump;
       -            break;
       -    }
       -
                f = ((GwinWidget)w)->gwin.gotchar;
                if(f)
                        (*f)(c, kind);
 (DIR) diff --git a/samterm/main.c b/samterm/main.c
       @@ -680,7 +680,7 @@ typedef long (*Commandfunc)(Flayer *, long, Text *);
        typedef struct CommandEntry CommandEntry;
        struct CommandEntry{
            Commandfunc f;
       -    int lock;
       +    int unlocked;
        };
        
        CommandEntry commands[Cmax] ={
       @@ -760,8 +760,8 @@ type(Flayer *l, int res)        /* what a bloody mess this is */
            }
        
            if (k.k == Kcommand){
       -        CommandEntry *e = &commands[k.k];
       -        if (e->lock == 0 || !lock)
       +        CommandEntry *e = &commands[k.c];
       +        if (!e->unlocked || !lock)
                    a = e->f(l, a, t);
            }