diff options
| -rw-r--r-- | editor.c | 3 | ||||
| -rw-r--r-- | text.c | 28 | ||||
| -rw-r--r-- | text.h | 6 | ||||
| -rw-r--r-- | vis.c | 12 |
4 files changed, 33 insertions, 16 deletions
@@ -484,7 +484,8 @@ static void editor_prompt_update(Prompt *prompt) { static void editor_prompt_clear(Prompt *prompt) { Text *text = prompt->win->text; - while (text_undo(text)); + while (text_undo(text) != (size_t)-1); + window_cursor_to(prompt->win->win, 0); } void editor_prompt_hide(Editor *ed) { @@ -84,7 +84,8 @@ typedef struct Change Change; struct Change { Span old; /* all pieces which are being modified/swapped out by the change */ Span new; /* all pieces which are introduced/swapped in by the change */ - Change *next; + size_t pos; /* absolute position at which the change occured */ + Change *next; /* next change which is part of the same action */ }; /* An Action is a list of Changes which are used to undo/redo all modifications @@ -144,7 +145,7 @@ static Location piece_get_extern(Text *txt, size_t pos); static void span_init(Span *span, Piece *start, Piece *end); static void span_swap(Text *txt, Span *old, Span *new); /* change management */ -static Change *change_alloc(Text *txt); +static Change *change_alloc(Text *txt, size_t pos); static void change_free(Change *c); /* action management */ static Action *action_alloc(Text *txt); @@ -439,7 +440,7 @@ static Location piece_get_extern(Text *txt, size_t pos) { /* allocate a new change, associate it with current action or a newly * allocated one if none exists. */ -static Change *change_alloc(Text *txt) { +static Change *change_alloc(Text *txt, size_t pos) { Action *a = txt->current_action; if (!a) { a = action_alloc(txt); @@ -449,6 +450,7 @@ static Change *change_alloc(Text *txt) { Change *c = calloc(1, sizeof(Change)); if (!c) return NULL; + c->pos = pos; c->next = a->change; a->change = c; return c; @@ -501,7 +503,7 @@ bool text_insert_raw(Text *txt, size_t pos, const char *data, size_t len) { if (cache_insert(txt, p, off, data, len)) return true; - Change *c = change_alloc(txt); + Change *c = change_alloc(txt, pos); if (!c) return false; @@ -547,31 +549,35 @@ bool text_insert(Text *txt, size_t pos, const char *data) { } /* undo all changes of the last action, return whether changes existed */ -bool text_undo(Text *txt) { +size_t text_undo(Text *txt) { + size_t pos = -1; Action *a = action_pop(&txt->undo); if (!a) - return false; + return pos; for (Change *c = a->change; c; c = c->next) { span_swap(txt, &c->new, &c->old); + pos = c->pos; } action_push(&txt->redo, a); lineno_cache_invalidate(&txt->lines); - return true; + return pos; } /* redo all changes of the last action, return whether changes existed */ -bool text_redo(Text *txt) { +size_t text_redo(Text *txt) { + size_t pos = -1; Action *a = action_pop(&txt->redo); if (!a) - return false; + return pos; for (Change *c = a->change; c; c = c->next) { span_swap(txt, &c->old, &c->new); + pos = c->pos; } action_push(&txt->undo, a); lineno_cache_invalidate(&txt->lines); - return true; + return pos; } /* save current content to given filename. the data is first saved to @@ -706,7 +712,7 @@ bool text_delete(Text *txt, size_t pos, size_t len) { return true; size_t cur; // how much has already been deleted bool midway_start = false, midway_end = false; - Change *c = change_alloc(txt); + Change *c = change_alloc(txt, pos); if (!c) return false; Piece *before, *after; // unmodified pieces before / after deletion point @@ -33,8 +33,10 @@ bool text_insert(Text*, size_t pos, const char *data); bool text_insert_raw(Text*, size_t pos, const char *data, size_t len); bool text_delete(Text*, size_t pos, size_t len); void text_snapshot(Text*); -bool text_undo(Text*); -bool text_redo(Text*); +/* undo/redos to the last snapshoted state. returns the position where + * the change occured or (size_t)-1 if nothing could be undo/redo. */ +size_t text_undo(Text*); +size_t text_redo(Text*); size_t text_pos_by_lineno(Text*, size_t lineno); size_t text_lineno_by_pos(Text*, size_t pos); @@ -593,13 +593,21 @@ static void mark_line(const Arg *arg) { } static void undo(const Arg *arg) { - if (text_undo(vis->win->text)) + size_t pos = text_undo(vis->win->text); + if (pos != (size_t)-1) { + window_cursor_to(vis->win->win, pos); + /* redraw all windows in case some display the same file */ editor_draw(vis); + } } static void redo(const Arg *arg) { - if (text_redo(vis->win->text)) + size_t pos = text_redo(vis->win->text); + if (pos != (size_t)-1) { + window_cursor_to(vis->win->win, pos); + /* redraw all windows in case some display the same file */ editor_draw(vis); + } } static void zero(const Arg *arg) { |
