Redo working

This commit is contained in:
Krzosa Karol
2024-07-01 07:41:44 +02:00
parent d1f83fa669
commit 1a420e2f22
2 changed files with 86 additions and 49 deletions

View File

@@ -20,7 +20,8 @@ struct HistoryEntry {
};
struct History {
Array<HistoryEntry> entries;
Array<HistoryEntry> undo_stack;
Array<HistoryEntry> redo_stack;
int debug_edit_phase;
};
@@ -287,14 +288,78 @@ void MergeCursors(Window *window) {
new_cursors.add(it);
}
}
Assert(new_cursors.len <= window->cursors.len);
window->cursors.dealloc();
window->cursors = new_cursors;
}
void UndoEdit(Window *window) {
if (window->history.entries.len <= 0) return;
void SaveHistoryBeforeMergeCursor(Window *window, Array<HistoryEntry> *stack) {
HistoryEntry *entry = stack->alloc();
Allocator sys_allocator = GetSystemAllocator();
entry->cursors = window->cursors.tight_copy(sys_allocator);
}
HistoryEntry entry = window->history.entries.pop();
void SaveHistoryBeforeApplyEdits(Window *window, Array<HistoryEntry> *stack, Array<Edit> edits) {
HistoryEntry *entry = stack->last();
Allocator sys_allocator = GetSystemAllocator();
entry->edits = edits.tight_copy(sys_allocator);
// Make reverse edits
For(entry->edits) {
Range new_range = {it.range.min, it.range.min + it.string.len};
String string = GetString(window->buffer, it.range);
it.string = Copy(sys_allocator, string);
it.range = new_range;
}
Array<Edit> temp_edits = entry->edits.tight_copy(sys_allocator);
defer { temp_edits.dealloc(); };
// Fix reverse edits
ForItem(edit, edits) {
int64_t remove_size = GetRangeSize(edit.range);
int64_t insert_size = edit.string.len;
int64_t offset = insert_size - remove_size;
for (int64_t i = 0; i < entry->edits.len; i += 1) {
Edit &new_edit = entry->edits.data[i];
Edit &old_edit = temp_edits.data[i];
if (old_edit.range.min > edit.range.min) {
new_edit.range.min += offset;
new_edit.range.max += offset;
}
}
}
}
void RedoEdit(Window *window) {
if (window->history.redo_stack.len <= 0) return;
HistoryEntry entry = window->history.redo_stack.pop();
SaveHistoryBeforeMergeCursor(window, &window->history.undo_stack);
SaveHistoryBeforeApplyEdits(window, &window->history.undo_stack, entry.edits);
_ApplyEdits(&window->buffer, entry.edits);
window->cursors.dealloc();
window->cursors = entry.cursors;
Allocator sys_allocator = GetSystemAllocator();
For(entry.edits) Dealloc(sys_allocator, &it.string.data);
entry.edits.dealloc();
// Generate layout
Clear(&window->layout_arena);
window->layout = CalculateLayout(&window->layout_arena, window->buffer, window->font, window->font_size, window->font_spacing);
}
void UndoEdit(Window *window) {
if (window->history.undo_stack.len <= 0) return;
HistoryEntry entry = window->history.undo_stack.pop();
SaveHistoryBeforeMergeCursor(window, &window->history.redo_stack);
SaveHistoryBeforeApplyEdits(window, &window->history.redo_stack, entry.edits);
_ApplyEdits(&window->buffer, entry.edits);
window->cursors.dealloc();
@@ -312,55 +377,21 @@ void UndoEdit(Window *window) {
void BeforeEdit(Window *window) {
Assert(window->history.debug_edit_phase == 0);
window->history.debug_edit_phase += 1;
{
History &h = window->history;
HistoryEntry *entry = h.entries.alloc();
Allocator sys_allocator = GetSystemAllocator();
Assert(window->cursors.len);
entry->cursors = window->cursors.tight_copy(sys_allocator);
Assert(window->cursors.len);
SaveHistoryBeforeMergeCursor(window, &window->history.undo_stack);
For(window->history.redo_stack) {
it.cursors.dealloc();
ForItem(edit, it.edits) Dealloc(it.edits.allocator, &edit.string.data);
it.edits.dealloc();
}
window->history.redo_stack.dealloc();
MergeCursors(window);
}
void ApplyEdits(Window *window, Array<Edit> edits) {
Assert(window->history.debug_edit_phase == 1);
window->history.debug_edit_phase += 1;
{
HistoryEntry *entry = window->history.entries.last();
Allocator sys_allocator = GetSystemAllocator();
entry->edits = edits.tight_copy(sys_allocator);
// Make reverse edits
For(entry->edits) {
Range new_range = {it.range.min, it.range.min + it.string.len};
String string = GetString(window->buffer, it.range);
it.string = Copy(sys_allocator, string);
it.range = new_range;
}
Array<Edit> temp_edits = entry->edits.tight_copy(sys_allocator);
defer { temp_edits.dealloc(); };
// Fix reverse edits
ForItem(edit, edits) {
int64_t remove_size = GetRangeSize(edit.range);
int64_t insert_size = edit.string.len;
int64_t offset = insert_size - remove_size;
for (int64_t i = 0; i < entry->edits.len; i += 1) {
Edit &new_edit = entry->edits.data[i];
Edit &old_edit = temp_edits.data[i];
if (old_edit.range.min > edit.range.min) {
new_edit.range.min += offset;
new_edit.range.max += offset;
}
}
}
}
SaveHistoryBeforeApplyEdits(window, &window->history.undo_stack, edits);
_ApplyEdits(&window->buffer, edits);
}
@@ -368,7 +399,7 @@ void AfterEdit(Window *window, Array<Edit> edits) {
Assert(window->history.debug_edit_phase == 2);
window->history.debug_edit_phase -= 2;
HistoryEntry *entry = window->history.entries.last();
HistoryEntry *entry = window->history.undo_stack.last();
Assert(entry->cursors.len);
Assert(entry->edits.len);

View File

@@ -316,8 +316,14 @@ int main() {
AfterEdit(focused_window, edits);
}
if (IsKeyDown(KEY_LEFT_CONTROL) && (IsKeyPressed(KEY_Z) || IsKeyPressedRepeat(KEY_Z))) {
UndoEdit(focused_window);
if ((IsKeyPressed(KEY_Z) || IsKeyPressedRepeat(KEY_Z))) {
if (IsKeyDown(KEY_LEFT_CONTROL)) {
if (IsKeyDown(KEY_LEFT_SHIFT)) {
RedoEdit(focused_window);
} else {
UndoEdit(focused_window);
}
}
}
if (IsKeyPressed(KEY_DELETE) || IsKeyPressedRepeat(KEY_DELETE)) {