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 b7dc5c71dceb3a26368fc7d027053378a5828463
parent 7f10c769894b662194bf2fd54bc159647e012bf9
Author: lumidify <nobody@lumidify.org>
Date:   Tue,  2 Nov 2021 11:05:18 +0100

Fix various issues with selection; fix escape key in normal mode

Diffstat:
D.buffer.c.swp | 0
D.keys_basic.c.swp | 0
Mbuffer.c | 57+++++++++++++++++++++++++++++++++------------------------
Mkeys_basic.c | 13+++++++++----
Mkeys_basic_config.h | 2+-
5 files changed, 43 insertions(+), 29 deletions(-)

diff --git a/.buffer.c.swp b/.buffer.c.swp Binary files differ. diff --git a/.keys_basic.c.swp b/.keys_basic.c.swp Binary files differ. diff --git a/buffer.c b/buffer.c @@ -13,6 +13,7 @@ #include <pango/pangoxft.h> #include <X11/extensions/Xdbe.h> +#include "pango-compat.h" #include "memory.h" #include "common.h" #include "txtbuf.h" @@ -1608,21 +1609,24 @@ ledit_buffer_set_selection(ledit_buffer *buffer, int line1, int byte1, int line2 ledit_buffer_wipe_line_cursor_attrs(buffer, i); } } - if (l1_new == l2_new) { - ledit_buffer_set_line_selection(buffer, l1_new, b1_new, b2_new); - } else { - ledit_line *ll1 = ledit_buffer_get_line(buffer, l1_new); - ledit_buffer_set_line_selection(buffer, l1_new, b1_new, ll1->len); - ledit_buffer_set_line_selection(buffer, l2_new, 0, b2_new); - /* FIXME: optimize this */ - for (int i = l1_new + 1; i < l2_new; i++) { - if (i <= buffer->sel.line1 || i >= buffer->sel.line2) { - ledit_line *llx = ledit_buffer_get_line(buffer, i); - ledit_buffer_set_line_selection(buffer, i, 0, llx->len); + if (l1_new >= 0 && l2_new >= 0) { + if (l1_new == l2_new) { + ledit_buffer_set_line_selection(buffer, l1_new, b1_new, b2_new); + } else { + ledit_line *ll1 = ledit_buffer_get_line(buffer, l1_new); + ledit_buffer_set_line_selection(buffer, l1_new, b1_new, ll1->len); + ledit_buffer_set_line_selection(buffer, l2_new, 0, b2_new); + /* FIXME: optimize this */ + for (int i = l1_new + 1; i < l2_new; i++) { + if (i <= buffer->sel.line1 || i >= buffer->sel.line2) { + ledit_line *llx = ledit_buffer_get_line(buffer, i); + ledit_buffer_set_line_selection(buffer, i, 0, llx->len); + } } } + if (l1_new != l2_new || b1_new != b2_new) + copy_selection_to_x_primary(buffer, l1_new, b1_new, l2_new, b2_new); } - copy_selection_to_x_primary(buffer, l1_new, b1_new, l2_new, b2_new); } buffer->sel.line1 = line1; buffer->sel.byte1 = byte1; @@ -1643,18 +1647,13 @@ ledit_buffer_button_handler(void *data, XEvent *event) { int y = event->xbutton.y; switch (event->type) { case ButtonPress: - ledit_xy_to_line_byte(buffer, x, y, 1, &l, &b); - ledit_buffer_set_selection(buffer, l, b, l, b); - if (buffer->common->mode == NORMAL) { - ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); - /* FIXME: only set mode after dragging/when something is selected? */ - /* -> return to old mode afterwards? */ - /* should change_mode_group even be called here? */ - ledit_buffer_set_mode(buffer, VISUAL); - } + ledit_xy_to_line_byte(buffer, x, y, 0, &l, &b); + buffer->selecting = 1; buffer->cur_line = l; buffer->cur_index = b; - buffer->selecting = 1; + ledit_buffer_set_selection(buffer, -1, -1, -1, -1); + if (buffer->common->mode == NORMAL) + ledit_buffer_set_line_cursor_attrs(buffer, l, b); break; case ButtonRelease: buffer->selecting = 0; @@ -1663,7 +1662,17 @@ ledit_buffer_button_handler(void *data, XEvent *event) { if (buffer->selecting) { y = y >= 0 ? y : 0; ledit_xy_to_line_byte(buffer, x, y, 1, &l, &b); - ledit_buffer_set_selection(buffer, buffer->sel.line1, buffer->sel.byte1, l, b); + if (buffer->sel.line1 < 0 || buffer->sel.byte1 < 0) { + ledit_buffer_set_selection(buffer, l, b, l, b); + } else { + ledit_buffer_set_selection(buffer, buffer->sel.line1, buffer->sel.byte1, l, b); + } + if (buffer->common->mode == NORMAL) { + ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); + /* FIXME: return to old mode afterwards? */ + /* should change_mode_group even be called here? */ + ledit_buffer_set_mode(buffer, VISUAL); + } buffer->cur_line = l; buffer->cur_index = b; } @@ -1733,7 +1742,7 @@ ledit_buffer_redraw(ledit_buffer *buffer) { int box_x = strong.x / PANGO_SCALE; int box_w = 10; /* determine where the box should be drawn */ - PangoDirection dir = PANGO_DIRECTION_RTL; + PangoDirection dir = PANGO_DIRECTION_LTR; int tmp_index = buffer->cur_index; if (buffer->cur_index >= cur_line->len) tmp_index = cur_line->len - 1; diff --git a/keys_basic.c b/keys_basic.c @@ -3,6 +3,10 @@ /* 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 */ +/* FIXME: some weird things still happen with selections staying as "ghosts" + and being deleted at some later time even though they're not shown anymore */ +/* FIXME: there seem to be some issues with undo, but I couldn't reproduce + them reliably yet */ #include <stdio.h> #include <stdlib.h> @@ -1164,7 +1168,7 @@ move_cursor_in_line_dir(ledit_buffer *buffer, int movement_dir, int allow_illega static void move_cursor_logically(ledit_buffer *buffer, int movement_dir, int allow_illegal_index) { - PangoDirection dir = PANGO_DIRECTION_RTL; + PangoDirection dir = PANGO_DIRECTION_LTR; int tmp_index = buffer->cur_index; ledit_line *cur_line = ledit_buffer_get_line(buffer, buffer->cur_line); if (buffer->cur_index >= cur_line->len) @@ -1188,16 +1192,15 @@ static struct action escape_key(ledit_buffer *buffer, char *text, int len) { (void)text; (void)len; - clear_key_stack(); /* just in case... */ + clear_key_stack(); if (buffer->common->mode == INSERT) finalize_repetition_stack(); if (buffer->common->mode == INSERT && (buffer->sel.line1 != buffer->sel.line2 || buffer->sel.byte1 != buffer->sel.byte2)) { ledit_buffer_set_mode(buffer, VISUAL); - } else { + } else if (buffer->common->mode != NORMAL) { ledit_buffer_set_mode(buffer, NORMAL); - clear_key_stack(); move_cursor_logically(buffer, -1, 0); if (buffer->sel.line1 != buffer->sel.line2) { int min = buffer->sel.line1 < buffer->sel.line2 ? buffer->sel.line1 : buffer->sel.line2; @@ -1206,6 +1209,8 @@ escape_key(ledit_buffer *buffer, char *text, int len) { ledit_buffer_wipe_line_cursor_attrs(buffer, i); } } + buffer->sel.line1 = buffer->sel.line2 = -1; + buffer->sel.byte1 = buffer->sel.byte2 = -1; /* FIXME: optimize this to avoid first wiping and then setting the attrs */ ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index); } diff --git a/keys_basic_config.h b/keys_basic_config.h @@ -79,7 +79,7 @@ static struct key keys_en[] = { {NULL, 0, XK_Down, VISUAL|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, VISUAL|INSERT, KEY_ANY, KEY_ANY, &escape_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},