tFix crash and other misc. bugs - 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 155a081f559a9ecfddd8b086c7d91187c2af4bc2 | |
parent 81ddea61d765938b662b3456b3fe80369cfbc138 | |
Author: lumidify <[email protected]> | |
Date: Wed, 25 Oct 2023 13:42:10 +0200 | |
Fix crash and other misc. bugs | |
Diffstat: | |
M buffer.c | 14 ++++++++++---- | |
M keys_basic.c | 8 ++++---- | |
M leditrc.5 | 6 +++--- | |
M memory.c | 4 +++- | |
M view.c | 30 ++++++++++++++---------------- | |
5 files changed, 34 insertions(+), 28 deletions(-) | |
--- | |
diff --git a/buffer.c b/buffer.c | |
t@@ -574,8 +574,8 @@ buffer_insert_text_base(ledit_buffer *buffer, size_t line_… | |
ledit_assert(index <= line->len); | |
/* \0 is not included in line->len */ | |
resize_and_move_text_gap(line, add_sz3(line->len, len, 1), index); | |
- /* the gap is now located at 'index' and least large enough to hold th… | |
- memcpy(line->text + index, text, len); | |
+ /* the gap is now located at 'index' and at least large enough to hold… | |
+ memmove(line->text + index, text, len); | |
line->gap += len; | |
line->len += len; | |
for (size_t i = 0; i < buffer->views_num; i++) { | |
t@@ -920,8 +920,10 @@ buffer_delete_line_section_base(ledit_buffer *buffer, siz… | |
(void)add_sz(start, length); /* just check that no overflow */ | |
ledit_assert(start + length <= l->len); | |
if (start <= l->gap && start + length >= l->gap) { | |
+ /* range includes gap */ | |
l->gap = start; | |
- } else if (start < l->gap && start + length < l->gap) { | |
+ } else if (start < l->gap && start + length <= l->gap) { | |
+ /* entire range is before gap */ | |
memmove( | |
l->text + l->cap - l->len + start + length, | |
l->text + start + length, | |
t@@ -929,11 +931,15 @@ buffer_delete_line_section_base(ledit_buffer *buffer, si… | |
); | |
l->gap = start; | |
} else { | |
+ /* entire range is after gap */ | |
+ /* move piece between end of gap and | |
+ start of range to beginning of gap */ | |
memmove( | |
l->text + l->gap, | |
l->text + l->gap + l->cap - l->len, | |
- start - l->gap - l->cap + l->len | |
+ start - l->gap | |
); | |
+ l->gap += start - l->gap; | |
} | |
l->len -= length; | |
/* possibly decrease size of line */ | |
diff --git a/keys_basic.c b/keys_basic.c | |
t@@ -1930,18 +1930,18 @@ move_cursor_up_down(ledit_view *view, int dir) { | |
view_get_softline_bounds(view, new_line, new_softline, &start,… | |
cb(view, new_line, start, KEY_MOTION_LINE); | |
} else { | |
- int lineno, x; | |
+ int lineno, x, diff = 0, old_line = view->cur_line; | |
view_pos_to_x_softline(view, view->cur_line, view->cur_index, … | |
view->cur_index = view_x_softline_to_pos(view, new_line, x, ne… | |
if (view->cur_line != new_line) | |
- view_wipe_line_cursor_attrs(view, view->cur_line); | |
+ diff = 1; | |
view->cur_line = new_line; | |
if (view->mode == VISUAL) { | |
view_set_selection(view, view->sel.line1, view->sel.by… | |
- } else if (view->mode == INSERT && view->sel_valid) { | |
- view_wipe_selection(view); | |
} else if (view->mode == NORMAL) { | |
+ if (diff) | |
+ view_wipe_line_cursor_attrs(view, old_line); | |
view_set_line_cursor_attrs(view, view->cur_line, view-… | |
} | |
view->redraw = 1; | |
diff --git a/leditrc.5 b/leditrc.5 | |
t@@ -1,4 +1,4 @@ | |
-.Dd October 5, 2023 | |
+.Dd October 6, 2023 | |
.Dt LEDITRC 5 | |
.Os | |
.Sh NAME | |
t@@ -68,7 +68,7 @@ Yes, this is inconsistent and confusing. | |
As defined by Unicode (UAX #29). | |
A grapheme may be composed of multiple Unicode characters. | |
The cursor is only allowed to be at valid grapheme boundaries, but | |
-some operations work with characters, while other work with graphemes. | |
+some operations work with characters, while others work with graphemes. | |
.It Ar paste buffer | |
When text is deleted or explicitly copied (yanked), it is written to the | |
paste buffer so that it can be pasted later. | |
t@@ -82,7 +82,7 @@ A hardline is an actual line separated from the other lines … | |
character. | |
A softline is a displayed line, but might only be part of a | |
hardline if the text is wrapped. | |
-.Nm | |
+.Xr ledit 1 | |
can be in hardline or softline mode. | |
Some commands change their behavior depending on this mode, for instance | |
to move the cursor down a certain number of softlines instead of hardlines. | |
diff --git a/memory.c b/memory.c | |
t@@ -162,6 +162,7 @@ resize_and_move_gap( | |
size_t old_gap, size_t old_cap, size_t len, | |
size_t min_size, size_t index, | |
size_t *new_gap_ret, size_t *new_cap_ret) { | |
+ ledit_assert(array != NULL || (len == 0 && old_cap == 0)); | |
ledit_assert(index <= len); | |
ledit_assert(len <= old_cap); | |
ledit_assert(old_gap <= len); | |
t@@ -213,7 +214,8 @@ resize_and_move_gap( | |
/* otherwise, parts may be cut off */ | |
ledit_assert(min_size >= len); | |
/* FIXME: optimize this */ | |
- move_gap(array, elem_size, len, old_gap, old_cap, len, NULL); | |
+ if (array) | |
+ move_gap(array, elem_size, len, old_gap, old_cap, len,… | |
array = ledit_reallocarray(array, new_cap, elem_size); | |
move_gap(array, elem_size, index, len, new_cap, len, NULL); | |
} | |
diff --git a/view.c b/view.c | |
t@@ -198,6 +198,8 @@ resize_and_move_line_gap(ledit_view *view, size_t min_size… | |
a part, which may cause these notification functions to be called) */ | |
void | |
view_notify_insert_text(ledit_view *view, size_t line, size_t index, size_t le… | |
+ int sel_valid = view->sel_valid; | |
+ view_wipe_selection(view); | |
ledit_view_line *vl = view_get_line(view, line); | |
vl->text_dirty = 1; | |
if (line == view->cur_line && index < view->cur_index) { | |
t@@ -206,14 +208,14 @@ view_notify_insert_text(ledit_view *view, size_t line, s… | |
if (vl->cursor_index_valid) | |
view_set_line_cursor_attrs(view, line, view->cur_index… | |
} | |
- /* FIXME: maybe just wipe selection completely, or at least | |
- when in insert mode? */ | |
- if (view->sel_valid) | |
+ if (sel_valid) | |
view_set_selection(view, view->cur_line, view->cur_index, view… | |
} | |
void | |
view_notify_delete_text(ledit_view *view, size_t line, size_t index, size_t le… | |
+ int sel_valid = view->sel_valid; | |
+ view_wipe_selection(view); | |
ledit_view_line *vl = view_get_line(view, line); | |
vl->text_dirty = 1; | |
if (line == view->cur_line) { | |
t@@ -232,12 +234,14 @@ view_notify_delete_text(ledit_view *view, size_t line, s… | |
if (vl->cursor_index_valid) | |
view_set_line_cursor_attrs(view, line, view->cur_index… | |
} | |
- if (view->sel_valid) | |
+ if (sel_valid) | |
view_set_selection(view, view->cur_line, view->cur_index, view… | |
} | |
void | |
view_notify_append_line(ledit_view *view, size_t line) { | |
+ int sel_valid = view->sel_valid; | |
+ view_wipe_selection(view); | |
cache_invalidate_from_line( | |
view->cache, line + 1, view, | |
&invalidate_pixmap_line_helper, &invalidate_layout_line_helper | |
t@@ -245,12 +249,12 @@ view_notify_append_line(ledit_view *view, size_t line) { | |
resize_and_move_line_gap(view, add_sz(view->lines_num, 1), line + 1); | |
if (line < view->cur_line) | |
view->cur_line++; | |
- if (view->sel_valid) | |
- view_set_selection(view, view->cur_line, view->cur_index, view… | |
view->lines_num++; | |
view->lines_gap++; | |
ledit_view_line *vl = view_get_line(view, line + 1); | |
init_line(view, vl); | |
+ if (sel_valid) | |
+ view_set_selection(view, view->cur_line, view->cur_index, view… | |
} | |
void | |
t@@ -277,8 +281,6 @@ view_notify_delete_lines(ledit_view *view, size_t index1, … | |
if (vl->cursor_index_valid) | |
view_set_line_cursor_attrs(view, view->cur_line, view-… | |
} | |
- if (sel_valid) | |
- view_set_selection(view, view->cur_line, view->cur_index, view… | |
cache_invalidate_from_line( | |
view->cache, index1, view, | |
&invalidate_pixmap_line_helper, &invalidate_layout_line_helper | |
t@@ -295,6 +297,8 @@ view_notify_delete_lines(ledit_view *view, size_t index1, … | |
ledit_view_line *vl = view_get_line(view, 0); | |
vl->y_offset = 0; | |
} | |
+ if (sel_valid) | |
+ view_set_selection(view, view->cur_line, view->cur_index, view… | |
} | |
void | |
t@@ -1760,14 +1764,8 @@ view_wipe_selection(ledit_view *view) { | |
} | |
} | |
view->sel_valid = 0; | |
- /* FIXME: check what makes most sense here - this used to be set to 0,… | |
- caused "jumping effects" because some functions (cursor movement) u… | |
- values without checking view->sel_valid before (which should actual… | |
- changed because it is an error) */ | |
- view->sel.line1 = view->sel.line2 = view->cur_line; | |
- view->sel.byte1 = view->sel.byte2 = view->cur_index; | |
- if (view->mode == NORMAL) | |
- view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind… | |
+ view->sel.line1 = view->sel.line2 = 0; | |
+ view->sel.byte1 = view->sel.byte2 = 0; | |
} | |
void |