ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit 8c56c0d034a6e99583be2d9926946997c8fa82bb
parent b4c5e772118e3f198989732e3aee1146ef9b5217
Author: lumidify <nobody@lumidify.org>
Date:   Wed, 22 Dec 2021 21:44:07 +0100

Fix various problems

* Sort of clean up key types
* Change cursor type over text area
* Fix cache invalidation
* Make 'G' work with selections
* Improve themes

Diffstat:
Mkeys_basic.c | 38+++++++++++++++++++++++---------------
Mkeys_basic_config.h | 226+++++++++++++++++++++++++++++++++++--------------------------------------------
Mkeys_command.c | 2+-
Mledit.1 | 2++
Mledit.c | 1+
Mtheme.c | 7+++++++
Mtheme.h | 5+++++
Mtheme_config.h | 5+++--
Mview.c | 11+++++++++--
Mwindow.c | 44++++++++++++++++++++++----------------------
Mwindow.h | 1+
11 files changed, 174 insertions(+), 168 deletions(-)

diff --git a/keys_basic.c b/keys_basic.c @@ -147,8 +147,8 @@ push_key_stack(void) { key_stack.alloc = new_alloc; } e = &key_stack.stack[key_stack.len]; - e->key = KEY_NONE; - e->followup = KEY_NONE; + e->key = KEY_INVALID; + e->followup = KEY_INVALID; e->motion_cb = NULL; e->count = 0; key_stack.len++; @@ -629,7 +629,10 @@ move_to_line(ledit_view *view, char *text, size_t len) { ledit_line *ll = buffer_get_line(view->buffer, line - 1); cb(view, line - 1, ll->len, KEY_MOTION_LINE); } else { - view_wipe_line_cursor_attrs(view, view->cur_line); + if (view->mode == NORMAL) + view_wipe_line_cursor_attrs(view, view->cur_line); + else + view_set_selection(view, view->sel.line1, view->sel.byte1, line - 1, 0); view->cur_line = line - 1; view->cur_index = 0; int text_w, text_h; @@ -642,7 +645,8 @@ move_to_line(ledit_view *view, char *text, size_t len) { vl->y_offset + h > view->display_offset + text_h) { view_scroll(view, vl->y_offset - text_h / 2); } - view_set_line_cursor_attrs(view, view->cur_line, view->cur_index); + if (view->mode == NORMAL) + view_set_line_cursor_attrs(view, view->cur_line, view->cur_index); discard_repetition_stack(); } return (struct action){ACTION_NONE, NULL}; @@ -932,7 +936,7 @@ change(ledit_view *view, char *text, size_t len) { return err_invalid_key(view); } else { struct key_stack_elem *e = push_key_stack(); - e->key = KEY_MOTION; /* ? */ + e->key = KEY_MOTIONALLOWED; e->count = num; e->motion_cb = &change_cb; } @@ -1010,7 +1014,7 @@ yank(ledit_view *view, char *text, size_t len) { clear_key_stack(); } else if (cb == NULL) { struct key_stack_elem *e = push_key_stack(); - e->key = KEY_MOTION; + e->key = KEY_MOTIONALLOWED; e->count = num; e->motion_cb = &yank_cb; } else { @@ -1116,7 +1120,7 @@ delete(ledit_view *view, char *text, size_t len) { return err_invalid_key(view); } else { struct key_stack_elem *e = push_key_stack(); - e->key = KEY_MOTION; /* ? */ + e->key = KEY_MOTIONALLOWED; e->count = num; e->motion_cb = &delete_cb; } @@ -2231,7 +2235,7 @@ toggle_hard_line_based(ledit_view *view, char *text, size_t len) { } static struct action -handle_key(ledit_view *view, char *key_text, size_t len, KeySym sym, unsigned int key_state, int lang_index, int *found) { +handle_key(ledit_view *view, char *key_text, size_t len, KeySym sym, unsigned int key_state, int lang_index, int *found, enum key_type *type) { struct key *cur_keys = keys[lang_index].keys; int num_keys = keys[lang_index].num_keys; struct key_stack_elem *e = peek_key_stack(); @@ -2249,18 +2253,21 @@ handle_key(ledit_view *view, char *key_text, size_t len, KeySym sym, unsigned in if (cur_keys[i].text) { if (len > 0 && (cur_keys[i].modes & view->mode) && - (!e || (e->key & cur_keys[i].prev_keys)) && + (cur_keys[i].prev_keys == KEY_ANY || (!e && (cur_keys[i].prev_keys & KEY_NONE)) || (e && (e->key & cur_keys[i].prev_keys))) && ((!strncmp(cur_keys[i].text, key_text, len) && match_key(cur_keys[i].mods, key_state & ~ShiftMask)) || cur_keys[i].text[0] == '\0')) { /* FIXME: seems a bit hacky to remove shift, but it is needed to make keys that use shift match */ + *type = cur_keys[i].type; *found = 1; return cur_keys[i].func(view, key_text, len); } } else if ((cur_keys[i].modes & view->mode) && - cur_keys[i].keysym == sym && - match_key(cur_keys[i].mods, key_state)) { + cur_keys[i].keysym == sym && + (cur_keys[i].prev_keys == KEY_ANY || (!e && (cur_keys[i].prev_keys & KEY_NONE)) || (e && (e->key & cur_keys[i].prev_keys))) && + match_key(cur_keys[i].mods, key_state)) { + *type = cur_keys[i].type; *found = 1; return cur_keys[i].func(view, key_text, len); } @@ -2284,12 +2291,13 @@ repeat_command(ledit_view *view, char *text, size_t len) { return (struct action){ACTION_NONE, NULL}; } int found; + enum key_type type; repetition_stack.replaying = 1; for (int i = 0; i < num; i++) { unwind_repetition_stack(); struct repetition_stack_elem *e = get_cur_repetition_stack_elem(); while (e) { - (void)handle_key(view, e->key_text, e->len, e->sym, e->key_state, e->lang_index, &found); + (void)handle_key(view, e->key_text, e->len, e->sym, e->key_state, e->lang_index, &found, &type); advance_repetition_stack(); e = get_cur_repetition_stack_elem(); } @@ -2322,14 +2330,14 @@ basic_key_handler(ledit_view *view, XEvent *event, int lang_index) { int found = 0; int msg_shown = view->window->message_shown; view->window->message_shown = 0; /* FIXME: this is hacky */ - struct action act = handle_key(view, buf, (size_t)n, sym, key_state, lang_index, &found); + enum key_type type; + struct action act = handle_key(view, buf, (size_t)n, sym, key_state, lang_index, &found, &type); if (found && n > 0 && !view->window->message_shown) window_hide_message(view->window); else if (msg_shown) view->window->message_shown = msg_shown; - /* FIXME: add attribute for this to keys - this doesn't take e.g. cursor keys into account! */ - if (found && n > 0) + if (found && (type & KEY_ENSURE_CURSOR_SHOWN)) view_ensure_cursor_shown(view); if (!found && n > 0) window_show_message(view->window, "Invalid key", -1); diff --git a/keys_basic_config.h b/keys_basic_config.h @@ -2,17 +2,21 @@ * These are all the regular keys used in normal, visual, and insert mode. */ -/* FIXME: these aren't really used properly */ +/* + * Note: The key types are currently very inconsistent and don't always make + * sense. This will hopefully be fixed sometime. (FIXME) + */ + enum key_type { - KEY_NONE = 0, - KEY_MISC = 1, - KEY_CHAR = 2, + KEY_INVALID = 0, + KEY_NONE = 2, KEY_MOTION_CHAR = 4, KEY_MOTION_LINE = 8, KEY_MOTION = 4|8, - KEY_NUMBER = 16, - KEY_NUMBERALLOWED = 32, - KEY_ACTIONCALLBACK = 64, + KEY_MOTIONALLOWED = 16, + KEY_NUMBER = 32, + KEY_NUMBERALLOWED = 64, + KEY_ENSURE_CURSOR_SHOWN = 128, /* jump to cursor if it is off screen */ KEY_ANY = 0xFF }; @@ -20,9 +24,9 @@ struct key { char *text; /* for keys that correspond with text */ unsigned int mods; /* modifier mask */ KeySym keysym; /* for other keys, e.g. arrow keys */ - ledit_mode modes; /* modes in which this keybinding is functional */ + ledit_mode modes; /* modes in which this keybinding is functional */ enum key_type prev_keys; /* allowed previous keys */ - enum key_type key_types; /* key types - used to determine if the key is allowed */ + enum key_type type; /* type of key - mainly used for ensure_cursor_shown */ struct action (*func)(ledit_view *, char *, size_t); /* callback function */ }; @@ -102,133 +106,103 @@ static struct action toggle_hard_line_based(ledit_view *view, char *text, size_t /* FIXME: maybe sort these and use binary search -> but that would mess with the catch-all keys */ -/* FIXME: sort out the key types */ static struct key keys_en[] = { - {NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, - {NULL, 0, XK_Left, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_left}, - {NULL, 0, XK_Right, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_right}, - {NULL, 0, XK_Up, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, - {NULL, 0, XK_Down, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_down}, - {NULL, XK_ANY_MOD, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, - {NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, - {NULL, 0, XK_Escape, NORMAL|VISUAL|INSERT, KEY_ANY, KEY_ANY, &escape_key}, - {"i", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &enter_insert}, - {"h", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_left}, - {"l", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_right}, - {"j", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_down}, - {"k", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_up}, - {"h", ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_left}, - {"t", ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &toggle_hard_line_based}, - {NULL, 0, XK_space, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_right}, - {"j", ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_down}, - {"n", ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_down}, - {"p", ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_up}, - {"0", 0, 0, NORMAL|VISUAL, ~KEY_NUMBER, KEY_ANY, &cursor_to_beginning}, - {"0", 0, 0, NORMAL|VISUAL, KEY_NUMBER, KEY_NUMBER, &push_0}, - {"1", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_1}, - {"2", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_2}, - {"3", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_3}, - {"4", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_4}, - {"5", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_5}, - {"6", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_6}, - {"7", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_7}, - {"8", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_8}, - {"9", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_9}, - {"x", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &delete_chars_forwards}, - {"X", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &delete_chars_backwards}, - {"d", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &delete}, - {"y", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &yank}, - {"Y", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &yank_lines}, - {"c", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &change}, - {"v", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_visual}, - {"o", 0, 0, VISUAL, KEY_ANY, KEY_ANY, &switch_selection_end}, - {"c", ControlMask, 0, VISUAL, KEY_ANY, KEY_ANY, &clipcopy}, - {"v", ControlMask, 0, INSERT, KEY_ANY, KEY_ANY, &clippaste}, - {"g", ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &show_line}, - {":", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &enter_commandedit}, - {"?", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_searchedit_backward}, - {"/", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_searchedit_forward}, - {"n", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &key_search_next}, - {"N", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &key_search_prev}, - {"u", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &undo}, - {"U", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &redo}, - {".", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &repeat_command}, /* FIXME: only allow after finished key sequence */ - {"z", ControlMask, 0, INSERT, KEY_ANY, KEY_ANY, &undo}, - {"y", ControlMask, 0, INSERT, KEY_ANY, KEY_ANY, &redo}, /* FIXME: this is confusing with ctrl+y in normal mode */ - {"b", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &screen_up}, - {"f", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &screen_down}, - {"e", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &scroll_with_cursor_down}, - {"y", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &scroll_with_cursor_up}, - {"d", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &scroll_lines_down}, - {"u", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &scroll_lines_up}, - {"$", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &move_to_eol}, - {"w", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &next_word}, - {"e", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &next_word_end}, - {"W", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &next_bigword}, - {"E", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &next_bigword_end}, - {"b", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &prev_word}, - {"B", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &prev_bigword}, - {"G", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &move_to_line}, - {"J", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &join_lines}, - {"I", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &insert_at_beginning}, - {"p", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &paste_normal}, - {"P", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &paste_normal_backwards}, - {"A", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &append_after_eol}, - {"a", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &append_after_cursor}, - {"O", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &append_line_above}, - {"o", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &append_line_below}, - {"m", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &mark_line}, - {"'", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &jump_to_mark}, - {"C", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &change_to_eol}, - {"D", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &delete_to_eol}, - {"r", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &replace}, - {"^", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &cursor_to_first_non_ws}, - {"t", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_next_char_forwards}, - {"T", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_next_char_backwards}, - {"f", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_char_forwards}, - {"F", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBERALLOWED, &find_char_backwards}, - {"", 0, 0, INSERT, KEY_ANY, KEY_ANY, &insert_mode_insert_text} + {NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &backspace}, + {NULL, 0, XK_Left, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left}, + {NULL, 0, XK_Right, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right}, + {NULL, 0, XK_Up, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up}, + {NULL, 0, XK_Down, VISUAL|INSERT|NORMAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down}, + {NULL, XK_ANY_MOD, XK_Return, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &return_key}, + {NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &delete_key}, + {NULL, 0, XK_Escape, NORMAL|VISUAL|INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &escape_key}, + {"i", 0, 0, NORMAL|VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_insert}, + {"h", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left}, + {"l", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right}, + {"j", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down}, + {"k", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up}, + {"h", ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_left}, + {"t", ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &toggle_hard_line_based}, + {NULL, 0, XK_space, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_right}, + {"j", ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down}, + {"n", ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_down}, + {"p", ControlMask, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &cursor_up}, + {"0", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_beginning}, + {"0", 0, 0, NORMAL|VISUAL, KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &push_0}, + {"1", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_1}, + {"2", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_2}, + {"3", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_3}, + {"4", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_4}, + {"5", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_5}, + {"6", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_6}, + {"7", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_7}, + {"8", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_8}, + {"9", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_NUMBERALLOWED, KEY_ENSURE_CURSOR_SHOWN, &push_9}, + {"x", 0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_forwards}, + {"X", 0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &delete_chars_backwards}, + {"d", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &delete}, + {"y", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &yank}, + {"Y", 0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &yank_lines}, + {"c", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &change}, + {"v", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &enter_visual}, + {"o", 0, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &switch_selection_end}, + {"c", ControlMask, 0, VISUAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clipcopy}, + {"v", ControlMask, 0, INSERT, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &clippaste}, + {"g", ControlMask, 0, NORMAL|VISUAL, KEY_ANY, KEY_NONE, &show_line}, + {":", 0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &enter_commandedit}, + {"?", 0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_backward}, + {"/", 0, 0, NORMAL, KEY_NONE, KEY_NONE, &enter_searchedit_forward}, + {"n", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_next}, + {"N", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &key_search_prev}, + {"u", 0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &undo}, + {"U", 0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &redo}, + {".", 0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &repeat_command}, /* FIXME: only allow after finished key sequence */ + {"z", ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &undo}, + {"y", ControlMask, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &redo}, /* FIXME: this is confusing with ctrl+y in normal mode */ + {"b", ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_up}, + {"f", ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &screen_down}, + {"e", ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_down}, + {"y", ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_with_cursor_up}, + {"d", ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_down}, + {"u", ControlMask, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &scroll_lines_up}, + {"$", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_eol}, + {"w", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word}, + {"e", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_word_end}, + {"W", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword}, + {"E", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &next_bigword_end}, + {"b", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_word}, + {"B", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &prev_bigword}, + {"G", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &move_to_line}, + {"J", 0, 0, NORMAL, KEY_NONE|KEY_NUMBER, KEY_ENSURE_CURSOR_SHOWN, &join_lines}, + {"I", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &insert_at_beginning}, + {"p", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal}, + {"P", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &paste_normal_backwards}, + {"A", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_eol}, + {"a", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_after_cursor}, + {"O", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_above}, + {"o", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &append_line_below}, + {"m", 0, 0, NORMAL|VISUAL, KEY_NONE, KEY_NONE, &mark_line}, + {"'", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &jump_to_mark}, + {"C", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &change_to_eol}, + {"D", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &delete_to_eol}, + {"r", 0, 0, NORMAL, KEY_NONE, KEY_ENSURE_CURSOR_SHOWN, &replace}, + {"^", 0, 0, NORMAL, KEY_NONE|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &cursor_to_first_non_ws}, + {"t", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_forwards}, + {"T", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_next_char_backwards}, + {"f", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_forwards}, + {"F", 0, 0, NORMAL|VISUAL, KEY_NONE|KEY_NUMBER|KEY_MOTIONALLOWED, KEY_ENSURE_CURSOR_SHOWN, &find_char_backwards}, + {"", 0, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &insert_mode_insert_text} }; static struct key keys_de[] = { - {"", 0, 0, INSERT, KEY_ANY, KEY_ANY, &insert_mode_insert_text} + {"", 0, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &insert_mode_insert_text} }; static struct key keys_ur[] = { - {NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, - {NULL, 0, XK_Left, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_left}, - {NULL, 0, XK_Right, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_right}, - {NULL, 0, XK_Up, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, - {NULL, 0, XK_Down, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_down}, - {NULL, 0, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, - {NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, - {NULL, 0, XK_Escape, INSERT, KEY_ANY, KEY_ANY, &escape_key}, - {"ی", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_insert}, - {"ح", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_left}, - {"ل", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_right}, - {"ج", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_down}, - {"ک", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_up}, - {"0", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &cursor_to_beginning}, - {"چ", ControlMask, 0, INSERT|VISUAL, KEY_ANY, KEY_ANY, &clipcopy}, - {"", 0, 0, INSERT, KEY_ANY, KEY_ANY, &insert_mode_insert_text} + {"", 0, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &insert_mode_insert_text} }; static struct key keys_hi[] = { - {NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, - {NULL, 0, XK_Left, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_left}, - {NULL, 0, XK_Right, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_right}, - {NULL, 0, XK_Up, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, - {NULL, 0, XK_Down, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_down}, - {NULL, 0, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, - {NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, - {NULL, 0, XK_Escape, INSERT, KEY_ANY, KEY_ANY, &escape_key}, - {"ि", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_insert}, - {"ह", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_left}, - {"ल", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_right}, - {"ज", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_down}, - {"क", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_up}, - {"0", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &cursor_to_beginning}, - {"", 0, 0, INSERT, KEY_ANY, KEY_ANY, &insert_mode_insert_text} + {"", 0, 0, INSERT, KEY_ANY, KEY_ENSURE_CURSOR_SHOWN, &insert_mode_insert_text} }; GEN_KEY_ARRAY(struct key, keys_en, keys_de, keys_ur, keys_hi); diff --git a/keys_command.c b/keys_command.c @@ -307,7 +307,7 @@ substitute_all_remaining(ledit_view *view) { } if (min_line < view->lines_num) buffer_recalc_all_views_from_line(view->buffer, min_line); - window_show_message_fmt(view->window, "Replaced %d occurrences", sub_state.num); + window_show_message_fmt(view->window, "Replaced %d occurrence(s)", sub_state.num); /* this doesn't need to be added to the undo stack since it's called on undo/redo anyways */ view->cur_index = view_get_legal_normal_pos(view, view->cur_line, view->cur_index); view_set_line_cursor_attrs(view, view->cur_line, view->cur_index); diff --git a/ledit.1 b/ledit.1 @@ -1,6 +1,8 @@ .\" TODO: .\" paste buffer line vs. char oriented .\" bigword, etc. +.\" commands - no good way for mapping found +.\" difference between unicode char and grapheme .\" .\" WARNING: Some parts of this are stolen shamelessly from OpenBSD's .\" vi(1) manpage! diff --git a/ledit.c b/ledit.c @@ -91,6 +91,7 @@ mainloop(void) { change_kbd = 1; continue; } + /* FIXME: why None? */ if (XFilterEvent(&event, None)) continue; ledit_view *view = NULL; diff --git a/theme.c b/theme.c @@ -13,13 +13,18 @@ theme_create(ledit_common *common) { ledit_theme *theme = ledit_malloc(sizeof(ledit_theme)); theme->scrollbar_width = SCROLLBAR_WIDTH; theme->scrollbar_step = SCROLLBAR_STEP; + theme->text_font = TEXT_FONT; theme->text_size = TEXT_SIZE; theme->text_fg_hex = TEXT_FG; theme->text_bg_hex = TEXT_BG; + theme->bar_fg_hex = BAR_FG; + theme->bar_bg_hex = BAR_BG; theme->scrollbar_fg_hex = SCROLLBAR_FG; theme->scrollbar_bg_hex = SCROLLBAR_BG; XftColorAllocName(common->dpy, common->vis, common->cm, TEXT_FG, &theme->text_fg); XftColorAllocName(common->dpy, common->vis, common->cm, TEXT_BG, &theme->text_bg); + XftColorAllocName(common->dpy, common->vis, common->cm, BAR_FG, &theme->bar_fg); + XftColorAllocName(common->dpy, common->vis, common->cm, BAR_BG, &theme->bar_bg); XftColorAllocName(common->dpy, common->vis, common->cm, SCROLLBAR_FG, &theme->scrollbar_fg); XftColorAllocName(common->dpy, common->vis, common->cm, SCROLLBAR_BG, &theme->scrollbar_bg); return theme; @@ -29,6 +34,8 @@ void theme_destroy(ledit_common *common, ledit_theme *theme) { XftColorFree(common->dpy, common->vis, common->cm, &theme->text_fg); XftColorFree(common->dpy, common->vis, common->cm, &theme->text_bg); + XftColorFree(common->dpy, common->vis, common->cm, &theme->bar_fg); + XftColorFree(common->dpy, common->vis, common->cm, &theme->bar_bg); XftColorFree(common->dpy, common->vis, common->cm, &theme->scrollbar_fg); XftColorFree(common->dpy, common->vis, common->cm, &theme->scrollbar_bg); free(theme); diff --git a/theme.h b/theme.h @@ -10,10 +10,15 @@ typedef struct { int text_size; XftColor text_fg; XftColor text_bg; + XftColor bar_fg; + XftColor bar_bg; XftColor scrollbar_fg; XftColor scrollbar_bg; + const char *text_font; const char *text_fg_hex; const char *text_bg_hex; + const char *bar_fg_hex; + const char *bar_bg_hex; const char *scrollbar_fg_hex; const char *scrollbar_bg_hex; } ledit_theme; diff --git a/theme_config.h b/theme_config.h @@ -1,8 +1,9 @@ -/* FIXME: different bg for bottom bar */ -/* FIXME: configure font here */ +static const char *TEXT_FONT = "Monospace"; static const int TEXT_SIZE = 12; static const char *TEXT_FG = "#000000"; static const char *TEXT_BG = "#FFFFFF"; +static const char *BAR_FG = "#000000"; +static const char *BAR_BG = "#CCCCCC"; /* FIXME: give in units other than pixels */ static const int SCROLLBAR_WIDTH = 10; diff --git a/view.c b/view.c @@ -229,6 +229,10 @@ view_notify_delete_text(ledit_view *view, size_t line, size_t index, size_t len) void view_notify_append_line(ledit_view *view, size_t line) { + cache_invalidate_from_line( + view->cache, line + 1, view, + &invalidate_pixmap_line_helper, &invalidate_layout_line_helper + ); resize_and_move_line_gap(view, add_sz(view->lines_num, 1), line + 1); if (line < view->cur_line) view->cur_line++; @@ -1756,11 +1760,12 @@ static void view_button_handler(void *data, XEvent *event) { size_t l, b; ledit_view *view= (ledit_view *)data; - int x = event->xbutton.x; - int y = event->xbutton.y; + int x, y; int snap; switch (event->type) { case ButtonPress: + x = event->xbutton.x; + y = event->xbutton.y; snap = view->mode == NORMAL ? 0 : 1; view_xy_to_line_byte(view, x, y, snap, &l, &b); view->selecting = 1; @@ -1780,6 +1785,8 @@ view_button_handler(void *data, XEvent *event) { view->selecting = 0; break; case MotionNotify: + x = event->xmotion.x; + y = event->xmotion.y; if (view->selecting) { y = y >= 0 ? y : 0; view_xy_to_line_byte(view, x, y, 1, &l, &b); diff --git a/window.c b/window.c @@ -8,6 +8,7 @@ #include <X11/Xlib.h> #include <X11/Xatom.h> #include <X11/Xutil.h> +#include <X11/cursorfont.h> #include <pango/pangoxft.h> #include <X11/extensions/Xdbe.h> @@ -122,8 +123,8 @@ redraw_line_text(ledit_window *window) { pango_layout_set_text(window->bb->line, window->bb->line_text, window->bb->line_len); pango_layout_get_pixel_size(window->bb->line, &window->bb->line_w, &window->bb->line_h); draw_grow(window, window->bb->line_draw, window->bb->line_w, window->bb->line_h); - XftDrawRect(window->bb->line_draw->xftdraw, &window->theme->text_bg, 0, 0, window->bb->line_w, window->bb->line_h); - pango_xft_render_layout(window->bb->line_draw->xftdraw, &window->theme->text_fg, window->bb->line, 0, 0); + XftDrawRect(window->bb->line_draw->xftdraw, &window->theme->bar_bg, 0, 0, window->bb->line_w, window->bb->line_h); + pango_xft_render_layout(window->bb->line_draw->xftdraw, &window->theme->bar_fg, window->bb->line, 0, 0); recalc_text_size(window); window->redraw = 1; } @@ -231,15 +232,8 @@ window_delete_bottom_bar_char(ledit_window *window, int dir) { ); window->bb->line_len -= (byte - window->bb->line_cur_pos); } - /* FIXME: move to separate function */ window->bb->line_text[window->bb->line_len] = '\0'; - pango_layout_set_text(window->bb->line, window->bb->line_text, window->bb->line_len); - pango_layout_get_pixel_size(window->bb->line, &window->bb->line_w, &window->bb->line_h); - draw_grow(window, window->bb->line_draw, window->bb->line_w, window->bb->line_h); - XftDrawRect(window->bb->line_draw->xftdraw, &window->theme->text_bg, 0, 0, window->bb->line_w, window->bb->line_h); - pango_xft_render_layout(window->bb->line_draw->xftdraw, &window->theme->text_fg, window->bb->line, 0, 0); - recalc_text_size(window); - window->redraw = 1; + redraw_line_text(window); } void @@ -358,8 +352,8 @@ window_set_mode(ledit_window *window, ledit_mode mode) { free(final_text); pango_layout_get_pixel_size(window->bb->mode, &window->bb->mode_w, &window->bb->mode_h); draw_grow(window, window->bb->mode_draw, window->bb->mode_w, window->bb->mode_h); - XftDrawRect(window->bb->mode_draw->xftdraw, &window->theme->text_bg, 0, 0, window->bb->mode_w, window->bb->mode_h); - pango_xft_render_layout(window->bb->mode_draw->xftdraw, &window->theme->text_fg, window->bb->mode, 0, 0); + XftDrawRect(window->bb->mode_draw->xftdraw, &window->theme->bar_bg, 0, 0, window->bb->mode_w, window->bb->mode_h); + pango_xft_render_layout(window->bb->mode_draw->xftdraw, &window->theme->bar_fg, window->bb->mode, 0, 0); recalc_text_size(window); window->redraw = 1; } @@ -545,7 +539,7 @@ window_create(ledit_common *common, ledit_theme *theme, ledit_mode mode) { /* FIXME: FocusChangeMask? */ window->wattrs.event_mask = KeyPressMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask | - ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; + PointerMotionMask | ButtonPressMask | ButtonReleaseMask; window->xwin = XCreateWindow( common->dpy, DefaultRootWindow(common->dpy), 0, 0, window->w, window->h, 0, common->depth, @@ -567,8 +561,7 @@ window_create(ledit_common *common, ledit_theme *theme, ledit_mode mode) { window->fontmap = pango_xft_get_font_map(common->dpy, common->screen); window->context = pango_font_map_create_context(window->fontmap); - /* FIXME: theme font name */ - window->font = pango_font_description_from_string("Monospace"); + window->font = pango_font_description_from_string(theme->text_font); pango_font_description_set_size(window->font, theme->text_size * PANGO_SCALE); window->wm_delete_msg = XInternAtom(common->dpy, "WM_DELETE_WINDOW", False); @@ -577,7 +570,6 @@ window_create(ledit_common *common, ledit_theme *theme, ledit_mode mode) { window->common = common; window->theme = theme; - /* FIXME: theme font */ window->bb = ledit_malloc(sizeof(bottom_bar)); window->bb->mode = pango_layout_new(window->context); pango_layout_set_font_description(window->bb->mode, window->font); @@ -619,6 +611,7 @@ window_create(ledit_common *common, ledit_theme *theme, ledit_mode mode) { if (window->xtarget == None) window->xtarget = XA_STRING; + window->cursor_text = XCreateFontCursor(window->common->dpy, XC_xterm); /* ledit_clear_window(window); ledit_redraw_window(window); @@ -692,7 +685,7 @@ window_redraw(ledit_window *window) { window->common->dpy, window->drawable, window->gc, window->w - t->scrollbar_width, 0, t->scrollbar_width, window->text_h ); - XSetForeground(window->common->dpy, window->gc, t->text_fg.pixel); + XSetForeground(window->common->dpy, window->gc, t->scrollbar_fg.pixel); double scroll_h, scroll_y; get_scroll_pos_height(window, &scroll_y, &scroll_h); XFillRectangle( @@ -701,8 +694,7 @@ window_redraw(ledit_window *window) { t->scrollbar_width, (int)round(scroll_h) ); } - XSetForeground(window->common->dpy, window->gc, t->text_bg.pixel); - /* FIXME: allow different color for bar */ + XSetForeground(window->common->dpy, window->gc, t->bar_bg.pixel); XFillRectangle( window->common->dpy, window->drawable, window->gc, 0, window->text_h, @@ -716,7 +708,7 @@ window_redraw(ledit_window *window) { 0, window->text_h ); } else if (window->bottom_text_shown) { - XSetForeground(window->common->dpy, window->gc, t->text_fg.pixel); + XSetForeground(window->common->dpy, window->gc, t->bar_fg.pixel); /* move input method position to cursor and draw cursor */ PangoRectangle strong, weak; pango_layout_get_cursor_pos( @@ -1027,6 +1019,14 @@ window_register_resize(ledit_window *window, XEvent *event) { void window_register_motion(ledit_window *window, XEvent *event) { + /* cursor should always change, even if time has not elapsed */ + int x = event->xmotion.x; + int y = event->xmotion.y; + /* FIXME: avoid these calls if nothing has changed */ + if (x < window->text_w && y < window->text_h) + XDefineCursor(window->common->dpy, window->xwin, window->cursor_text); + else + XDefineCursor(window->common->dpy, window->xwin, None); window->last_motion_event = *event; window->last_motion_valid = 1; } @@ -1084,8 +1084,8 @@ window_drag_motion(ledit_window *window, XEvent *event) { if (window->scroll_dragging) { double scroll_h, scroll_y; get_scroll_pos_height(window, &scroll_y, &scroll_h); - scroll_y += event->xbutton.y - window->scroll_grab_handle; - window->scroll_grab_handle = event->xbutton.y; + scroll_y += event->xmotion.y - window->scroll_grab_handle; + window->scroll_grab_handle = event->xmotion.y; set_scroll_pos(window, scroll_y); window->redraw = 1; } else { diff --git a/window.h b/window.h @@ -53,6 +53,7 @@ typedef struct { bottom_bar *bb; /* encapsulates the text at the bottom */ int redraw; /* whether something has changed and the window has to be redrawn */ ledit_mode mode; /* mode of the view - a bit ugly to duplicate this here... */ + Cursor cursor_text; /* text cursor shown when cursor is over text area */ /* stuff for filtering events so not too many have to be handled */ struct timespec last_scroll;