1 /**
2 * \file ui-keymap.c
3 * \brief Keymap handling
4 *
5 * Copyright (c) 2011 Andi Sidwell
6 *
7 * This work is free software; you can redistribute it and/or modify it
8 * under the terms of either:
9 *
10 * a) the GNU General Public License as published by the Free Software
11 * Foundation, version 2, or
12 *
13 * b) the "Angband licence":
14 * This software may be copied and distributed for educational, research,
15 * and not for profit purposes provided that this copyright and statement
16 * are included in all such copies. Other copyrights may also apply.
17 */
18 #include "angband.h"
19 #include "ui-keymap.h"
20 #include "ui-term.h"
21
22 /**
23 * Keymap implementation.
24 *
25 * Keymaps are defined in pref files and map onto the internal game keyset,
26 * which is roughly what you get if you have roguelike keys turned off.
27 *
28 * We store keymaps by pairing triggers with actions; the trigger is a single
29 * keypress and the action is stored as a string of keypresses, terminated
30 * with a keypress with type == EVT_NONE.
31 *
32 * XXX We should note when we read in keymaps that are "official game" keymaps
33 * and ones which are user-defined. Then we can avoid writing out official
34 * game ones and messing up everyone's pref files with a load of junk.
35 */
36
37
38 /**
39 * Struct for a keymap.
40 */
41 struct keymap {
42 struct keypress key;
43 struct keypress *actions;
44
45 bool user; /* User-defined keymap */
46
47 struct keymap *next;
48 };
49
50
51 /**
52 * List of keymaps.
53 */
54 static struct keymap *keymaps[KEYMAP_MODE_MAX];
55
56
57 /**
58 * Find a keymap, given a keypress.
59 */
keymap_find(int keymap,struct keypress kc)60 const struct keypress *keymap_find(int keymap, struct keypress kc)
61 {
62 struct keymap *k;
63 assert(keymap >= 0 && keymap < KEYMAP_MODE_MAX);
64 for (k = keymaps[keymap]; k; k = k->next) {
65 if (k->key.code == kc.code && k->key.mods == kc.mods)
66 return k->actions;
67 }
68
69 return NULL;
70 }
71
72
73 /**
74 * Duplicate a given keypress string and return the duplicate.
75 */
keymap_make(const struct keypress * actions)76 static struct keypress *keymap_make(const struct keypress *actions)
77 {
78 struct keypress *new;
79 size_t n = 0;
80 while (actions[n].type) {
81 n++;
82 }
83
84 /* Make room for the terminator */
85 n += 1;
86
87 new = mem_zalloc(sizeof *new * n);
88 memcpy(new, actions, sizeof *new * n);
89
90 new[n - 1].type = EVT_NONE;
91
92 return new;
93 }
94
95
96 /**
97 * Add a keymap to the mappings table.
98 */
keymap_add(int keymap,struct keypress trigger,struct keypress * actions,bool user)99 void keymap_add(int keymap, struct keypress trigger, struct keypress *actions, bool user)
100 {
101 struct keymap *k = mem_zalloc(sizeof *k);
102 assert(keymap >= 0 && keymap < KEYMAP_MODE_MAX);
103
104 keymap_remove(keymap, trigger);
105
106 k->key = trigger;
107 k->actions = keymap_make(actions);
108 k->user = user;
109
110 k->next = keymaps[keymap];
111 keymaps[keymap] = k;
112
113 return;
114 }
115
116
117 /**
118 * Remove a keymap. Return true if one was removed.
119 */
keymap_remove(int keymap,struct keypress trigger)120 bool keymap_remove(int keymap, struct keypress trigger)
121 {
122 struct keymap *k;
123 struct keymap *prev = NULL;
124 assert(keymap >= 0 && keymap < KEYMAP_MODE_MAX);
125
126 for (k = keymaps[keymap]; k; k = k->next) {
127 if (k->key.code == trigger.code && k->key.mods == trigger.mods) {
128 mem_free(k->actions);
129 if (prev)
130 prev->next = k->next;
131 else
132 keymaps[keymap] = k->next;
133 mem_free(k);
134 return true;
135 }
136
137 prev = k;
138 }
139
140 return false;
141 }
142
143
144 /**
145 * Forget and free all keymaps.
146 */
keymap_free(void)147 void keymap_free(void)
148 {
149 size_t i;
150 struct keymap *k;
151 for (i = 0; i < N_ELEMENTS(keymaps); i++) {
152 k = keymaps[i];
153 while (k) {
154 struct keymap *next = k->next;
155 mem_free(k->actions);
156 mem_free(k);
157 k = next;
158 }
159 }
160 }
161
162
163 /**
164 * Append active keymaps to a given file.
165 */
keymap_dump(ang_file * fff)166 void keymap_dump(ang_file *fff)
167 {
168 int mode;
169 struct keymap *k;
170
171 if (OPT(player, rogue_like_commands))
172 mode = KEYMAP_MODE_ROGUE;
173 else
174 mode = KEYMAP_MODE_ORIG;
175
176 for (k = keymaps[mode]; k; k = k->next) {
177 char buf[1024];
178 struct keypress key[2] = { KEYPRESS_NULL, KEYPRESS_NULL };
179
180 if (!k->user) continue;
181
182 /* Encode the action */
183 keypress_to_text(buf, sizeof(buf), k->actions, false);
184 file_putf(fff, "keymap-act:%s\n", buf);
185
186 /* Convert the key into a string */
187 key[0] = k->key;
188 keypress_to_text(buf, sizeof(buf), key, true);
189 file_putf(fff, "keymap-input:%d:%s\n", mode, buf);
190
191 file_putf(fff, "\n");
192 }
193 }
194