Introduction
Introduction Statistics Contact Development Disclaimer Help
tSomewhat properly implement substitution - 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 0498ed82f507017d8a5c6d83da08c66b2520bf95
parent 3572b3d7dd300642a94067f72f30fc83c8651e39
Author: lumidify <[email protected]>
Date: Thu, 9 Dec 2021 17:34:35 +0100
Somewhat properly implement substitution
Diffstat:
M buffer.c | 29 +++++++++++++++++++++++++++++
M buffer.h | 11 ++++++++++-
M keys_basic.c | 61 ++++++++++++++++++-----------…
M keys_command.c | 242 ++++++++++++++++++++++-------…
M view.c | 8 ++++++--
5 files changed, 251 insertions(+), 100 deletions(-)
---
diff --git a/buffer.c b/buffer.c
t@@ -202,6 +202,35 @@ buffer_insert_mark(ledit_buffer *buffer, char *mark, size…
marklist->len++;
}
+/* FIXME: check that byte is actually at grapheme boundary
+ (difficult because that can't currently be done by the buffer) */
+int
+buffer_get_mark(ledit_buffer *buffer, char *mark, size_t len, size_t *line_ret…
+ ledit_buffer_marklist *marklist = buffer->marklist;
+ int ret = 1;
+ for (size_t i = 0; i < marklist->len; i++) {
+ if (!strncmp(mark, marklist->marks[i].text, len)) {
+ ledit_line *ll;
+ ledit_buffer_mark *m = &marklist->marks[i];
+ if (m->line >= buffer->lines_num) {
+ *line_ret = buffer->lines_num - 1;
+ ll = buffer_get_line(buffer, *line_ret);
+ *byte_ret = ll->len;
+ } else {
+ *line_ret = m->line;
+ ll = buffer_get_line(buffer, m->line);
+ if (m->byte >= ll->len)
+ *byte_ret = ll->len;
+ else
+ *byte_ret = m->byte;
+ }
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
static ledit_buffer_marklist *
marklist_create(void) {
ledit_buffer_marklist *marklist = ledit_malloc(sizeof(ledit_buffer_mar…
diff --git a/buffer.h b/buffer.h
t@@ -184,11 +184,20 @@ size_t line_prev_utf8(ledit_line *line, size_t index);
size_t line_byte_to_char(ledit_line *line, size_t byte);
/*
- * Insert a mark with key 'mark' at line 'line' and byte 'byte'.
+ * Insert a mark with key 'mark' (which has byte length 'len') at line 'line' …
*/
void buffer_insert_mark(ledit_buffer *buffer, char *mark, size_t len, size_t l…
/*
+ * Retrieve mark 'mark' (with byte length 'len').
+ * The line and byte of the mark are written to 'line_ret' and 'byte_ret'.
+ * These returned positions are always valid positions in the buffer, even
+ * if the buffer has been modified and the mark points to an invalid location.
+ * Returns 0 if the mark was found, 1 otherwise.
+ */
+int buffer_get_mark(ledit_buffer *buffer, char *mark, size_t len, size_t *line…
+
+/*
* Perform one undo step.
* 'mode' should be the current mode of the calling view.
* 'cur_line' and 'cur_byte' are filled with the new line and cursor
diff --git a/keys_basic.c b/keys_basic.c
t@@ -121,6 +121,15 @@ static void change_cb(ledit_view *view, size_t line, size…
static void push_undo_empty_insert(ledit_view *view, size_t line, size_t index…
static void move_half_screen(ledit_view *view, int movement);
+static struct action
+view_locked_error(ledit_view *view) {
+ window_show_message(view->window, view->lock_text, -1);
+ return (struct action){ACTION_NONE, NULL};
+}
+
+#define CHECK_VIEW_LOCKED(view) if (view->lock_text) return view_locked_error(…
+#define CHECK_VIEW_LOCKED_NORETURN(view) if (view->lock_text) (void)view_locke…
+
/* FIXME: move to common */
static void
swap_sz(size_t *a, size_t *b) {
t@@ -478,6 +487,7 @@ static struct action
delete_chars_forwards(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
int num = get_key_repeat();
if (num == -1) {
window_show_message(view->window, "Invalid key", -1);
t@@ -505,6 +515,7 @@ static struct action
delete_chars_backwards(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
int num = get_key_repeat();
if (num == -1) {
window_show_message(view->window, "Invalid key", -1);
t@@ -543,6 +554,7 @@ push_undo_empty_insert(ledit_view *view, size_t line, size…
static struct action
append_line_above(ledit_view *view, char *text, size_t len) {
+ CHECK_VIEW_LOCKED(view);
size_t start, end;
/* do this here already so the mode group is the same for the newline …
enter_insert(view, text, len);
t@@ -558,6 +570,7 @@ append_line_above(ledit_view *view, char *text, size_t len…
static struct action
append_line_below(ledit_view *view, char *text, size_t len) {
+ CHECK_VIEW_LOCKED(view);
size_t start, end;
enter_insert(view, text, len);
view_get_pos_softline_bounds(view, view->cur_line, view->cur_index, &s…
t@@ -572,6 +585,7 @@ append_line_below(ledit_view *view, char *text, size_t len…
static struct action
append_after_cursor(ledit_view *view, char *text, size_t len) {
+ CHECK_VIEW_LOCKED(view);
enter_insert(view, text, len);
/* make cursor jump back to original position on undo */
push_undo_empty_insert(view, view->cur_line, view->cur_index, 1);
t@@ -583,6 +597,7 @@ append_after_cursor(ledit_view *view, char *text, size_t l…
static struct action
append_after_eol(ledit_view *view, char *text, size_t len) {
+ CHECK_VIEW_LOCKED(view);
size_t start, end;
enter_insert(view, text, len);
view_get_pos_softline_bounds(view, view->cur_line, view->cur_index, &s…
t@@ -833,6 +848,7 @@ static struct action
delete_to_eol(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
if (!key_stack_empty())
return err_invalid_key(view);
size_t start, end;
t@@ -859,6 +875,7 @@ static struct action
change_to_eol(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
if (!key_stack_empty())
return err_invalid_key(view);
view_set_mode(view, INSERT);
t@@ -885,6 +902,7 @@ static struct action
change(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
motion_callback cb = NULL;
int num = get_key_repeat_and_motion_cb(&cb);
if (num == -1)
t@@ -921,6 +939,7 @@ change(ledit_view *view, char *text, size_t len) {
static void
change_cb(ledit_view *view, size_t line, size_t char_pos, enum key_type type) {
+ CHECK_VIEW_LOCKED_NORETURN(view);
/* set mode first so the deletion is included in the undo group */
view_set_mode(view, INSERT);
int line_based = type == KEY_MOTION_LINE ? 1 : 0;
t@@ -1066,6 +1085,7 @@ static struct action
delete(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
motion_callback cb = NULL;
int num = get_key_repeat_and_motion_cb(&cb);
if (num == -1)
t@@ -1104,6 +1124,7 @@ delete(ledit_view *view, char *text, size_t len) {
/* FIXME: should this get number of lines to remove or actual end line? */
static void
delete_cb(ledit_view *view, size_t line, size_t char_pos, enum key_type type) {
+ CHECK_VIEW_LOCKED_NORETURN(view);
view_wipe_line_cursor_attrs(view, view->cur_line);
int line_based = type == KEY_MOTION_LINE ? 1 : 0;
delete_range(
t@@ -1124,6 +1145,7 @@ static struct action
paste_normal(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
if (!paste_buffer) {
window_show_message(view->window, "Nothing to paste", -1);
discard_repetition_stack();
t@@ -1182,6 +1204,7 @@ static struct action
paste_normal_backwards(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
if (!paste_buffer) {
window_show_message(view->window, "Nothing to paste", -1);
discard_repetition_stack();
t@@ -1347,6 +1370,7 @@ static struct action
backspace(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
/* FIXME: don't copy to paste buffer on del_sel here; delete entire gr…
if (delete_selection(view)) {
/* NOP */
t@@ -1367,6 +1391,7 @@ static struct action
delete_key(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
ledit_line *cur_line = buffer_get_line(view->buffer, view->cur_line);
if (delete_selection(view)) {
/* NOP */
t@@ -1387,6 +1412,7 @@ static struct action
move_to_eol(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
motion_callback cb;
int num = get_key_repeat_and_motion_cb(&cb);
if (num == -1)
t@@ -1544,6 +1570,7 @@ static struct action
return_key(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
int start_group = 1;
if (delete_selection(view))
start_group = 0;
t@@ -1591,6 +1618,7 @@ static struct action
enter_insert(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
if (view->mode == NORMAL)
view_wipe_line_cursor_attrs(view, view->cur_line);
view_set_mode(view, INSERT);
t@@ -1663,6 +1691,7 @@ static struct action
join_lines(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
int num = get_key_repeat();
if (num == -1)
return err_invalid_key(view);
t@@ -1696,6 +1725,7 @@ join_lines(ledit_view *view, char *text, size_t len) {
static struct action
insert_at_beginning(ledit_view *view, char *text, size_t len) {
+ CHECK_VIEW_LOCKED(view);
if (!key_stack_empty())
return err_invalid_key(view);
enter_insert(view, text, len);
t@@ -1854,39 +1884,15 @@ mark_line_cb(ledit_view *view, char *text, size_t len)…
return (struct action){ACTION_NONE, NULL};
}
-/* FIXME: move part of this to buffer.c */
-/* FIXME: check that byte is actually at grapheme boundary */
static struct action
jump_to_mark_cb(ledit_view *view, char *text, size_t len) {
grab_char_cb = NULL;
- ledit_buffer_marklist *marklist = view->buffer->marklist;
motion_callback cb;
int num = get_key_repeat_and_motion_cb(&cb);
if (num > 0)
return err_invalid_key(view);
size_t line = 0, index = 0;
- int mark_found = 0;
- for (size_t i = 0; i < marklist->len; i++) {
- if (!strncmp(text, marklist->marks[i].text, len)) {
- ledit_line *ll;
- ledit_buffer_mark *m = &marklist->marks[i];
- if (m->line >= view->lines_num) {
- line = view->lines_num - 1;
- ll = buffer_get_line(view->buffer, line);
- index = ll->len;
- } else {
- line = m->line;
- ll = buffer_get_line(view->buffer, m->line);
- if (m->byte >= ll->len)
- index = ll->len;
- else
- index = m->byte;
- }
- mark_found = 1;
- break;
- }
- }
- if (!mark_found)
+ if (buffer_get_mark(view->buffer, text, len, &line, &index))
return err_invalid_key(view);
if (view->mode == VISUAL) {
view_set_selection(
t@@ -1969,6 +1975,7 @@ static struct action
undo(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
view_wipe_selection(view);
view_wipe_line_cursor_attrs(view, view->cur_line);
view_undo(view);
t@@ -1981,6 +1988,7 @@ static struct action
redo(ledit_view *view, char *text, size_t len) {
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
view_wipe_selection(view);
view_wipe_line_cursor_attrs(view, view->cur_line);
view_redo(view);
t@@ -1991,6 +1999,7 @@ redo(ledit_view *view, char *text, size_t len) {
static struct action
insert_mode_insert_text(ledit_view *view, char *text, size_t len) {
+ CHECK_VIEW_LOCKED(view);
/* FIXME: set cur_index when deleting selection */
delete_selection(view);
insert_text(view, view->cur_line, view->cur_index, text, len, 0, 0, 0,…
t@@ -2149,6 +2158,7 @@ GEN_MOVE_TO_CHAR(
static struct action
replace_cb(ledit_view *view, char *text, size_t len) {
+ CHECK_VIEW_LOCKED(view);
size_t start_index = view->cur_index;
/* FIXME: replace with (key repeat) * text instead of just text */
size_t end_index = view_next_cursor_pos(
t@@ -2176,6 +2186,7 @@ replace(ledit_view *view, char *text, size_t len) {
(void)view;
(void)text;
(void)len;
+ CHECK_VIEW_LOCKED(view);
int num = get_key_repeat();
if (num != 0)
return err_invalid_key(view);
diff --git a/keys_command.c b/keys_command.c
t@@ -27,9 +27,20 @@
#include "keys_command.h"
#include "keys_command_config.h"
-static char *last_search = NULL;
-static char *last_replacement = NULL;
-static int last_replacement_global = 0;
+static struct {
+ char *search;
+ char *replace;
+ size_t slen;
+ size_t rlen;
+ size_t line;
+ size_t byte;
+ size_t old_line;
+ size_t old_byte;
+ size_t max_line;
+ int global;
+ int num;
+ int start_group; /* only set for the first replacement */
+} sub_state = {NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
static int
view_locked_error(ledit_view *view) {
t@@ -37,7 +48,7 @@ view_locked_error(ledit_view *view) {
return 0;
}
-#define CHECK_VIEW_LOCKED if (view->lock_text) return view_locked_error(view)
+#define CHECK_VIEW_LOCKED(view) if (view->lock_text) return view_locked_error(…
/* FIXME: history for search and commands */
t@@ -110,13 +121,114 @@ handle_write_quit(ledit_view *view, char *cmd, size_t l…
return 0;
}
+static void
+show_num_substituted(ledit_view *view) {
+ char buf[30];
+ if (snprintf(buf, sizeof(buf), "%d substitution(s)", sub_state.num) < …
+ window_show_message(view->window, "This message is a bug, tell…
+ } else {
+ window_show_message(view->window, buf, -1);
+ }
+}
+
+/* returns 1 when match was found, 0 otherwise */
+static int
+next_replace_pos(
+ ledit_view *view,
+ size_t line, size_t byte, size_t max_line,
+ size_t *line_ret, size_t *byte_ret) {
+ size_t start_index = byte;
+ for (size_t i = line; i <= max_line; i++) {
+ ledit_line *ll = buffer_get_line(view->buffer, i);
+ buffer_normalize_line(ll);
+ char *pos = strstr(ll->text + start_index, sub_state.search);
+ if (pos != NULL) {
+ *line_ret = i;
+ *byte_ret = (size_t)(pos - ll->text);
+ return 1;
+ }
+ start_index = 0;
+ }
+ return 0;
+}
+
+/* returns whether keys should continue being captured */
+static int
+move_to_next_substitution(ledit_view *view) {
+ view_wipe_line_cursor_attrs(view, view->cur_line);
+ if (!next_replace_pos(view, sub_state.line, sub_state.byte, sub_state.…
+ view->cur_line = sub_state.line;
+ view->cur_index = sub_state.byte;
+ view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind…
+ window_show_message(view->window, "No more matches", -1);
+ buffer_unlock_all_views(view->buffer);
+ return 0;
+ }
+ view->cur_line = sub_state.line;
+ view->cur_index = sub_state.byte;
+ view_set_line_cursor_attrs(view, view->cur_line, view->cur_index);
+ window_show_message(view->window, "Replace? (y/Y/n/N)", -1);
+ view_ensure_cursor_shown(view);
+ return 1;
+}
+
+/* WARNING: sub_state must be set properly! */
+static void
+substitute_single(ledit_view *view) {
+ ledit_range cur_range;
+ cur_range.line1 = sub_state.old_line;
+ cur_range.byte1 = sub_state.old_byte;
+ cur_range.line2 = sub_state.line;
+ cur_range.byte2 = sub_state.byte;
+ buffer_delete_with_undo_base(
+ view->buffer, cur_range,
+ sub_state.start_group, view->mode,
+ sub_state.line, sub_state.byte,
+ sub_state.line, sub_state.byte + sub_state.slen, NULL
+ );
+ sub_state.start_group = 0;
+ cur_range.line1 = sub_state.line;
+ cur_range.byte1 = sub_state.byte;
+ buffer_insert_with_undo_base(
+ view->buffer, cur_range, 0, 0, view->mode,
+ sub_state.line, sub_state.byte,
+ sub_state.replace, sub_state.rlen,
+ NULL, NULL
+ );
+ sub_state.num++;
+}
+
+static void
+substitute_all_remaining(ledit_view *view) {
+ view_wipe_line_cursor_attrs(view, view->cur_line);
+ size_t min_line = SIZE_MAX;
+ while (next_replace_pos(view, sub_state.line, sub_state.byte, sub_stat…
+ if (sub_state.line < min_line)
+ min_line = sub_state.line;
+ substitute_single(view);
+ view->cur_line = sub_state.old_line = sub_state.line;
+ view->cur_index = sub_state.old_byte = sub_state.byte;
+ if (!sub_state.global) {
+ sub_state.line++;
+ sub_state.byte = 0;
+ } else {
+ sub_state.byte += sub_state.rlen;
+ }
+ }
+ if (min_line < view->lines_num)
+ buffer_recalc_all_views_from_line(view->buffer, min_line);
+ /* FIXME: show number replaced */
+ /* this doesn't need to be added to the undo stack since it's called o…
+ view->cur_index = view_get_legal_normal_pos(view, view->cur_line, view…
+ view_set_line_cursor_attrs(view, view->cur_line, view->cur_index);
+ view_ensure_cursor_shown(view);
+ show_num_substituted(view);
+ buffer_unlock_all_views(view->buffer);
+}
+
static int
handle_substitute(ledit_view *view, char *cmd, size_t l1, size_t l2) {
- (void)view;
- (void)cmd;
- (void)l1;
- (void)l2;
- CHECK_VIEW_LOCKED;
+ CHECK_VIEW_LOCKED(view);
cmd++; /* remove 's' at beginning */
size_t len = strlen(cmd);
if (len == 0) goto error;
t@@ -146,64 +258,27 @@ handle_substitute(ledit_view *view, char *cmd, size_t l1…
}
c++;
}
- free(last_search);
- free(last_replacement);
- last_search = ledit_strdup(cmd);
- last_replacement = ledit_strdup(next);
- last_replacement_global = global;
+ free(sub_state.search);
+ free(sub_state.replace);
+ sub_state.search = ledit_strdup(cmd);
+ sub_state.replace = ledit_strdup(next);
+ sub_state.slen = strlen(sub_state.search);
+ sub_state.rlen = strlen(sub_state.replace);
+ sub_state.global = global;
+ sub_state.line = l1;
+ sub_state.byte = 0;
+ sub_state.old_line = view->cur_line;
+ sub_state.old_byte = view->cur_index;
+ sub_state.max_line = l2;
+ sub_state.num = 0;
+ sub_state.start_group = 1;
if (confirm) {
buffer_lock_all_views_except(view->buffer, view, "Ongoing subs…
- buffer_unlock_all_views(view->buffer);
+ view->cur_command_type = CMD_SUBSTITUTE;
+ return move_to_next_substitution(view);
} else {
- int num = 0;
- int start_undo_group = 1;
- size_t slen = strlen(last_search);
- size_t rlen = strlen(last_replacement);
- txtbuf *buf = txtbuf_new(); /* FIXME: don't allocate new every…
- view_wipe_line_cursor_attrs(view, view->cur_line);
- size_t min_line = SIZE_MAX;
- for (size_t i = l1 - 1; i < l2; i++) {
- ledit_line *ll = buffer_get_line(view->buffer, i);
- buffer_normalize_line(ll);
- char *pos = strstr(ll->text, last_search);
- if (pos != NULL && i < min_line)
- min_line = i;
- while (pos != NULL) {
- size_t index = (size_t)(pos - ll->text);
- ledit_range cur_range;
- cur_range.line1 = view->cur_line;
- cur_range.byte1 = view->cur_line;
- cur_range.line2 = i;
- cur_range.byte2 = index;
- buffer_delete_with_undo_base(
- view->buffer, cur_range,
- start_undo_group, view->mode,
- i, index, i, index + slen, NULL
- );
- view->cur_line = i;
- view->cur_index = index;
- start_undo_group = 0;
- cur_range.line1 = i;
- cur_range.byte1 = index;
- buffer_insert_with_undo_base(
- view->buffer, cur_range, 0, 0, view->mode,
- i, index, last_replacement, rlen,
- NULL, NULL
- );
- num++;
- if (!global) break;
- buffer_normalize_line(ll); /* just in case */
- pos = strstr(ll->text + index + rlen, last_sea…
- }
- }
- buffer_recalc_all_views_from_line(view->buffer, min_line);
- /* FIXME: show number replaced */
- /* this doesn't need to be added to the undo stack since it's …
- view->cur_index = view_get_legal_normal_pos(view, view->cur_li…
- view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind…
- view_ensure_cursor_shown(view);
- txtbuf_destroy(buf);
+ substitute_all_remaining(view);
}
return 0;
error:
t@@ -312,8 +387,9 @@ parse_range(ledit_view *view, char *cmd, size_t len, char …
if ((*l1_valid || *l2_valid) && (l1 == 0 || l2 == 0 || l1 > view->line…
return 1; /* FIXME: better error messages */
*cmd_ret = c;
- *line1_ret = l1;
- *line2_ret = l2;
+ /* ranges are given 1-indexed by user */
+ *line1_ret = l1 - 1;
+ *line2_ret = l2 - 1;
return 0;
}
t@@ -328,7 +404,9 @@ handle_cmd(ledit_view *view, char *cmd, size_t len) {
if (parse_range(view, cmd, len, &c, &l1, &l2, &l1_valid, &l2_valid))
return 0;
int range_given = l1_valid && l2_valid;
- /* FIXME: mandatory range */
+ if (!range_given) {
+ l1 = l2 = view->cur_line;
+ }
for (size_t i = 0; i < LENGTH(cmds); i++) {
if (!strncmp(cmds[i].cmd, c, strlen(cmds[i].cmd)) &&
(!range_given || cmds[i].type == CMD_OPTIONAL_RANGE)) {
t@@ -340,33 +418,53 @@ handle_cmd(ledit_view *view, char *cmd, size_t len) {
static int
substitute_yes(ledit_view *view, char *key_text, size_t len) {
- (void)view;
(void)key_text;
(void)len;
- return 1;
+ substitute_single(view);
+ buffer_recalc_line(view->buffer, sub_state.line);
+ if (!sub_state.global) {
+ sub_state.line++;
+ sub_state.byte = 0;
+ } else {
+ sub_state.byte += sub_state.rlen;
+ }
+ int ret = move_to_next_substitution(view);
+ if (ret)
+ show_num_substituted(view);
+ return ret;
}
static int
substitute_yes_all(ledit_view *view, char *key_text, size_t len) {
- (void)view;
(void)key_text;
(void)len;
+ substitute_all_remaining(view);
+ show_num_substituted(view);
return 0;
}
static int
substitute_no(ledit_view *view, char *key_text, size_t len) {
- (void)view;
(void)key_text;
(void)len;
- return 1;
+ if (!sub_state.global) {
+ sub_state.line++;
+ sub_state.byte = 0;
+ } else {
+ sub_state.byte += sub_state.slen;
+ }
+ int ret = move_to_next_substitution(view);
+ if (ret)
+ show_num_substituted(view);
+ return ret;
}
static int
substitute_no_all(ledit_view *view, char *key_text, size_t len) {
- (void)view;
(void)key_text;
(void)len;
+ buffer_unlock_all_views(view->buffer);
+ show_num_substituted(view);
return 0;
}
diff --git a/view.c b/view.c
t@@ -627,8 +627,8 @@ line_prev_word(
PangoLayout *layout = get_pango_layout(view, line);
const PangoLogAttr *attrs =
pango_layout_get_log_attrs_readonly(layout, &nattrs);
- if (char_index > (size_t)nattrs)
- return -1;
+ if (char_index > (size_t)nattrs - 1)
+ char_index = (size_t)nattrs - 1;
/* this is a bit weird because size_t can't be negative */
for (size_t i = char_index; i > 0; i--) {
if (attrs[i-1].is_word_start) {
t@@ -655,6 +655,8 @@ line_prev_bigword(
size_t next_cursorb = byte;
size_t next_cursorc = char_index;
int found_word = 0;
+ if (char_index > (size_t)nattrs - 1)
+ char_index = (size_t)nattrs - 1;
/* this is a bit weird because size_t can't be negative */
for (size_t i = char_index; i > 0; i--) {
if (!found_word && !attrs[i-1].is_white) {
t@@ -820,6 +822,7 @@ view_next_##name( …
cur_line < view->lines_num - 1) { …
cur_line++; …
cur_byte = 0; …
+ cur_char = 0; …
wrapped_line = 1; …
} …
if (last_ret == -1 && cur_line == view->lines_num - 1) …
t@@ -854,6 +857,7 @@ view_prev_##name( …
cur_line--; …
ll = buffer_get_line(view->buffer, cur_line); …
cur_byte = ll->len; …
+ cur_char = ll->len; …
} …
if (last_ret == -1 && cur_line == 0) …
break; …
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.