aboutsummaryrefslogtreecommitdiffhomepage
path: root/undo.h
blob: 5b955ab11ab04f29579d8f7ca6ef560299380e20 (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
131
#ifndef __UNDO_H
#define __UNDO_H

#include <bsd/sys/queue.h>

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

#include <Scintilla.h>

class UndoToken {
public:
	SLIST_ENTRY(UndoToken) tokens;

	gint pos;

	UndoToken();

	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)
	{
		*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(undo_head, UndoToken) head;

public:
	bool enabled;

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

	inline void
	push(UndoToken *token)
	{
		if (enabled)
			SLIST_INSERT_HEAD(&head, token, tokens);
		else
			delete 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