commits
tags
#include "undo.h"
#include <stdlib.h>
#include <string.h>
void snapshot_stack_init(SnapshotStack *s, int limit) {
s->items = NULL;
s->count = 0;
s->cap = 0;
s->limit = limit;
}
void snapshot_stack_clear(SnapshotStack *s) {
for (int i = 0; i < s->count; i++) document_free(&s->items[i].doc);
s->count = 0;
}
void snapshot_stack_free(SnapshotStack *s) {
snapshot_stack_clear(s);
free(s->items);
s->items = NULL;
s->cap = 0;
}
void snapshot_stack_push(SnapshotStack *s, const Document *doc, int cursorBlock, int cursorOffset) {
if (s->count == s->cap) {
int newCap = s->cap > 0 ? s->cap * 2 : 8;
s->items = realloc(s->items, (size_t)newCap * sizeof(Snapshot));
s->cap = newCap;
}
Snapshot *slot = &s->items[s->count++];
document_clone(&slot->doc, doc);
slot->cursorBlock = cursorBlock;
slot->cursorOffset = cursorOffset;
if (s->count > s->limit) {
/* Evict the oldest entry, shifting the rest down. */
document_free(&s->items[0].doc);
memmove(&s->items[0], &s->items[1], (size_t)(s->count - 1) * sizeof(Snapshot));
s->count--;
}
}
bool snapshot_stack_pop(SnapshotStack *s, Snapshot *out) {
if (s->count == 0) return false;
*out = s->items[--s->count];
return true;
}
void undo_manager_init(UndoManager *m, int limit) {
snapshot_stack_init(&m->undo, limit);
snapshot_stack_init(&m->redo, limit);
m->lastKind = EDIT_NONE;
m->lastBlock = -1;
m->lastOffset = -1;
}
void undo_manager_free(UndoManager *m) {
snapshot_stack_free(&m->undo);
snapshot_stack_free(&m->redo);
}
void undo_manager_reset(UndoManager *m) {
snapshot_stack_clear(&m->undo);
snapshot_stack_clear(&m->redo);
m->lastKind = EDIT_NONE;
m->lastBlock = -1;
m->lastOffset = -1;
}
void undo_manager_before_edit(UndoManager *m, EditKind kind, const Document *doc, int cursorBlock, int cursorOffset) {
bool coalesce = (kind == m->lastKind) && (cursorBlock == m->lastBlock) && (cursorOffset == m->lastOffset);
if (!coalesce) {
snapshot_stack_push(&m->undo, doc, cursorBlock, cursorOffset);
snapshot_stack_clear(&m->redo);
}
}
void undo_manager_after_edit(UndoManager *m, EditKind kind, int cursorBlock, int cursorOffset) {
m->lastKind = kind;
m->lastBlock = cursorBlock;
m->lastOffset = cursorOffset;
}