summaryrefslogtreecommitdiff
path: root/src/undo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/undo.cpp')
-rw-r--r--src/undo.cpp56
1 files changed, 54 insertions, 2 deletions
diff --git a/src/undo.cpp b/src/undo.cpp
index ec85530..38c22ef 100644
--- a/src/undo.cpp
+++ b/src/undo.cpp
@@ -1,3 +1,7 @@
+#if SPECIAL
+#include "main.h"
+#endif
+
struct history_info {
uint16 ActionCount_Total;
uint16 ActionCount_EndOfPlayhead;
@@ -11,7 +15,7 @@ struct history_info {
};
static uint64
-History_GetActionSize(history_entry_list *History, int i, uint16 ActionCount_EndOfPlayhead)
+History_GetActionSize(history_entry_list *History, int i)
{
history_action *Action = &History->Action[i];
if (Action->Type == action_type_swap || Action->Type == action_type_swap_bitmap)
@@ -44,7 +48,7 @@ History_GetTreeInfo(history_entry_list *History, uint16 SampleIndex)
for (int i = 0; i < Info.ActionCount_Total; i++)
{
- uint64 Size = History_GetActionSize(History, i, Info.ActionCount_EndOfPlayhead);
+ uint64 Size = History_GetActionSize(History, i);
Info.ActionOffset_Total += Size;
if (i < Info.ActionCount_EndOfPlayhead)
Info.ActionOffset_EndOfPlayhead += Size;
@@ -202,6 +206,9 @@ void History_Entry_Commit(memory *Memory, char *Name)
history_entry *Entry = &History->Entry[History->EntryPlayhead];
Entry->Name = Name;
Entry->NumberOfActions = 0;
+ if (History->NumberOfEntries > MAX_HISTORY_ENTRIES) {
+ Assert(0);
+ }
// Effectively deletes entries in front if we're beginning out of an undo.
if (History->NumberOfEntries != History->EntryPlayhead)
History->NumberOfEntries = History->EntryPlayhead;
@@ -223,6 +230,42 @@ void History_Entry_End(memory *Memory)
#endif
}
+static void
+History_Purge(memory *Memory, history_entry_list *History, uint64 ActionCount_Total, uint64 ActionOffset_Total, uint64 PurgeSize)
+{
+ int Size = 0;
+ int EntryIndex = 0;
+ int ActionIndex = 0;
+ int ActionCount = 0;
+ while (Size < PurgeSize) {
+ history_entry *Entry = &History->Entry[EntryIndex];
+ ActionCount += Entry->NumberOfActions;
+ while (ActionIndex < ActionCount) {
+ Size += History_GetActionSize(History, ActionIndex);
+ ActionIndex++;
+ }
+ EntryIndex++;
+ }
+ int EntryCount = (EntryIndex + 1);
+ {
+ uint8 *Address_Start = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Size);
+ uint8 *Address_End = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, ActionOffset_Total);
+ Arbitrary_ShiftData(Address_Start, Address_End, Size, -1);
+ }
+ {
+ uint8 *Address_Start = (uint8 *)&History->Entry[EntryCount];
+ uint8 *Address_End = (uint8 *)&History->Entry[History->NumberOfEntries];
+ Arbitrary_ShiftData(Address_Start, Address_End, sizeof(history_entry) * EntryCount, -1);
+ }
+ {
+ uint8 *Address_Start = (uint8 *)&History->Action[ActionCount];
+ uint8 *Address_End = (uint8 *)&History->Action[ActionCount_Total];
+ Arbitrary_ShiftData(Address_Start, Address_End, sizeof(history_action) * ActionCount, -1);
+ }
+ History->NumberOfEntries -= EntryCount;
+ History->EntryPlayhead -= EntryCount;
+}
+
// NOTE(fox): Shift is the only action that additionally changes the data after
// the info is put on the tree, since it's always the same function used.
@@ -233,6 +276,15 @@ static void History_Action_Add(memory *Memory, history_action ActionData, void *
history_info Info = History_GetTreeInfo(History, History->EntryPlayhead - 1);
+ if ((Info.ActionOffset_EndOfPlayhead + ActionData.Size) > Memory->Slot[P_UndoBuffer].Size) {
+ History_Purge(Memory, History, Info.ActionCount_Total, Info.ActionOffset_Total, ActionData.Size * 4);
+ Entry = &History->Entry[History->EntryPlayhead - 1];
+ Info = History_GetTreeInfo(History, History->EntryPlayhead - 1);
+ }
+ if (Info.ActionCount_Total > MAX_HISTORY_ACTIONS) {
+ Assert(0);
+ }
+
history_action *Action = &History->Action[Info.ActionCount_Total];
*Action = ActionData;