]> git.mdlowis.com Git - projs/tide.git/commitdiff
Added real modifier support to keybindings and added keybindings for common non-modal...
authorMichael D. Lowis <mike.lowis@gentex.com>
Tue, 29 Nov 2016 14:37:51 +0000 (09:37 -0500)
committerMichael D. Lowis <mike.lowis@gentex.com>
Tue, 29 Nov 2016 14:37:51 +0000 (09:37 -0500)
inc/edit.h
inc/x11.h
libedit/utils.c
libx/x11.c
xedit.c
xpick.c

index 562f59318e0eef1963c50e41e5e5a5f47c9cb822..c3a67d46b6e040eafc0a688bcf6e3a35660bd1e1 100644 (file)
@@ -7,7 +7,7 @@ typedef struct {
 
 FMap fmap(char* path);
 void funmap(FMap file);
-uint32_t getmillis(void);
+uint64_t getmillis(void);
 bool risword(Rune r);
 bool risblank(Rune r);
 char* stringdup(const char* str);
@@ -214,12 +214,13 @@ enum ColorId {
 /* Global State
  *****************************************************************************/
 typedef struct {
+    int mods;
     Rune key;
     void (*action)(void);
 } KeyBinding;
 
 typedef struct {
-    uint32_t time;
+    uint64_t time;
     uint8_t count;
     bool pressed;
     int region;
index a3ee126c4814cda3017c038e4d98218a653b8fd1..3d3e7886a5b50c2c510a268c7fa9347614ce46d3 100644 (file)
--- a/inc/x11.h
+++ b/inc/x11.h
@@ -16,7 +16,7 @@ typedef enum {
 
 typedef struct {
     void (*redraw)(int width, int height);
-    void (*handle_key)(uint32_t rune);
+    void (*handle_key)(int mods, uint32_t rune);
     void (*handle_mouse)(MouseAct act, MouseBtn btn, int x, int y);
     uint32_t palette[16];
 } XConfig;
@@ -107,6 +107,19 @@ enum Keys {
     KEY_CTRL_UNDERSCORE  = 0x1F,
 };
 
+/* Key modifier masks */
+enum {
+    ModNone       = 0,
+    ModShift      = (1 << 0),
+    ModCapsLock   = (1 << 1),
+    ModCtrl       = (1 << 2),
+    ModAlt        = (1 << 3),
+    ModNumLock    = (1 << 4),
+    ModScrollLock = (1 << 5),
+    ModWindows    = (1 << 6),
+    ModAny        = ModWindows-1
+};
+
 void x11_init(XConfig* cfg);
 void x11_deinit(void);
 void x11_window(char* name, int width, int height);
index 154b34b995b42bf68b7029ed02263fd3c497358d..674c704e60dda7143bcf562d8faeb96f9e3c0925 100644 (file)
 #include <time.h>
 #include <sys/time.h>
 
-uint32_t getmillis(void) {
+uint64_t getmillis(void) {
     struct timespec time;
     clock_gettime(CLOCK_MONOTONIC, &time);
-    return ((time.tv_sec * 1000) + (time.tv_nsec / 1000000));
+    uint64_t ms = ((uint64_t)time.tv_sec * (uint64_t)1000);
+    ms += ((uint64_t)time.tv_nsec / (uint64_t)1000000);
+    return ms;
 }
 
 void die(const char* msgfmt, ...) {
index d700c7b5c191957e40917c140abb9ffa7eaa45c2..f0fffb0ab84ca57b0271f8c51d406e7e57b0ea6c 100644 (file)
@@ -133,23 +133,7 @@ void x11_show(void) {
     XMapWindow(X.display, X.window);
 }
 
-static uint32_t getkey(XEvent* e) {
-    uint32_t rune = 0xFFFD;
-    size_t len = 0;
-    char buf[8];
-    KeySym key;
-    Status status;
-    /* Read the key string */
-    if (X.xic)
-        len = Xutf8LookupString(X.xic, &e->xkey, buf, sizeof(buf), &key, &status);
-    else
-        len = XLookupString(&e->xkey, buf, sizeof(buf), &key, 0);
-    /* decode it */
-    if (len > 0) {
-        len = 0;
-        for(int i = 0; i < 8 && !utf8decode(&rune, &len, buf[i]); i++);
-    }
-    /* translate the key code into a unicode codepoint */
+static uint32_t special_keys(uint32_t key) {
     switch (key) {
         case XK_F1:        return KEY_F1;
         case XK_F2:        return KEY_F2;
@@ -173,8 +157,39 @@ static uint32_t getkey(XEvent* e) {
         case XK_Down:      return KEY_DOWN;
         case XK_Left:      return KEY_LEFT;
         case XK_Right:     return KEY_RIGHT;
-        default:           return rune;
+        default:           return key;
+    }
+}
+
+static uint32_t getkey(XEvent* e) {
+    uint32_t rune = RUNE_ERR;
+    size_t len = 0;
+    char buf[8];
+    KeySym key;
+    Status status;
+    /* Read the key string */
+    if (X.xic)
+        len = Xutf8LookupString(X.xic, &e->xkey, buf, sizeof(buf), &key, &status);
+    else
+        len = XLookupString(&e->xkey, buf, sizeof(buf), &key, 0);
+    /* if it's ascii, just return it */
+    if (key >= 0x20 && key <= 0x7F)
+        return (uint32_t)key;
+    /* decode it */
+    if (len > 0) {
+        len = 0;
+        for (int i = 0; i < 8 && !utf8decode(&rune, &len, buf[i]); i++);
     }
+    /* translate special key codes into unicode codepoints */
+    key = special_keys(key);
+    return rune;
+}
+
+static void handle_key(XEvent* event) {
+    uint32_t key = getkey(event);
+    int mods = event->xkey.state & ModAny;
+    if (key == RUNE_ERR) return;
+    Config->handle_key(mods, key);
 }
 
 static void handle_mouse(XEvent* e) {
@@ -214,7 +229,7 @@ void x11_loop(void) {
                 switch (e.type) {
                     case FocusIn:       if (X.xic) XSetICFocus(X.xic);   break;
                     case FocusOut:      if (X.xic) XUnsetICFocus(X.xic); break;
-                    case KeyPress:      Config->handle_key(getkey(&e));  break;
+                    case KeyPress:      handle_key(&e);                  break;
                     case ButtonRelease: handle_mouse(&e);                break;
                     case ButtonPress:   handle_mouse(&e);                break;
                     case MotionNotify:  handle_mouse(&e);                break;
diff --git a/xedit.c b/xedit.c
index f702f0d345baaafc30a829ab7d055dfbb8887129..c6cb28b03b29ef6c0830c35f16321de6ac680fe0 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -14,7 +14,7 @@ enum RegionId {
 // Input Handlers
 static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y);
 static void tag_handler(char* cmd, char* arg);
-static void key_handler(Rune key);
+static void key_handler(int mods, Rune key);
 
 // Drawing Routines
 static void draw_runes(size_t x, size_t y, int fg, int bg, UGlyph* glyphs, size_t rlen);
@@ -47,6 +47,24 @@ static void search(void);
 static void execute(void);
 static void find(char* arg);
 static void open_file(void);
+static void delrune_right(void);
+static void delword_right(void);
+static void delrune_left(void);
+static void delword_left(void);
+static void cursor_bof(void);
+static void select_bol(void);
+static void select_bof(void);
+static void cursor_eof(void);
+static void select_eol(void);
+static void select_eof(void);
+static void select_up(void);
+static void select_dn(void);
+static void select_left(void);
+static void word_left(void);
+static void selword_left(void);
+static void select_right(void);
+static void word_right(void);
+static void selword_right(void);
 
 // Tag/Cmd Execution
 static Tag* tag_lookup(char* cmd);
@@ -111,41 +129,60 @@ static KeyBinding Bindings[] = {
     //{ KEY_CTRL_U,    del_to_bol   },
     //{ KEY_CTRL_W,    del_to_bow   },
     //{ KEY_CTRL_H,    del_prev_char},
-    { KEY_CTRL_A,    cursor_bol   },
-    { KEY_CTRL_E,    cursor_eol   },
+    { ModCtrl, 'a', cursor_bol },
+    { ModCtrl, 'e', cursor_eol },
 
     /* Standard Text Editing Shortcuts */
-    { KEY_CTRL_S,    save         },
-    { KEY_CTRL_Z,    undo         },
-    { KEY_CTRL_Y,    redo         },
-    { KEY_CTRL_X,    cut          },
-    { KEY_CTRL_C,    copy         },
-    { KEY_CTRL_V,    paste        },
+    { ModCtrl, 's', save  },
+    { ModCtrl, 'z', undo  },
+    { ModCtrl, 'y', redo  },
+    { ModCtrl, 'x', cut   },
+    { ModCtrl, 'c', copy  },
+    { ModCtrl, 'v', paste },
 
     /* Common Special Keys */
-    { KEY_DELETE,    delete       },
-    { KEY_HOME,      cursor_bol   },
-    { KEY_END,       cursor_eol   },
-    { KEY_PGUP,      page_up      },
-    { KEY_PGDN,      page_dn      },
-    { KEY_UP,        cursor_up    },
-    { KEY_DOWN,      cursor_dn    },
-    { KEY_LEFT,      cursor_left  },
-    { KEY_RIGHT,     cursor_right },
+    { ModNone, KEY_PGUP,      page_up       },
+    { ModNone, KEY_PGDN,      page_dn       },
+    { ModNone, KEY_DELETE,    delrune_right },
+    { ModCtrl, KEY_DELETE,    delword_right },
+    { ModNone, KEY_BACKSPACE, delrune_left  },
+    { ModCtrl, KEY_BACKSPACE, delword_left  },
+
+    /* Cursor Movements */
+    { ModNone,          KEY_HOME,   cursor_bol    },
+    { ModCtrl,          KEY_HOME,   cursor_bof    },
+    { ModShift,         KEY_HOME,   select_bol    },
+    { ModCtrl|ModShift, KEY_HOME,   select_bof    },
+    { ModNone,          KEY_END,    cursor_eol    },
+    { ModCtrl,          KEY_END,    cursor_eof    },
+    { ModShift,         KEY_END,    select_eol    },
+    { ModCtrl|ModShift, KEY_END,    select_eof    },
+    { ModNone,          KEY_UP,     cursor_up     },
+    { ModShift,         KEY_UP,     select_up     },
+    { ModNone,          KEY_DOWN,   cursor_dn     },
+    { ModShift,         KEY_DOWN,   select_dn     },
+    { ModNone,          KEY_LEFT,   cursor_left   },
+    { ModShift,         KEY_LEFT,   select_left   },
+    { ModCtrl,          KEY_LEFT,   word_left     },
+    { ModCtrl|ModShift, KEY_LEFT,   selword_left  },
+    { ModNone,          KEY_RIGHT,  cursor_right  },
+    { ModShift,         KEY_RIGHT,  select_right  },
+    { ModCtrl,          KEY_RIGHT,  word_right    },
+    { ModCtrl|ModShift, KEY_RIGHT,  selword_right },
 
     /* Implementation Specific */
-    { KEY_ESCAPE,    select_prev  },
-    { KEY_CTRL_T,    change_focus },
-    { KEY_CTRL_Q,    quit         },
-    { KEY_CTRL_F,    search       },
-    { KEY_CTRL_D,    execute      },
+    { ModAny,  KEY_ESCAPE, select_prev  },
+    { ModCtrl, 't',        change_focus },
+    { ModCtrl, 'q',        quit         },
+    { ModCtrl, 'f',        search       },
+    { ModCtrl, 'd',        execute      },
 
     /* Picker Shortcuts */
-    { KEY_CTRL_O,    open_file    },
+    { ModCtrl, 'o', open_file },
     //{ KEY_CTRL_P,    find_ctag    },
     //{ KEY_CTRL_G,    goto_ctag    },
 
-    { 0,             NULL         }
+    { 0, 0, NULL } // End the table
 };
 
 /* External Commands
@@ -214,7 +251,7 @@ static void mouse_handler(MouseAct act, MouseBtn btn, int x, int y) {
     }
 }
 
-static void key_handler(Rune key) {
+static void key_handler(int mods, Rune key) {
     /* ignore invalid keys */
     if (key == RUNE_ERR) return;
     /* handle the proper line endings */
@@ -222,8 +259,10 @@ static void key_handler(Rune key) {
     if (key == '\n' && currview()->buffer.crlf) key = RUNE_CRLF;
     /* handle the key */
     KeyBinding* bindings = Bindings;
+    uint32_t mkey = tolower(key);
     while (bindings->key) {
-        if (key == bindings->key) {
+        int keymods = bindings->mods;
+        if ((mkey == bindings->key) && (keymods == ModAny || keymods == mods)) {
             bindings->action();
             return;
         }
@@ -395,9 +434,9 @@ static void change_focus(void) {
 }
 
 static void quit(void) {
-    static uint32_t num_clicks = 0;
-    static uint32_t prevtime = 0;
-    uint32_t now = getmillis();
+    static uint64_t num_clicks = 0;
+    static uint64_t prevtime = 0;
+    uint64_t now = getmillis();
     num_clicks = (now - prevtime < 250 ? num_clicks+1 : 1);
     prevtime = now;
     if (!getbuf(EDIT)->modified || num_clicks >= 2)
@@ -472,6 +511,25 @@ static void open_file(void) {
     free(file);
 }
 
+static void delrune_right(void){}
+static void delword_right(void){}
+static void delrune_left(void){}
+static void delword_left(void){}
+static void cursor_bof(void){}
+static void select_bol(void){}
+static void select_bof(void){}
+static void cursor_eof(void){}
+static void select_eol(void){}
+static void select_eof(void){}
+static void select_up(void){}
+static void select_dn(void){}
+static void select_left(void){}
+static void word_left(void){}
+static void selword_left(void){}
+static void select_right(void){}
+static void word_right(void){}
+static void selword_right(void){}
+
 /* Tag/Cmd Execution
  *****************************************************************************/
 static Tag* tag_lookup(char* cmd) {
diff --git a/xpick.c b/xpick.c
index d77ec44abdf357c54b5e1dedf5afe54a6c9b6422..4a8d070325a4284ca80f66e87169a00386e82fca 100644 (file)
--- a/xpick.c
+++ b/xpick.c
@@ -7,7 +7,7 @@
 
 static void redraw(int width, int height);
 static void mouse_input(MouseAct act, MouseBtn btn, int x, int y);
-static void keyboard_input(uint32_t key);
+static void keyboard_input(int mods, uint32_t key);
 
 typedef struct {
     float score;
@@ -163,7 +163,7 @@ static void mouse_input(MouseAct act, MouseBtn btn, int x, int y) {
     (void)y;
 }
 
-static void keyboard_input(uint32_t key) {
+static void keyboard_input(int mods, uint32_t key) {
     switch (key) {
         case KEY_LEFT:  break;
         case KEY_RIGHT: break;