From 60fe132d6c59d54021091af8e5aa09fcd4704562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Tue, 30 Jun 2015 11:13:17 +0200 Subject: Cleanup insert/replace mode input handling View should only display the file content, but not modify it. --- config.def.h | 2 +- editor.c | 61 ++++++++++++++++++++++++++++++--------------- editor.h | 6 ++--- view.c | 80 +++++------------------------------------------------------- view.h | 18 +++++++++----- vis.c | 22 ++++------------- 6 files changed, 69 insertions(+), 120 deletions(-) diff --git a/config.def.h b/config.def.h index 044c530..9d491a0 100644 --- a/config.def.h +++ b/config.def.h @@ -486,7 +486,7 @@ static KeyBinding vis_mode_readline[] = { BACKSPACE( call, f, editor_backspace_key ), { { NONE(ESC) }, switchmode, { .i = VIS_MODE_NORMAL } }, { { CONTROL('c') }, switchmode, { .i = VIS_MODE_NORMAL } }, - { { CONTROL('D') }, call, { .f = editor_delete_key } }, + { { CONTROL('D') }, delete , { .i = MOVE_CHAR_NEXT } }, { { CONTROL('W') }, delete, { .i = MOVE_LONGWORD_START_PREV } }, { { CONTROL('U') }, delete, { .i = MOVE_LINE_BEGIN } }, { /* empty last element, array terminator */ }, diff --git a/editor.c b/editor.c index 114c06e..ae2bc2d 100644 --- a/editor.c +++ b/editor.c @@ -5,6 +5,7 @@ #include #include "editor.h" #include "util.h" +#include "text-motions.h" static void file_free(Editor *ed, File *file); static File *file_new(Editor *ed, const char *filename); @@ -421,35 +422,57 @@ void editor_free(Editor *ed) { free(ed); } -void editor_insert_key(Editor *ed, const char *c, size_t len) { +void editor_insert(Editor *ed, size_t pos, const char *data, size_t len) { + text_insert(ed->win->file->text, pos, data, len); + editor_windows_invalidate(ed, pos, pos + len); +} + +void editor_insert_key(Editor *ed, const char *data, size_t len) { View *view = ed->win->view; - size_t start = view_cursor_get(view); - view_insert_key(view, c, len); - editor_windows_invalidate(ed, start, start + len); + size_t pos = view_cursor_get(view); + if (memchr(data, '\n', len) && view_cursor_viewpos(view).y+1 == view_height_get(view)) + view_viewport_down(view, 1); + editor_insert(ed, pos, data, len); + view_cursor_to(view, pos + len); +} + +void editor_replace(Editor *ed, size_t pos, const char *data, size_t len) { + size_t chars = 0; + for (size_t i = 0; i < len; i++) { + if (ISUTF8(data[i])) + chars++; + } + + Text *txt = ed->win->file->text; + Iterator it = text_iterator_get(txt, pos); + for (char c; chars-- > 0 && text_iterator_byte_get(&it, &c) && c != '\r' && c != '\n'; ) + text_iterator_char_next(&it, NULL); + + text_delete(txt, pos, it.pos - pos); + editor_insert(ed, pos, data, len); } -void editor_replace_key(Editor *ed, const char *c, size_t len) { +void editor_replace_key(Editor *ed, const char *data, size_t len) { View *view = ed->win->view; - size_t start = view_cursor_get(view); - view_replace_key(view, c, len); - editor_windows_invalidate(ed, start, start + 6); + size_t pos = view_cursor_get(view); + if (memchr(data, '\n', len) && view_cursor_viewpos(view).y+1 == view_height_get(view)) + view_viewport_down(view, 1); + editor_replace(ed, pos, data, len); + view_cursor_to(view, pos + len); } void editor_backspace_key(Editor *ed) { View *view = ed->win->view; + Text *txt = ed->win->file->text; size_t end = view_cursor_get(view); - size_t start = view_backspace_key(view); + size_t start = text_char_prev(txt, end); + if (view_viewport_get(view).start == end) { + view_viewport_up(view, 1); + view_cursor_to(view, end); + } + text_delete(txt, start, end-start); editor_windows_invalidate(ed, start, end); -} - -void editor_delete_key(Editor *ed) { - size_t start = view_delete_key(ed->win->view); - editor_windows_invalidate(ed, start, start + 6); -} - -void editor_insert(Editor *ed, size_t pos, const char *c, size_t len) { - text_insert(ed->win->file->text, pos, c, len); - editor_windows_invalidate(ed, pos, pos + len); + view_cursor_to(view, start); } void editor_delete(Editor *ed, size_t pos, size_t len) { diff --git a/editor.h b/editor.h index d985755..3fd130a 100644 --- a/editor.h +++ b/editor.h @@ -257,12 +257,12 @@ void editor_suspend(Editor*); /* these function operate on the currently focused window but make sure * that all windows which show the affected region are redrawn too. */ -void editor_insert_key(Editor*, const char *c, size_t len); -void editor_replace_key(Editor*, const char *c, size_t len); +void editor_insert_key(Editor*, const char *data, size_t len); +void editor_replace_key(Editor*, const char *data, size_t len); void editor_backspace_key(Editor*); -void editor_delete_key(Editor*); void editor_insert(Editor*, size_t pos, const char *data, size_t len); void editor_delete(Editor*, size_t pos, size_t len); +void editor_replace(Editor*, size_t pos, const char *data, size_t len); /* set tabwidth (must be in range [1, 8], affects all windows */ void editor_tabwidth_set(Editor*, int tabwidth); diff --git a/view.c b/view.c index 73fca17..85e5c41 100644 --- a/view.c +++ b/view.c @@ -59,16 +59,6 @@ static bool view_addch(View *view, Cell *cell); static size_t view_cursor_update(View *view); /* set/move current cursor position to a given (line, column) pair */ static size_t view_cursor_set(View *view, Line *line, int col); -/* move visible viewport n-lines up/down, redraws the view but does not change - * cursor position which becomes invalid and should be corrected by either: - * - * - view_cursor_to - * - view_cursor_set - * - * the return value indicates wether the visible area changed. - */ -static bool view_viewport_up(View *view, int n); -static bool view_viewport_down(View *view, int n); void view_tabwidth_set(View *view, int tabwidth) { view->tabwidth = tabwidth; @@ -237,6 +227,10 @@ CursorPos view_cursor_getpos(View *view) { return pos; } +ViewPos view_cursor_viewpos(View *view) { + return (ViewPos){ .x = view->cursor.col, .y = view->cursor.row }; +} + /* snyc current cursor position with internal Line/Cell structures */ static void view_cursor_sync(View *view) { int row = 0, col = 0; @@ -596,7 +590,7 @@ static size_t view_cursor_set(View *view, Line *line, int col) { return pos; } -static bool view_viewport_down(View *view, int n) { +bool view_viewport_down(View *view, int n) { Line *line; if (view->end == text_size(view->text)) return false; @@ -610,7 +604,7 @@ static bool view_viewport_down(View *view, int n) { return true; } -static bool view_viewport_up(View *view, int n) { +bool view_viewport_up(View *view, int n) { /* scrolling up is somewhat tricky because we do not yet know where * the lines start, therefore scan backwards but stop at a reasonable * maximum in case we are dealing with a file without any newlines @@ -797,68 +791,6 @@ size_t view_screenline_end(View *view) { return view_cursor_set(view, cursor->line, col >= 0 ? col : 0); } -size_t view_delete_key(View *view) { - Cursor *cursor = &view->cursor; - Line *line = cursor->line; - size_t len = line->cells[cursor->col].len; - text_delete(view->text, cursor->pos, len); - view_draw(view); - view_cursor_to(view, cursor->pos); - return cursor->pos; -} - -size_t view_backspace_key(View *view) { - Cursor *cursor = &view->cursor; - if (view->start == cursor->pos) { - if (view->start == 0) - return cursor->pos; - /* if we are on the top left most position in the view - * first scroll up so that the to be deleted character is - * visible then proceed as normal */ - size_t pos = cursor->pos; - view_viewport_up(view, 1); - view_cursor_to(view, pos); - } - view_char_prev(view); - size_t pos = cursor->pos; - size_t len = cursor->line->cells[cursor->col].len; - text_delete(view->text, pos, len); - view_draw(view); - view_cursor_to(view, pos); - return pos; -} - -size_t view_insert_key(View *view, const char *c, size_t len) { - size_t pos = view->cursor.pos; - text_insert(view->text, pos, c, len); - if (view->cursor.line == view->bottomline && memchr(c, '\n', len)) - view_viewport_down(view, 1); - else - view_draw(view); - pos += len; - view_cursor_to(view, pos); - return pos; -} - -size_t view_replace_key(View *view, const char *c, size_t len) { - Cursor *cursor = &view->cursor; - Line *line = cursor->line; - size_t pos = cursor->pos; - /* do not overwrite new line which would merge the two lines */ - if (line->cells[cursor->col].data[0] != '\n') { - size_t oldlen = line->cells[cursor->col].len; - text_delete(view->text, pos, oldlen); - } - text_insert(view->text, pos, c, len); - if (cursor->line == view->bottomline && memchr(c, '\n', len)) - view_viewport_down(view, 1); - else - view_draw(view); - pos += len; - view_cursor_to(view, pos); - return pos; -} - size_t view_cursor_get(View *view) { return view->cursor.pos; } diff --git a/view.h b/view.h index 9a9cd8c..01b4918 100644 --- a/view.h +++ b/view.h @@ -46,12 +46,6 @@ void view_ui(View*, UiWin*); void view_reload(View*, Text*); void view_free(View*); -/* keyboard input at cursor position */ -size_t view_insert_key(View*, const char *c, size_t len); -size_t view_replace_key(View*, const char *c, size_t len); -size_t view_backspace_key(View*); -size_t view_delete_key(View*); - bool view_resize(View*, int width, int height); int view_height_get(View*); void view_draw(View*); @@ -83,6 +77,12 @@ size_t view_screenline_goto(View*, int n); /* get cursor position in bytes from start of the file */ size_t view_cursor_get(View*); +typedef struct { + int x, y; +} ViewPos; + +ViewPos view_cursor_viewpos(View*); + const Line *view_lines_get(View*); /* get cursor position in terms of screen coordinates */ CursorPos view_cursor_getpos(View*); @@ -108,6 +108,12 @@ void view_selection_set(View*, Filerange *sel); void view_selection_clear(View*); /* get the currently displayed area in bytes from the start of the file */ Filerange view_viewport_get(View*); +/* move visible viewport n-lines up/down, redraws the view but does not change + * cursor position which becomes invalid and should be corrected by calling + * view_cursor_to. the return value indicates wether the visible area changed. + */ +bool view_viewport_up(View *view, int n); +bool view_viewport_down(View *view, int n); /* associate a set of syntax highlighting rules to this window. */ void view_syntax_set(View*, Syntax*); Syntax *view_syntax_get(View*); diff --git a/vis.c b/vis.c index 000a3ab..bb7bf21 100644 --- a/vis.c +++ b/vis.c @@ -592,21 +592,10 @@ static size_t op_repeat_insert(OperatorContext *c) { } static size_t op_repeat_replace(OperatorContext *c) { - Text *txt = vis->win->file->text; - size_t chars = 0, len = vis->buffer_repeat.len; - if (!len) - return c->pos; const char *data = vis->buffer_repeat.data; - for (size_t i = 0; i < len; i++) { - if (ISUTF8(data[i])) - chars++; - } - - Iterator it = text_iterator_get(txt, c->pos); - while (chars-- > 0) - text_iterator_char_next(&it, NULL); - text_delete(txt, c->pos, it.pos - c->pos); - return op_repeat_insert(c); + size_t len = vis->buffer_repeat.len; + editor_replace(vis, c->pos, data, len); + return c->pos + len; } /** movement implementations of type: size_t (*move)(const Arg*) */ @@ -818,8 +807,7 @@ static void replace(const Arg *arg) { action_reset(&vis->action_prev); vis->action_prev.op = &ops[OP_REPEAT_REPLACE]; buffer_put(&vis->buffer_repeat, k.str, strlen(k.str)); - editor_delete_key(vis); - editor_insert_key(vis, k.str, strlen(k.str)); + editor_replace(vis, pos, k.str, strlen(k.str)); text_snapshot(vis->win->file->text); view_cursor_to(vis->win->view, pos); } @@ -1037,7 +1025,7 @@ static void prompt_backspace(const Arg *arg) { if (!cmd || !*cmd) prompt_enter(NULL); else - view_backspace_key(vis->win->view); + delete(&(const Arg){ .i = MOVE_CHAR_PREV }); free(cmd); } -- cgit v1.2.3