From 2fe3cf9e625925a878ae8667208c567ac3fb9aab Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Mon, 20 Aug 2018 23:03:37 -0400 Subject: [PATCH] added undo support for deletes --- lib/buf.c | 56 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/lib/buf.c b/lib/buf.c index f8dcbbc..f97a23c 100644 --- a/lib/buf.c +++ b/lib/buf.c @@ -134,8 +134,25 @@ static Sel buf_getsel(Buf* buf) { return sel; } -/* Unod/Redo Operations +/* Undo/Redo Operations ******************************************************************************/ +static void putb(Buf* buf, char b, Sel* p_sel) { + buf_syncgap(buf, p_sel->end); + *(buf->gapstart++) = b; + p_sel->end = p_sel->end + 1u; + p_sel->beg = p_sel->end; + buf->status = MODIFIED; +} + +static Log* mklog(size_t beg, size_t end, char* data, Log* next) { + Log* log = calloc(1, sizeof(Log)); + log->beg = beg; + log->end = end; + log->data = data; + log->next = next; + return log; +} + static void log_clear(Log** list) { while (*list) { Log* deadite = *list; @@ -147,6 +164,30 @@ static void log_clear(Log** list) { } void buf_undo(Buf* buf) { + if (!buf->undo) return; + Log* item = buf->undo; + buf->selection.beg = item->beg; + buf->selection.end = item->end; + if (item->data) { + /* reinsert deleted bytes */ + for (char* s = item->data; s && *s; s++) + putb(buf, *s, &(buf->selection)); + free(item->data); + item->data = NULL; + } else { + /* delete the added bytes */ + Sel sel = buf_getsel(buf); + item->data = buf_gets(buf); + buf_syncgap(buf, sel.beg); + buf->gapend += (item->end - item->beg); + sel.end = sel.beg; + buf->selection = sel; + item->beg = sel.beg; + item->end = sel.end; + } + /* push item onto redo stack */ + item->next = buf->redo; + buf->redo = item; } void buf_redo(Buf* buf) { @@ -165,14 +206,6 @@ void buf_lastins(Buf* buf) { /* Basic Operations and Accessors ******************************************************************************/ -static void putb(Buf* buf, char b, Sel* p_sel) { - buf_syncgap(buf, p_sel->end); - *(buf->gapstart++) = b; - p_sel->end = p_sel->end + 1u; - p_sel->beg = p_sel->end; - buf->status = MODIFIED; -} - static char getb(Buf* buf, size_t off) { if (off >= buf_end(buf)) return '\n'; // TODO: get rid of this hack size_t bsz = (buf->gapstart - buf->bufstart); @@ -225,13 +258,12 @@ void buf_del(Buf* buf) { size_t nbytes = sel.end - sel.beg; if (nbytes > 0) { buf->status = MODIFIED; - //char* str = buf_gets(buf, &sel); + char* str = buf_gets(buf); buf_syncgap(buf, sel.beg); buf->gapend += nbytes; sel.end = sel.beg; buf->selection = sel; - // update log here - // free(str); + buf->undo = mklog(sel.beg, sel.end, str, buf->undo); } } -- 2.49.0