aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-06-30 11:13:17 +0200
committerMarc André Tanner <mat@brain-dump.org>2015-06-30 11:13:17 +0200
commit60fe132d6c59d54021091af8e5aa09fcd4704562 (patch)
tree506249a4ebd7a09c0e2433c2a920c8c89a1ca4a8
parent82a10e051c593e133554ce9675169fd68bb02ad7 (diff)
downloadvis-60fe132d6c59d54021091af8e5aa09fcd4704562.tar.gz
vis-60fe132d6c59d54021091af8e5aa09fcd4704562.tar.xz
Cleanup insert/replace mode input handling
View should only display the file content, but not modify it.
-rw-r--r--config.def.h2
-rw-r--r--editor.c61
-rw-r--r--editor.h6
-rw-r--r--view.c80
-rw-r--r--view.h18
-rw-r--r--vis.c22
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 <errno.h>
#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);
}