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;
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) {
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;
// 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);
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);
//{ 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
}
}
-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 */
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;
}
}
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)
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) {