aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2020-02-04 18:08:58 +0100
committerMarc André Tanner <mat@brain-dump.org>2020-02-04 18:25:58 +0100
commit05067a24028eaedae01beb248c4409dc5d980862 (patch)
tree96e0a29d3f4ecab9703754d86c3439c5e3479d5b
parent17b83db3c57682991c188f0338bebe521408917a (diff)
downloadvis-05067a24028eaedae01beb248c4409dc5d980862.tar.gz
vis-05067a24028eaedae01beb248c4409dc5d980862.tar.xz
vis: make core code more robust
The core vis code was originally written under the assumption that there always exists at least one window. However, when being called from the Lua configuration file during start up this is not yet the case. In general, Lua code should always be placed within appropriate event handlers e.g. vis.events.INIT for global configuration. Invoking API functions depending on an active window from top level statements is not supported. Where before the editor simply crashed, these changes turn such code sections into NOPs. Fix #561
-rw-r--r--vis-lua.c2
-rw-r--r--vis-modes.c43
-rw-r--r--vis.c54
3 files changed, 69 insertions, 30 deletions
diff --git a/vis-lua.c b/vis-lua.c
index 344874b..0d9c24e 100644
--- a/vis-lua.c
+++ b/vis-lua.c
@@ -2852,7 +2852,7 @@ void vis_lua_quit(Vis *vis) {
*/
static bool vis_lua_input(Vis *vis, const char *key, size_t len) {
lua_State *L = vis->lua;
- if (!L || vis->win->file->internal)
+ if (!L || !vis->win || vis->win->file->internal)
return false;
bool ret = false;
vis_lua_event_get(L, "input");
diff --git a/vis-modes.c b/vis-modes.c
index 875d674..2e120aa 100644
--- a/vis-modes.c
+++ b/vis-modes.c
@@ -141,11 +141,14 @@ bool vis_window_mode_map(Win *win, enum VisMode id, bool force, const char *key,
/** mode switching event handlers */
static void vis_mode_normal_enter(Vis *vis, Mode *old) {
+ Win *win = vis->win;
+ if (!win)
+ return;
if (old != mode_get(vis, VIS_MODE_INSERT) && old != mode_get(vis, VIS_MODE_REPLACE))
return;
if (vis->autoindent && strcmp(vis->key_prev, "<Enter>") == 0) {
- Text *txt = vis->win->file->text;
- for (Selection *s = view_selections(vis->win->view); s; s = view_selections_next(s)) {
+ Text *txt = win->file->text;
+ for (Selection *s = view_selections(win->view); s; s = view_selections_next(s)) {
size_t pos = view_cursors_pos(s);
size_t start = text_line_start(txt, pos);
size_t end = text_line_end(txt, pos);
@@ -160,7 +163,7 @@ static void vis_mode_normal_enter(Vis *vis, Mode *old) {
}
}
macro_operator_stop(vis);
- if (!vis->win->parent && vis->action_prev.op == &vis_operators[VIS_OP_MODESWITCH] &&
+ if (!win->parent && vis->action_prev.op == &vis_operators[VIS_OP_MODESWITCH] &&
vis->action_prev.count > 1) {
/* temporarily disable motion, in something like `5atext`
* we should only move the cursor once then insert the text */
@@ -174,7 +177,7 @@ static void vis_mode_normal_enter(Vis *vis, Mode *old) {
vis->action_prev.movement = motion;
}
/* make sure we can recover the current state after an editing operation */
- vis_file_snapshot(vis, vis->win->file);
+ vis_file_snapshot(vis, win->file);
}
static void vis_mode_operator_input(Vis *vis, const char *str, size_t len) {
@@ -184,15 +187,17 @@ static void vis_mode_operator_input(Vis *vis, const char *str, size_t len) {
}
static void vis_mode_visual_enter(Vis *vis, Mode *old) {
- if (!old->visual) {
- for (Selection *s = view_selections(vis->win->view); s; s = view_selections_next(s))
+ Win *win = vis->win;
+ if (!old->visual && win) {
+ for (Selection *s = view_selections(win->view); s; s = view_selections_next(s))
view_selections_anchor(s, true);
}
}
static void vis_mode_visual_line_enter(Vis *vis, Mode *old) {
- if (!old->visual) {
- for (Selection *s = view_selections(vis->win->view); s; s = view_selections_next(s))
+ Win *win = vis->win;
+ if (!old->visual && win) {
+ for (Selection *s = view_selections(win->view); s; s = view_selections_next(s))
view_selections_anchor(s, true);
}
if (!vis->action.op)
@@ -200,25 +205,29 @@ static void vis_mode_visual_line_enter(Vis *vis, Mode *old) {
}
static void vis_mode_visual_line_leave(Vis *vis, Mode *new) {
+ Win *win = vis->win;
+ if (!win)
+ return;
if (!new->visual) {
if (!vis->action.op)
- window_selection_save(vis->win);
- view_selections_clear_all(vis->win->view);
+ window_selection_save(win);
+ view_selections_clear_all(win->view);
} else {
- view_cursor_to(vis->win->view, view_cursor_get(vis->win->view));
+ view_cursor_to(win->view, view_cursor_get(win->view));
}
}
static void vis_mode_visual_leave(Vis *vis, Mode *new) {
- if (!new->visual) {
+ Win *win = vis->win;
+ if (!new->visual && win) {
if (!vis->action.op)
- window_selection_save(vis->win);
- view_selections_clear_all(vis->win->view);
+ window_selection_save(win);
+ view_selections_clear_all(win->view);
}
}
static void vis_mode_insert_replace_enter(Vis *vis, Mode *old) {
- if (vis->win->parent)
+ if (!vis->win || vis->win->parent)
return;
if (!vis->action.op) {
action_reset(&vis->action_prev);
@@ -229,7 +238,9 @@ static void vis_mode_insert_replace_enter(Vis *vis, Mode *old) {
}
static void vis_mode_insert_idle(Vis *vis) {
- vis_file_snapshot(vis, vis->win->file);
+ Win *win = vis->win;
+ if (win)
+ vis_file_snapshot(vis, win->file);
}
static void vis_mode_insert_input(Vis *vis, const char *str, size_t len) {
diff --git a/vis.c b/vis.c
index 394b855..447d4a3 100644
--- a/vis.c
+++ b/vis.c
@@ -755,12 +755,18 @@ void vis_free(Vis *vis) {
}
void vis_insert(Vis *vis, size_t pos, const char *data, size_t len) {
- text_insert(vis->win->file->text, pos, data, len);
- vis_window_invalidate(vis->win);
+ Win *win = vis->win;
+ if (!win)
+ return;
+ text_insert(win->file->text, pos, data, len);
+ vis_window_invalidate(win);
}
void vis_insert_key(Vis *vis, const char *data, size_t len) {
- for (Selection *s = view_selections(vis->win->view); s; s = view_selections_next(s)) {
+ Win *win = vis->win;
+ if (!win)
+ return;
+ for (Selection *s = view_selections(win->view); s; s = view_selections_next(s)) {
size_t pos = view_cursors_pos(s);
vis_insert(vis, pos, data, len);
view_cursors_scroll_to(s, pos + len);
@@ -768,7 +774,10 @@ void vis_insert_key(Vis *vis, const char *data, size_t len) {
}
void vis_replace(Vis *vis, size_t pos, const char *data, size_t len) {
- Text *txt = vis->win->file->text;
+ Win *win = vis->win;
+ if (!win)
+ return;
+ Text *txt = win->file->text;
Iterator it = text_iterator_get(txt, pos);
int chars = text_char_count(data, len);
for (char c; chars-- > 0 && text_iterator_byte_get(&it, &c) && c != '\n'; )
@@ -779,7 +788,10 @@ void vis_replace(Vis *vis, size_t pos, const char *data, size_t len) {
}
void vis_replace_key(Vis *vis, const char *data, size_t len) {
- for (Selection *s = view_selections(vis->win->view); s; s = view_selections_next(s)) {
+ Win *win = vis->win;
+ if (!win)
+ return;
+ for (Selection *s = view_selections(win->view); s; s = view_selections_next(s)) {
size_t pos = view_cursors_pos(s);
vis_replace(vis, pos, data, len);
view_cursors_scroll_to(s, pos + len);
@@ -787,8 +799,11 @@ void vis_replace_key(Vis *vis, const char *data, size_t len) {
}
void vis_delete(Vis *vis, size_t pos, size_t len) {
- text_delete(vis->win->file->text, pos, len);
- vis_window_invalidate(vis->win);
+ Win *win = vis->win;
+ if (!win)
+ return;
+ text_delete(win->file->text, pos, len);
+ vis_window_invalidate(win);
}
bool vis_action_register(Vis *vis, const KeyAction *action) {
@@ -813,6 +828,8 @@ bool vis_interrupt_requested(Vis *vis) {
void vis_do(Vis *vis) {
Win *win = vis->win;
+ if (!win)
+ return;
File *file = win->file;
Text *txt = file->text;
View *view = win->view;
@@ -1497,7 +1514,9 @@ bool vis_macro_replay(Vis *vis, enum VisRegister id) {
vis_cancel(vis);
for (int i = 0; i < count; i++)
macro_replay(vis, macro);
- vis_file_snapshot(vis, vis->win->file);
+ Win *win = vis->win;
+ if (win)
+ vis_file_snapshot(vis, win->file);
return true;
}
@@ -1526,7 +1545,9 @@ void vis_repeat(Vis *vis) {
vis->action_prev = action_prev;
}
vis_cancel(vis);
- vis_file_snapshot(vis, vis->win->file);
+ Win *win = vis->win;
+ if (win)
+ vis_file_snapshot(vis, win->file);
}
int vis_count_get(Vis *vis) {
@@ -1571,15 +1592,18 @@ void vis_exit(Vis *vis, int status) {
}
void vis_insert_tab(Vis *vis) {
+ Win *win = vis->win;
+ if (!win)
+ return;
if (!vis->expandtab) {
vis_insert_key(vis, "\t", 1);
return;
}
char spaces[9];
int tabwidth = MIN(vis->tabwidth, LENGTH(spaces) - 1);
- for (Selection *s = view_selections(vis->win->view); s; s = view_selections_next(s)) {
+ for (Selection *s = view_selections(win->view); s; s = view_selections_next(s)) {
size_t pos = view_cursors_pos(s);
- int width = text_line_width_get(vis->win->file->text, pos);
+ int width = text_line_width_get(win->file->text, pos);
int count = tabwidth - (width % tabwidth);
for (int i = 0; i < count; i++)
spaces[i] = ' ';
@@ -1630,6 +1654,8 @@ size_t vis_text_insert_nl(Vis *vis, Text *txt, size_t pos) {
void vis_insert_nl(Vis *vis) {
Win *win = vis->win;
+ if (!win)
+ return;
View *view = win->view;
Text *txt = win->file->text;
for (Selection *s = view_selections(view); s; s = view_selections_next(s)) {
@@ -1936,11 +1962,13 @@ void vis_file_snapshot(Vis *vis, File *file) {
}
Text *vis_text(Vis *vis) {
- return vis->win->file->text;
+ Win *win = vis->win;
+ return win ? win->file->text : NULL;
}
View *vis_view(Vis *vis) {
- return vis->win->view;
+ Win *win = vis->win;
+ return win ? win->view : NULL;
}
Win *vis_window(Vis *vis) {