summaryrefslogtreecommitdiff
path: root/src/hotkeys.h
blob: 79740f3d466d9bc29b7505110b9de826e2e87708 (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
132
133
134
135
/* $Id$ */

/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 */

/** @file hotkeys.h Hotkey related functions. */

#ifndef HOTKEYS_H
#define HOTKEYS_H

#include "core/smallvec_type.hpp"
#include "gfx_type.h"

/**
 * All data for a single hotkey. The name (for saving/loading a configfile),
 * a list of keycodes and a number to help identifying this hotkey.
 */
template<class T>
struct Hotkey {
	typedef void (T::*hotkey_callback)(int);

	/**
	 * A wrapper around the callback function. This wrapper is needed because
	 * the size of a pointer to a member function depends on the class
	 * definition. The possible solutions are to either wrap the callback
	 * pointer in a class and dynamically allocate memory for it like we do
	 * now or making all class definitions available in hotkeys.cpp.
	 */
	struct CallbackWrapper {
		CallbackWrapper(hotkey_callback callback) :
			callback(callback)
		{}
		hotkey_callback callback;
	};

	/**
	 * Create a new Hotkey object with a single default keycode.
	 * @param default_keycode The default keycode for this hotkey.
	 * @param name The name of this hotkey.
	 * @param num Number of this hotkey, should be unique within the hotkey list.
	 * @param callback The function to call if the hotkey is pressed.
	 */
	Hotkey(uint16 default_keycode, const char *name, int num, hotkey_callback callback = NULL) :
		name(name),
		num(num)
	{
		if (callback == NULL) {
			this->callback = NULL;
		} else {
			this->callback = new CallbackWrapper(callback);
		}
		if (default_keycode != 0) this->AddKeycode(default_keycode);
	}

	/**
	 * Create a new Hotkey object with multiple default keycodes.
	 * @param default_keycodes An array of default keycodes terminated with 0.
	 * @param name The name of this hotkey.
	 * @param num Number of this hotkey, should be unique within the hotkey list.
	 * @param callback The function to call if the hotkey is pressed.
	 */
	Hotkey(const uint16 *default_keycodes, const char *name, int num, hotkey_callback callback = NULL) :
		name(name),
		num(num)
	{
		if (callback == NULL) {
			this->callback = NULL;
		} else {
			this->callback = new CallbackWrapper(callback);
		}

		const uint16 *keycode = default_keycodes;
		while (*keycode != 0) {
			this->AddKeycode(*keycode);
			keycode++;
		}
	}

	~Hotkey()
	{
		delete this->callback;
	}

	/**
	 * Add a keycode to this hotkey, from now that keycode will be matched
	 * in addition to any previously added keycodes.
	 * @param keycode The keycode to add.
	 */
	void AddKeycode(uint16 keycode)
	{
		this->keycodes.Include(keycode);
	}

	const char *name;
	int num;
	SmallVector<uint16, 1> keycodes;
	CallbackWrapper *callback;
};

#define HOTKEY_LIST_END(window_class) Hotkey<window_class>((uint16)0, NULL, -1)

/**
 * Check if a keycode is bound to something.
 * @param list The list with hotkeys to check
 * @param keycode The keycode that was pressed
 * @param w The window-pointer to give to the callback function (if any).
 * @param global_only Limit the search to hotkeys defined as 'global'.
 * @return The number of the matching hotkey or -1.
 */
template<class T>
int CheckHotkeyMatch(Hotkey<T> *list, uint16 keycode, T *w, bool global_only = false)
{
	while (list->num != -1) {
		if (list->keycodes.Contains(keycode | WKC_GLOBAL_HOTKEY) || (!global_only && list->keycodes.Contains(keycode))) {
			if (!global_only && list->callback != NULL) (w->*(list->callback->callback))(-1);
			return list->num;
		}
		list++;
	}
	return -1;
}

bool IsQuitKey(uint16 keycode);

void LoadHotkeysFromConfig();
void SaveHotkeysToConfig();


void HandleGlobalHotkeys(uint16 key, uint16 keycode);

#endif /* HOTKEYS_H */