tAdd Ctrl-f and Ctrl-b for scrolling whole screens at a time - ledit - Text edi… | |
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 1619b579fa72a45217ceeab062cd5dc6c9961a37 | |
parent bf406bf2c7ad5025890a061780823576b65a67d7 | |
Author: lumidify <[email protected]> | |
Date: Fri, 29 Oct 2021 21:03:27 +0200 | |
Add Ctrl-f and Ctrl-b for scrolling whole screens at a time | |
Diffstat: | |
M buffer.c | 33 +++++++++++++++++++++--------… | |
M buffer.h | 6 +++++- | |
M keys_basic.c | 74 +++++++++++++++++++++++++++++… | |
M keys_basic_config.h | 4 ++++ | |
M window.c | 2 ++ | |
5 files changed, 107 insertions(+), 12 deletions(-) | |
--- | |
diff --git a/buffer.c b/buffer.c | |
t@@ -1363,16 +1363,25 @@ ledit_buffer_resize_textview(ledit_buffer *buffer) { | |
} | |
ledit_window_set_scroll_max(buffer->window, buffer->total_height); | |
if (buffer->display_offset > 0 && | |
- buffer->display_offset + text_h >= buffer->total_height) { | |
- buffer->display_offset = buffer->total_height - text_h; | |
- if (buffer->display_offset < 0) | |
- buffer->display_offset = 0; | |
- ledit_window_set_scroll_pos(buffer->window, buffer->display_of… | |
+ buffer->display_offset + text_h > buffer->total_height) { | |
+ ledit_buffer_scroll(buffer, buffer->total_height - text_h); | |
} | |
} | |
void | |
-ledit_xy_to_line_byte(ledit_buffer *buffer, int x, int y, int *line_ret, int *… | |
+ledit_buffer_scroll(ledit_buffer *buffer, long new_offset) { | |
+ int text_w, text_h; | |
+ ledit_window_get_textview_size(buffer->window, &text_w, &text_h); | |
+ if (new_offset + text_h > buffer->total_height) | |
+ new_offset = buffer->total_height - text_h; | |
+ if (new_offset < 0) | |
+ new_offset = 0; | |
+ buffer->display_offset = new_offset; | |
+ ledit_window_set_scroll_pos(buffer->window, buffer->display_offset); | |
+} | |
+ | |
+void | |
+ledit_xy_to_line_byte(ledit_buffer *buffer, int x, int y, int snap_to_nearest,… | |
/* FIXME: store current line offset to speed this up */ | |
/* FIXME: use y_offset in lines */ | |
long h = 0; | |
t@@ -1386,9 +1395,11 @@ ledit_xy_to_line_byte(ledit_buffer *buffer, int x, int … | |
x * PANGO_SCALE, (int)(pos - h) * PANGO_SCALE, | |
&index, &trailing | |
); | |
- while (trailing > 0) { | |
- trailing--; | |
- index = ledit_line_next_utf8(line, index); | |
+ if (snap_to_nearest) { | |
+ while (trailing > 0) { | |
+ trailing--; | |
+ index = ledit_line_next_utf8(line, ind… | |
+ } | |
} | |
*line_ret = i; | |
*byte_ret = index; | |
t@@ -1509,7 +1520,7 @@ 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, &l, &b); | |
+ 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->cu… | |
t@@ -1528,7 +1539,7 @@ ledit_buffer_button_handler(void *data, XEvent *event) { | |
case MotionNotify: | |
if (buffer->selecting) { | |
y = y >= 0 ? y : 0; | |
- ledit_xy_to_line_byte(buffer, x, y, &l, &b); | |
+ ledit_xy_to_line_byte(buffer, x, y, 1, &l, &b); | |
ledit_buffer_set_selection(buffer, buffer->sel.line1, … | |
buffer->cur_line = l; | |
buffer->cur_index = b; | |
diff --git a/buffer.h b/buffer.h | |
t@@ -128,7 +128,10 @@ void ledit_buffer_insert_text_from_line( | |
); | |
void ledit_buffer_resize_width(ledit_buffer *buffer, int width); | |
-void ledit_xy_to_line_byte(ledit_buffer *buffer, int x, int y, int *line_ret, … | |
+/* x and y are in pixels, if snap_to_nearest is nonzero, the returned byte | |
+ is at the nearest grapheme boundary, if it is zero, the byte is always | |
+ the beginning of the grapheme under the position */ | |
+void ledit_xy_to_line_byte(ledit_buffer *buffer, int x, int y, int snap_to_nea… | |
void ledit_buffer_ensure_cursor_shown(ledit_buffer *buffer); | |
void ledit_buffer_scroll_handler(void *buffer, long pos); | |
void ledit_buffer_button_handler(void *data, XEvent *event); | |
t@@ -140,3 +143,4 @@ void ledit_buffer_set_mode(ledit_buffer *buffer, enum ledi… | |
void ledit_buffer_paste_clipboard(ledit_buffer *buffer); | |
void ledit_buffer_paste_primary(ledit_buffer *buffer); | |
void ledit_buffer_resize_textview(ledit_buffer *buffer); | |
+void ledit_buffer_scroll(ledit_buffer *buffer, long new_offset); | |
diff --git a/keys_basic.c b/keys_basic.c | |
t@@ -343,6 +343,79 @@ delete_selection(ledit_buffer *buffer) { | |
return 0; | |
} | |
+/* get the number of times a command should be repeated, or -1 if anything | |
+ invalid was on the stack - this is for commands that just take a repeat | |
+ count and nothin else (cursor movement keys are different because they | |
+ can use other elements on the key stack to, for instance, call a callback | |
+ as is done for deletion */ | |
+static int | |
+get_key_repeat(void) { | |
+ int num = 1; | |
+ 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; | |
+ e = pop_key_stack(); | |
+ } | |
+ if (e != NULL) { | |
+ /* the key was not a number, or there was another | |
+ element under it on the stack -> error */ | |
+ num = -1; | |
+ } | |
+ } | |
+ clear_key_stack(); | |
+ return num; | |
+} | |
+ | |
+/* movement is multiplied to the window height and added to the display offset | |
+ the cursor is moved to the top if movement is upwards, to the bottom otherw… | |
+static void | |
+move_screen(ledit_buffer *buffer, int movement) { | |
+ int w, h; | |
+ ledit_window_get_textview_size(buffer->window, &w, &h); | |
+ long total = movement * (long)h; | |
+ ledit_buffer_scroll(buffer, buffer->display_offset + total); | |
+ ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); | |
+ /* try to keep current x position of cursor */ | |
+ ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line); | |
+ int x, softline; | |
+ /* FIXME: properly document what uses PANGO_SCALE and what not */ | |
+ ledit_pos_to_x_softline(ll, buffer->cur_index, &x, &softline); | |
+ /* if movement is up, move cursor to top, else to bottom of current sc… | |
+ ledit_xy_to_line_byte( | |
+ buffer, x / PANGO_SCALE, movement < 0 ? 0 : h, 0, | |
+ &buffer->cur_line, &buffer->cur_index | |
+ ); | |
+ ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->c… | |
+} | |
+ | |
+static struct action | |
+screen_up(ledit_buffer *buffer, char *text, int len) { | |
+ (void)text; | |
+ (void)len; | |
+ int repeat = get_key_repeat(); | |
+ if (repeat >= 0) | |
+ move_screen(buffer, -repeat); | |
+ else | |
+ ledit_window_show_message(buffer->window, "Invalid key", -1); | |
+ discard_repetition_stack(); | |
+ return (struct action){ACTION_NONE, NULL}; | |
+} | |
+ | |
+static struct action | |
+screen_down(ledit_buffer *buffer, char *text, int len) { | |
+ (void)text; | |
+ (void)len; | |
+ int repeat = get_key_repeat(); | |
+ if (repeat >= 0) | |
+ move_screen(buffer, repeat); | |
+ else | |
+ ledit_window_show_message(buffer->window, "Invalid key", -1); | |
+ discard_repetition_stack(); | |
+ return (struct action){ACTION_NONE, NULL}; | |
+} | |
+ | |
static struct action | |
key_d(ledit_buffer *buffer, char *text, int len) { | |
(void)text; | |
t@@ -665,6 +738,7 @@ return_key(ledit_buffer *buffer, char *text, int len) { | |
return (struct action){ACTION_NONE, NULL}; | |
} | |
+/* FIXME: Is this illegal due to different licenses? */ | |
/* FIXME: Check earliest version of other used functions to get minimum pango … | |
for ledit as a whole */ | |
/* FIXME: This is just copied from the newer version of pango. It *seems* like | |
diff --git a/keys_basic_config.h b/keys_basic_config.h | |
t@@ -57,6 +57,8 @@ static struct action undo(ledit_buffer *buffer, char *text, … | |
static struct action redo(ledit_buffer *buffer, char *text, int len); | |
static struct action insert_mode_insert_text(ledit_buffer *buffer, char *text,… | |
static struct action repeat_command(ledit_buffer *buffer, char *text, int len); | |
+static struct action screen_up(ledit_buffer *buffer, char *text, int len); | |
+static struct action screen_down(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@@ -102,6 +104,8 @@ static struct key keys_en[] = { | |
{".", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &repeat_command}, /* FIXME: onl… | |
{"z", ControlMask, 0, INSERT, KEY_ANY, KEY_ANY, &undo}, | |
{"y", ControlMask, 0, INSERT, KEY_ANY, KEY_ANY, &redo}, | |
+ {"b", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &screen_up}, | |
+ {"f", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &screen_dow… | |
{"", 0, 0, INSERT, KEY_ANY, KEY_ANY, &insert_mode_insert_text} | |
}; | |
diff --git a/window.c b/window.c | |
t@@ -415,6 +415,8 @@ ledit_window_create(ledit_common *common, ledit_theme *the… | |
void | |
ledit_window_destroy(ledit_window *window) { | |
/* FIXME: cleanup everything else */ | |
+ /* FIXME: This doesn't seem to be correct - g_object_unref sometimes | |
+ causes segfault */ | |
pango_font_description_free(window->font); | |
g_object_unref(window->fontmap); | |
g_object_unref(window->context); |