//========================================================================
// E core library
//
// Undo/redo
//
// AUTHOR:  Gabor Nagy
// DATE:    2024-Apr-04 22:22:50
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//========================================================================

#ifndef _EUndo_h
#define _EUndo_h

#ifndef _EClass_h
#include <EClass.h>
#endif

#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif

// Operator codes
//
enum
{
	EOpNONE = 0,
};


// Status Content codes
//
enum
{
	EActionNONE = 0
};


// Function codes for Func() in EOperator
//
enum
{
	EOpDO = 1,
	EOpUNDO
};


typedef struct EOperator_S        EOperator;
typedef struct EOperator_S*       EOperatorPtr;
typedef struct EOperatorClass_S   EOperatorClass;
typedef struct EOperatorClass_S*  EOperatorClassPtr;
EListA_t(EOperatorClassPtr);

EListA_t(EOperatorPtr);

// Operator list
//
typedef struct
{
	char*  Name;
	EListA_s(, EOperatorPtr, Operators);
	EListA_s(, EOpNode, OpNodes);    // Filled in by the Operator->Func()s to indicate what changed
} EOps, *EOpsPtr;
EListA_t(EOpsPtr);


typedef EChangeFlags  (*EOperatorFunc)(EOps* POps, EOperator* POperator, const int PAction);


#define EOperatorCore\
	EObjectCore(EOperator);\
	EChangeFlags  ChangeFlags  /* Instance-specific change flags. E.g. animation curve editing adds E3dChgAnimationSELECTION to E3dOperatorAddDelSplineCVs, to make EQX redraw animation views */

#define EOperatorClassCore\
	EBaseClassCore(EOperator);\
	EOperatorFunc  Func    /* The function that performs the operation  */


struct EOperator_S
{
	EOperatorCore;
};

struct EOperatorClass_S
{
	EOperatorClassCore;
};





typedef struct
{
	int           Ptr;
	int           MaxUndoSteps;
	EChangeFlags  Changed;    // Flags indicating what changed
	EListA_s(, EOpsPtr, Steps);
} EUndoStack;



extern int		EOp_AllocStep;


extern EOperator*       EOperator_New(EOperatorClass* PClass);

extern EOperatorClass*  EOperatorClass_ByName(const char* PName);
extern EOperatorClass*  EOperator_ClassRegister(EOperatorClass* PClassDescriptor);
extern void             EOperator_ClassDeactivate(EOperatorClass* PClass);
extern void             EOperator_ClassesFree(void);


extern void      EUndoStack_AddOps(EUndoStack* PStack, EOps* POps, const char* PName);

extern void      EOps_Init(EOps* POps);
extern void      EOps_Free(EOps* POps);
extern void      EOps_FreeContents(EOps* POps);
extern void      EOps_Clear(EOps* POps);

extern uint32_t  EOps_Run(EOps* POps, const int PAction);

extern void      EUndoStack_Init(EUndoStack* PUndoStack, const EIndex PMaxSteps);
extern void      EUndoStack_Free(EUndoStack* PUndoStack);
extern void      EUndoStack_OperatorAppend(EUndoStack* PUndoStack, EOperator* POperator, const char* PName);

extern EOps*     EUndoStack_Undo(EUndoStack* PStack);
extern EOps*     EUndoStack_Redo(EUndoStack* PStack);


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif

#endif	// _EUndo_h
