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 b4b11228f9a7851bd47ceb8e9e31d8a3a857af79
parent d3e5c88151dca9a99f6c62bd0526391eecfc15cd
Author: lumidify <nobody@lumidify.org>
Date:   Sun, 26 Dec 2021 19:10:08 +0100

Fix crash on closing view

Diffstat:
Mbuffer.c | 2+-
Mkeys_command.c | 12++++++++----
Mledit.1 | 4++++
Mledit.c | 23+++++++++++++++++++++++
Mview.c | 1+
Mview.h | 1+
6 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/buffer.c b/buffer.c @@ -311,7 +311,7 @@ buffer_remove_view(ledit_buffer *buffer, ledit_view *view) { buffer->views + i + 1, (buffer->views_num - i - 1) * sizeof(ledit_view *) ); - ledit_reallocarray(buffer->views, --buffer->views_num, sizeof(ledit_view *)); + buffer->views = ledit_reallocarray(buffer->views, --buffer->views_num, sizeof(ledit_view *)); } } diff --git a/keys_command.c b/keys_command.c @@ -199,11 +199,15 @@ close_view(ledit_view *view, char *cmd, size_t l1, size_t l2) { (void)l2; /* FIXME: This will lead to problems if I add something that requires access to the view after the command is handled. */ + cmd++; + int force = 0; + if (*cmd == '!') + force = 1; ledit_buffer *buffer = view->buffer; - buffer_remove_view(buffer, view); - if (buffer->views_num == 0) { - ledit_cleanup(); - exit(0); + if (buffer->views_num == 1 && buffer->modified && !force) { + window_show_message(view->window, "File modified; write or use ! to override", -1); + } else { + view->destroy = 1; } return 0; } diff --git a/ledit.1 b/ledit.1 @@ -801,6 +801,10 @@ Confirm each substitution before performing it. Open a new view. Each view is a window that shows the text in the current buffer, which is synced between the views. +.It Cm :c +Close a view. +.It Cm :c\&! +Close a view, even if it is the last one and there are unsaved changes. .El .Sh MOUSE ACTIONS There currently are not many mouse actions. diff --git a/ledit.c b/ledit.c @@ -84,6 +84,29 @@ mainloop(void) { clock_gettime(CLOCK_MONOTONIC, &last); sleep_time.tv_sec = 0; while (running) { + /* This "lazy destroying" is not entirely ideal yet, but it's + necessary to avoid a crash when closing a view (I'm not + entirely sure what exactly causes the crash) + -> Update: The cause of the crash was something different, + but I'm still leaving it as is for now because there + may be other reasons for doing it lazily. */ + for (size_t i = 0; i < buffer->views_num; i++) { + if (buffer->views[i]->destroy) { + buffer_remove_view(buffer, buffer->views[i]); + if (buffer->views_num == 0) { + ledit_cleanup(); + exit(0); + } + /* only delete one - otherwise, + the loop would need to be + modified + I guess it's unrealistic to + assume that the deletion cmd + will be called multiple times + in such a short time anyways */ + break; + } + } while (XPending(common.dpy)) { XNextEvent(common.dpy, &event); if (event.type == xkb_event_type) { diff --git a/view.c b/view.c @@ -131,6 +131,7 @@ view_create(ledit_buffer *buffer, ledit_theme *theme, ledit_mode mode, size_t li view->display_offset = 0; view->sel.line1 = view->sel.byte1 = 0; view->sel.line2 = view->sel.byte2 = 0; + view->destroy = 0; view->button2_pressed = 0; view->selecting = 0; view->sel_valid = 0; diff --git a/view.h b/view.h @@ -77,6 +77,7 @@ struct ledit_view { long display_offset; /* current pixel offset of viewport */ ledit_range sel; /* current selection */ ledit_mode mode; /* current mode of this view */ + char destroy; /* whether the view should be destroyed at the next possible time */ char selecting; /* whether user is currently selecting text with mouse */ char button2_pressed; /* whether button 2 (middle button) is pressed */ char sel_valid; /* whether there is currently a valid selection */