diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-09-20 22:17:36 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-09-20 22:17:36 -0700 |
commit | bf953d07cf4caa822677b64cae5e8fc444bcdfe2 (patch) | |
tree | ed25f4930894e157d1f46f6fcf03823f847f740e | |
parent | 7c3fd4898b04c0e7be5e67f781dd123bc1f61237 (diff) | |
download | txr-bf953d07cf4caa822677b64cae5e8fc444bcdfe2.tar.gz txr-bf953d07cf4caa822677b64cae5e8fc444bcdfe2.tar.bz2 txr-bf953d07cf4caa822677b64cae5e8fc444bcdfe2.zip |
linenoise: renumber history indices in undo items
This has to be done because each time a history line is added,
or taken back, the relative numbers change.
* linenoise/linenoise.c (undo_pop): New static function.
(restore_undo): Skip undo items which refer to lines of
history which no longer exist. Restore history[0] also.
(renumber_undo_hist): New static function.
(edit): When leaving, and removing the extra history
line representing the current line, renumber the undo
items by -1.
(lino_hist_add): After adding a line, bump the undo item
history indices by 1.
-rw-r--r-- | linenoise/linenoise.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c index 330f1cad..70ccc490 100644 --- a/linenoise/linenoise.c +++ b/linenoise/linenoise.c @@ -352,6 +352,17 @@ static void record_triv_undo(lino_t *l) l->undo_stack->triv = 1; } +static void undo_pop(lino_t *l) +{ + struct lino_undo *top = l->undo_stack; + if (top == 0) + return; + l->undo_stack = top->next; + free(top->data); + top->data = 0; + free(top); +} + static void restore_undo(lino_t *l) { struct lino_undo *top = l->undo_stack; @@ -359,7 +370,11 @@ static void restore_undo(lino_t *l) if (top == 0) return; - l->undo_stack = top->next; + if (top->hist_index >= l->history_len - 1) { + undo_pop(l); + restore_undo(l); + return; + } strcpy(l->data, top->data); l->dlen = strlen(top->data); @@ -369,7 +384,7 @@ static void restore_undo(lino_t *l) { int history_pos = l->history_len - 1 - l->history_index; - if (history_pos >= 0 && history_pos < l->history_len - 1) { + if (history_pos >= 0 && history_pos < l->history_len) { free(l->history[history_pos]); l->history[history_pos] = chk_strdup_utf8(l->data); } @@ -377,9 +392,14 @@ static void restore_undo(lino_t *l) l->need_refresh = 1; - free(top->data); - top->data = 0; - free(top); + undo_pop(l); +} + +static void renumber_undo_hist(lino_t *l, int delta) +{ + struct lino_undo *iter; + for (iter = l->undo_stack; iter != 0; iter = iter->next) + iter->hist_index += delta; } /* ============================== Completion ================================ */ @@ -1750,6 +1770,7 @@ out: l->history_len--; free(l->history[l->history_len]); l->history[l->history_len] = 0; + renumber_undo_hist(l, -1); } return ret; } @@ -1980,6 +2001,7 @@ int lino_hist_add(lino_t *ls, const char *line) { } ls->history[ls->history_len] = linecopy; ls->history_len++; + renumber_undo_hist(ls, 1); return 1; } |