aboutsummaryrefslogtreecommitdiffhomepage
path: root/undo.h
blob: a32d02a186d83085741fdca566749ab49b6e73a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef __UNDO_H
#define __UNDO_H

#include <bsd/sys/queue.h>

#include <glib.h>
#include <glib/gprintf.h>

#include <Scintilla.h>

#ifdef DEBUG
#include "parser.h"
#endif

class UndoToken {
public:
	SLIST_ENTRY(UndoToken) tokens;

	gint pos;

	virtual void run() = 0;
};

class UndoTokenMessage : public UndoToken {
	unsigned int iMessage;
	uptr_t wParam;
	sptr_t lParam;

public:
	UndoTokenMessage(unsigned int _iMessage,
			 uptr_t _wParam = 0, sptr_t _lParam = 0)
			: UndoToken(), iMessage(_iMessage),
			  wParam(_wParam), lParam(_lParam) {}

	void run(void);
};

template <typename Type>
class UndoTokenVariable : public UndoToken {
	Type *ptr;
	Type value;

public:
	UndoTokenVariable(Type &variable, Type _value)
			 : UndoToken(), ptr(&variable), value(_value) {}

	void
	run(void)
	{
#ifdef DEBUG
		if ((State **)ptr == &States::current)
			g_printf("undo state -> %p\n", (void *)value);
#endif
		*ptr = value;
	}
};

class UndoTokenString : public UndoToken {
	gchar **ptr;
	gchar *str;

public:
	UndoTokenString(gchar *&variable, gchar *_str)
		       : UndoToken(), ptr(&variable)
	{
		str = _str ? g_strdup(_str) : NULL;
	}

	~UndoTokenString()
	{
		g_free(str);
	}

	void
	run(void)
	{
		g_free(*ptr);
		*ptr = str;
		str = NULL;
	}
};

extern class UndoStack {
	SLIST_HEAD(Head, UndoToken) head;

public:
	bool enabled;

	UndoStack(bool _enabled = false) : enabled(_enabled)
	{
		SLIST_INIT(&head);
	}
	~UndoStack();

	void push(UndoToken *token);

	void push_msg(unsigned int iMessage,
		      uptr_t wParam = 0, sptr_t lParam = 0);

	template <typename Type>
	inline void
	push_var(Type &variable, Type value)
	{
		push(new UndoTokenVariable<Type>(variable, value));
	}

	template <typename Type>
	inline void
	push_var(Type &variable)
	{
		push_var<Type>(variable, variable);
	}

	inline void
	push_str(gchar *&variable, gchar *str)
	{
		push(new UndoTokenString(variable, str));
	}
	inline void
	push_str(gchar *&variable)
	{
		push_str(variable, variable);
	}

	void pop(gint pos);

	void clear(void);
} undo;

#endif