Skip to content

Instantly share code, notes, and snippets.

@anael-seghezzi
Created September 28, 2022 12:04
Show Gist options
  • Save anael-seghezzi/52cc1f6f5f43e02e74bf9d08f0f6c48f to your computer and use it in GitHub Desktop.
Save anael-seghezzi/52cc1f6f5f43e02e74bf9d08f0f6c48f to your computer and use it in GitHub Desktop.
#ifndef M_ACTION_MAX
#define M_ACTION_MAX 256
#endif
struct m_action;
typedef void (*m_action_fun)(void *);
struct m_action
{
m_action_fun fun_do;
m_action_fun fun_undo;
m_action_fun fun_del;
void *user;
};
struct m_action_hystory
{
struct m_action *action;
int step;
};
void m_action_do(struct m_action *action)
{
if (action->fun_do) action->fun_do(action->user);
}
void m_action_undo(struct m_action *action)
{
if (action->fun_undo) action->fun_undo(action->user);
}
void m_action_free_user(struct m_action *action)
{
if (action->user) free(action->user);
}
void m_action_del(struct m_action *action)
{
if (action->fun_del) action->fun_del(action->user);
m_action_free_user(action);
}
void m_action_hystory_clean(struct m_action_hystory *dest)
{
int i, count = arrlen(dest->action);
if (count > dest->step) { // only delete potential redos (others still in use)
for (i = dest->step; i < count; i++)
m_action_del(&dest->action[i]);
arrdeln(dest->action, dest->step, count - dest->step);
}
}
void m_action_hystory_destroy(struct m_action_hystory *dest)
{
int i;
for (i = 0; i < dest->step; i++)
m_action_free_user(&dest->action[i]); // only free action user (internal data still in use)
m_action_hystory_clean(dest);
arrfree(dest->action);
dest->step = 0;
}
void m_action_hystory_add(struct m_action_hystory *dest, struct m_action *action)
{
m_action_hystory_clean(dest);
if (arrlen(dest->action) == M_ACTION_MAX) {
m_action_free_user(&dest->action[0]); // only free user (internal data still in use)
arrdel(dest->action, 0);
}
arrpush(dest->action, *action);
dest->step = arrlen(dest->action);
}
void m_action_hystory_undo(struct m_action_hystory *dest)
{
if (dest->step > 0) {
dest->step--;
m_action_undo(&dest->action[dest->step]);
}
}
void m_action_hystory_redo(struct m_action_hystory *dest)
{
if (dest->step < arrlen(dest->action)) {
m_action_do(&dest->action[dest->step]);
dest->step++;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment