URI: 
       tAdd buggy implementation of '$' - ledit - Text editor (WIP)
  HTML git clone git://lumidify.org/ledit.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit f12812ad75c528b59aaf96791c48e3940c9e888c
   DIR parent 67de119de536bb598da9aba39ecfdde09562a8d3
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Mon,  1 Nov 2021 21:29:42 +0100
       
       Add buggy implementation of '$'
       
       Diffstat:
         M buffer.c                            |      23 +++++++++++++++++------
         M keys_basic.c                        |      73 +++++++++++++++++++++++++++++--
         M keys_basic_config.h                 |       2 ++
       
       3 files changed, 88 insertions(+), 10 deletions(-)
       ---
   DIR diff --git a/buffer.c b/buffer.c
       t@@ -1723,12 +1723,23 @@ ledit_buffer_redraw(ledit_buffer *buffer) {
                /* FIXME: long, int, etc. */
                int cursor_y = strong.y / PANGO_SCALE + cur_line_y;
                if (cursor_displayed && cursor_y >= 0) {
       -                if (buffer->common->mode == NORMAL && buffer->cur_index == cur_line->len) {
       -                        XFillRectangle(
       -                            buffer->common->dpy, buffer->window->drawable, buffer->window->gc,
       -                            strong.x / PANGO_SCALE, cursor_y,
       -                            10, strong.height / PANGO_SCALE
       -                        );
       +                if (buffer->common->mode == NORMAL) {
       +                        /* FIXME: figure out if there's a better way to do this */
       +                        /* Seriously, which of the pango folks though it would be a good idea to
       +                           not highlight spaces at the end of soft lines? That is an utterly
       +                           horrible idea. Or am I just too stupid to use it properly? */
       +                        int x, sli;
       +                        pango_layout_index_to_line_x(cur_line->layout, buffer->cur_index, 0, &sli, &x);
       +                        PangoLayoutLine *sl = pango_layout_get_line_readonly(cur_line->layout, sli);
       +                        if (buffer->cur_index == cur_line->len ||
       +                            (cur_line->text[buffer->cur_index] == ' ' &&
       +                             buffer->cur_index == sl->start_index + sl->length - 1)) {
       +                                XFillRectangle(
       +                                    buffer->common->dpy, buffer->window->drawable, buffer->window->gc,
       +                                    strong.x / PANGO_SCALE, cursor_y,
       +                                    10, strong.height / PANGO_SCALE
       +                                );
       +                        }
                        } else if (buffer->common->mode == INSERT || buffer->common->mode == VISUAL) {
                                XDrawLine(
                                    buffer->common->dpy, buffer->window->drawable, buffer->window->gc,
   DIR diff --git a/keys_basic.c b/keys_basic.c
       t@@ -1,4 +1,8 @@
        /* FIXME: cursor isn't shown on spaces at end of softlines */
       +/* FIXME: selection is sometimes not reset when it is "clicked away" */
       +/* FIXME: use weak cursor */
       +/* FIXME: spaces at end of soft line are weird in bidi text
       +   -> space is hidden when e.g. ltr text left and rtl text on right is wrapped */
        #include <stdio.h>
        #include <stdlib.h>
        
       t@@ -101,6 +105,7 @@ static void get_new_line_softline(
            ledit_buffer *buffer, int cur_line, int cur_index,
            int movement, int *new_line_ret, int *new_softline_ret
        );
       +static void move_cursor_in_line_dir(ledit_buffer *buffer, int dir, int allow_illegal_index);
        static void move_cursor_logically(ledit_buffer *buffer, int movement_dir, int allow_illegal_index);
        static void change_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type);
        
       t@@ -371,8 +376,7 @@ get_key_repeat(void) {
                struct key_stack_elem *e = pop_key_stack();
                if (e != NULL) {
                        if (e->key & KEY_NUMBER) {
       -                        /* FIXME: why did I do this? */
       -                        num = e->count > 0 ? e->count : 0;
       +                        num = e->count > 0 ? e->count : 1;
                                e = pop_key_stack();
                        }
                        if (e != NULL) {
       t@@ -589,6 +593,7 @@ screen_down(ledit_buffer *buffer, char *text, int len) {
        }
        
        /* FIXME: clear selection on most commands */
       +/* FIXME: don't include escape when repeating change with '.'? */
        static struct action
        change(ledit_buffer *buffer, char *text, int len) {
                (void)text;
       t@@ -986,13 +991,52 @@ delete_key(ledit_buffer *buffer, char *text, int len) {
                return (struct action){ACTION_NONE, NULL};
        }
        
       +static struct action
       +move_to_eol(ledit_buffer *buffer, char *text, int len) {
       +        (void)text;
       +        (void)len;
       +        int num = 1;
       +        struct key_stack_elem *e = pop_key_stack();
       +        if (e != NULL) {
       +                if (e->key & KEY_NUMBER) {
       +                        num = e->count > 0 ? e->count : 1;
       +                        e = pop_key_stack();
       +                }
       +                if (e != NULL)
       +                        num *= (e->count > 0 ? e->count : 1);
       +        }
       +        ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line);
       +        int new_line, new_softline;
       +        get_new_line_softline(
       +            buffer, buffer->cur_line, buffer->cur_index, num - 1,
       +            &new_line, &new_softline
       +        );
       +        ledit_line *ll = ledit_buffer_get_line(buffer, new_line);
       +        PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, new_softline);
       +        int end_index = sl->start_index + sl->length;
       +        if (e != NULL && e->motion_cb != NULL) {
       +                e->motion_cb(buffer, new_line, end_index, KEY_MOTION_CHAR);
       +        } else {
       +                buffer->cur_line = new_line;
       +                buffer->cur_index = end_index;
       +                if (buffer->common->mode == VISUAL) {
       +                        ledit_buffer_set_selection(buffer, buffer->sel.line1, buffer->sel.byte1, new_line, end_index);
       +                } else {
       +                        /* FIXME: this is still kind of weird with mixed bidi text */
       +                        move_cursor_in_line_dir(buffer, -1, 0);
       +                }
       +        }
       +        ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
       +        return (struct action){ACTION_NONE, NULL};
       +}
       +
        static void
        move_cursor_left_right(ledit_buffer *buffer, int dir, int allow_illegal_index) {
                int num = 1;
                struct key_stack_elem *e = pop_key_stack();
                if (e != NULL) {
                        if (e->key & KEY_NUMBER) {
       -                        num = e->count > 0 ? e->count : 0;
       +                        num = e->count > 0 ? e->count : 1;
                                e = pop_key_stack();
                        }
                        if (e != NULL)
       t@@ -1150,6 +1194,27 @@ pango_layout_get_direction(PangoLayout *layout, int index) {
        #endif
        
        static void
       +move_cursor_in_line_dir(ledit_buffer *buffer, int movement_dir, int allow_illegal_index) {
       +        PangoDirection dir;
       +        int x, sli;
       +        ledit_line *cur_line = ledit_buffer_get_line(buffer, buffer->cur_line);
       +        pango_layout_index_to_line_x(cur_line->layout, buffer->cur_index, 0, &sli, &x);
       +        PangoLayoutLine *sl = pango_layout_get_line_readonly(cur_line->layout, sli);
       +        dir = sl->resolved_dir;
       +        if (dir == PANGO_DIRECTION_RTL || dir == PANGO_DIRECTION_WEAK_RTL) {
       +                if (movement_dir < 0)
       +                        move_cursor_left_right(buffer, 1, allow_illegal_index);
       +                else
       +                        move_cursor_left_right(buffer, -1, allow_illegal_index);
       +        } else {
       +                if (movement_dir < 0)
       +                        move_cursor_left_right(buffer, -1, allow_illegal_index);
       +                else
       +                        move_cursor_left_right(buffer, 1, allow_illegal_index);
       +        }
       +}
       +
       +static void
        move_cursor_logically(ledit_buffer *buffer, int movement_dir, int allow_illegal_index) {
                PangoDirection dir = PANGO_DIRECTION_RTL;
                int tmp_index = buffer->cur_index;
       t@@ -1219,7 +1284,7 @@ move_cursor_up_down(ledit_buffer *buffer, int dir) {
                struct key_stack_elem *e = pop_key_stack();
                if (e != NULL) {
                        if (e->key & KEY_NUMBER) {
       -                        num = e->count > 0 ? e->count : 0;
       +                        num = e->count > 0 ? e->count : 1;
                                e = pop_key_stack();
                        }
                        if (e != NULL)
   DIR diff --git a/keys_basic_config.h b/keys_basic_config.h
       t@@ -67,6 +67,7 @@ static struct action move_to_line(ledit_buffer *buffer, char *text, int len);
        static struct action paste_normal(ledit_buffer *buffer, char *text, int len);
        static struct action paste_normal_backwards(ledit_buffer *buffer, char *text, int len);
        static struct action change(ledit_buffer *buffer, char *text, int len);
       +static struct action move_to_eol(ledit_buffer *buffer, char *text, int len);
        
        /* FIXME: maybe sort these and use binary search
           -> but that would mess with the catch-all keys */
       t@@ -124,6 +125,7 @@ static struct key keys_en[] = {
                {"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},
                {"G",  0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &move_to_line},
                {"p",  0, 0, NORMAL, KEY_ANY, KEY_ANY, &paste_normal},
                {"P",  0, 0, NORMAL, KEY_ANY, KEY_ANY, &paste_normal_backwards},