home · contact · privacy
Client: reload_interface_conf() calls map_center() to re-focus map on player.
[plomrogue] / src / client / keybindings.c
1 /* src/client/keybindings.c */
2
3 #include "keybindings.h"
4 #include <ncurses.h> /* keycode defines, cbreak(), halfdelay(), getch() */
5 #include <stddef.h> /* NULL */
6 #include <stdio.h> /* FILE, sprintf(), snprintf() */
7 #include <stdint.h> /* uint8_t, uint16_t, uint32_t */
8 #include <stdlib.h> /* free(), atoi() */
9 #include <string.h> /* strlen(), strchr() */
10 #include "../common/readwrite.h" /* try_fopen(), textfile_sizes(), try_fgets(),
11                                   * try_fclose(), try_fclose_unlink_rename(),
12                                   * try_fwrite()
13                                   */
14 #include "../common/try_malloc.h" /* try_malloc() */
15 #include "wincontrol.h" /* get_winconf_by_win() */
16 #include "windows.h" /* draw_all_wins() */
17 #include "world.h" /* global world */
18
19
20
21 /* Return "n"-th keybinding in keybindings chain from "kb_p" on. */
22 static struct KeyBinding * get_keyb_of_n(struct KeyBinding * kb_p, uint16_t n);
23
24 /* Return number of keybindings in keybindings chain from "kb_p" on. */
25 static uint16_t get_n_of_keybs(struct KeyBinding * kb_p);
26
27 /* Return pointer to global keybindings or to keybindings for wingeometry config
28  * (c = "g") or winkeys config (c = "k") or active window's keybindings ("w").
29  */
30 static struct KeyBindingDB * char_selected_kb_db(char c);
31
32 /* If "keycode_given" equals "keycode_match", copy "keyname_match" to "keyname"
33  * and return 1; otherwise return 0.
34  */
35 static uint8_t try_keycode(uint16_t keycode_given, char * keyname,
36                            uint16_t keycode_match, char * keyname_match);
37
38
39
40 static struct KeyBinding * get_keyb_of_n(struct KeyBinding * kb_p, uint16_t n)
41 {
42     uint16_t i = 0;
43     while (1)
44     {
45         if (n == i)
46         {
47             break;
48         }
49         i++;
50         kb_p = kb_p->next;
51     }
52     return kb_p;
53 }
54
55
56
57 static uint16_t get_n_of_keybs(struct KeyBinding * kb_p)
58 {
59     uint16_t i = 0;
60     while (1)
61     {
62         if (0 == kb_p)
63         {
64             break;
65         }
66         i++;
67         kb_p = kb_p->next;
68     }
69     return i;
70 }
71
72
73
74 static struct KeyBindingDB * char_selected_kb_db(char c)
75 {
76     struct KeyBindingDB * kbd;
77     kbd = &world.kb_global;
78     if      ('g' == c)
79     {
80         kbd = &world.kb_wingeom;
81     }
82     else if ('k' == c)
83     {
84         kbd = &world.kb_winkeys;
85     }
86     else if ('w' == c)
87     {
88         struct WinConf * wc = get_winconf_by_win(world.wmeta.active);
89         kbd = &wc->kb;
90     }
91     return kbd;
92 }
93
94
95
96 static uint8_t try_keycode(uint16_t keycode_given, char * keyname,
97                            uint16_t keycode_match, char * keyname_match)
98 {
99     if (keycode_given == keycode_match)
100     {
101         sprintf(keyname, keyname_match);
102         return 1;
103     }
104     return 0;
105 }
106
107
108
109 extern struct Command * get_command_to_keycode(struct KeyBinding * kb_p,
110                                                uint16_t key)
111 {
112     while (0 != kb_p)
113     {
114         if (key == kb_p->key)
115         {
116             return kb_p->command;
117         }
118         kb_p = kb_p->next;
119     }
120     return NULL;
121 }
122
123
124
125 extern char * get_keyname_to_keycode(uint16_t keycode)
126 {
127     char * f_name = "get_name_to_keycode()";
128     char * keyname = try_malloc(15, f_name);                /* FIXME: Why 15? */
129     if (32 < keycode && keycode < 127)
130     {
131         sprintf(keyname, "%c", keycode);
132     }
133     else if (keycode >= KEY_F0 && keycode <= KEY_F(63))
134     {
135         uint16_t f = keycode - KEY_F0;
136         sprintf(keyname, "F%d", f);
137     }
138     else if (   try_keycode(keycode, keyname, 9, "TAB")
139              || try_keycode(keycode, keyname, 10, "RETURN")
140              || try_keycode(keycode, keyname, 27, "ESCAPE")
141              || try_keycode(keycode, keyname, 32, "SPACE")
142              || try_keycode(keycode, keyname, KEY_UP, "UP")
143              || try_keycode(keycode, keyname, KEY_DOWN, "DOWN")
144              || try_keycode(keycode, keyname, KEY_LEFT, "LEFT")
145              || try_keycode(keycode, keyname, KEY_RIGHT, "RIGHT")
146              || try_keycode(keycode, keyname, KEY_HOME, "HOME")
147              || try_keycode(keycode, keyname, KEY_BACKSPACE, "BACKSPACE")
148              || try_keycode(keycode, keyname, KEY_DC, "DELETE")
149              || try_keycode(keycode, keyname, KEY_IC, "INSERT")
150              || try_keycode(keycode, keyname, KEY_NPAGE, "NEXT PAGE")
151              || try_keycode(keycode, keyname, KEY_PPAGE, "PREV PAGE")
152              || try_keycode(keycode, keyname, KEY_END, "END"))
153     {
154         ;
155     }
156     else
157     {
158         sprintf(keyname, "(unknown)");
159     }
160     return keyname;
161 }
162
163
164
165 extern void init_keybindings(char * path, struct KeyBindingDB * kbd)
166 {
167     char * f_name = "init_keybindings()";
168     FILE * file = try_fopen(path, "r", f_name);
169     uint32_t lines;
170     uint32_t linemax = textfile_sizes(file, &lines);
171     char command[linemax + 1];
172     char * cmdptr;
173     struct KeyBinding ** loc_last_ptr = &kbd->kbs;
174     * loc_last_ptr = 0;
175     while (try_fgets(command, linemax + 1, file, f_name))
176     {
177         if ('\n' == command[0] || 0 == command[0])
178         {
179             break;
180         }
181         * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), f_name);
182         struct KeyBinding * kb_p = * loc_last_ptr;
183         kb_p->next = 0;
184         kb_p->key = atoi(command);
185         cmdptr = strchr(command, ' ') + 1;
186         cmdptr[strlen(cmdptr) - 1] = '\0';
187         kb_p->command = get_command(cmdptr);
188         loc_last_ptr = & kb_p->next;
189     }
190     try_fclose(file, f_name);
191     kbd->edit = 0;
192     kbd->select = 0;
193 }
194
195
196
197 extern void save_keybindings(char * path, struct KeyBindingDB * kbd)
198 {
199     char * f_name = "save_keybindings()";
200     char path_tmp[strlen(path) + 4 + 1];
201     sprintf(path_tmp, "%s_tmp", path);
202     FILE * file = try_fopen(path_tmp, "w", f_name);
203     uint16_t linemax = 0;
204     struct KeyBinding * kb_p = kbd->kbs;
205     while (0 != kb_p)
206     {
207         if (strlen(kb_p->command->dsc_short) > linemax)
208         {
209             linemax = strlen(kb_p->command->dsc_short);
210         }
211         kb_p = kb_p->next;
212     }
213     linemax = linemax + 6;         /* + 6 = + 3 digits + whitespace + \n + \0 */
214     char line[linemax];
215     kb_p = kbd->kbs;
216     while (0 != kb_p)
217     {
218         snprintf(line, linemax, "%d %s\n", kb_p->key, kb_p->command->dsc_short);
219         try_fwrite(line, sizeof(char), strlen(line), file, f_name);
220         kb_p = kb_p->next;
221     }
222     try_fclose_unlink_rename(file, path_tmp, path, f_name);
223 }
224
225
226
227 extern void free_keybindings(struct KeyBinding * kb_start)
228 {
229     if (0 == kb_start)
230     {
231         return;
232     }
233     struct KeyBinding * kb_p = kb_start->next;
234     if (0 != kb_p)
235     {
236         free_keybindings(kb_p);
237     }
238     free(kb_start);
239 }
240
241
242
243 extern void mod_selected_keyb(char kb_c)
244 {
245     struct KeyBindingDB * kbd = char_selected_kb_db(kb_c);
246     kbd->edit = 1;
247     draw_all_wins();
248     cbreak();
249     int key = getch();
250     halfdelay(world.halfdelay);
251     if (key < 1000)
252     {
253         struct KeyBinding * kb_p = get_keyb_of_n(kbd->kbs, kbd->select);
254         kb_p->key = key;
255     }
256     kbd->edit = 0;
257 }
258
259
260
261 extern void move_keyb_selection(char kb_c, char dir)
262 {
263     struct KeyBindingDB * kbd = char_selected_kb_db(kb_c);
264     if      ('u' == dir && kbd->select > 0)
265     {
266         kbd->select--;
267     }
268     else if ('d' == dir && kbd->select < get_n_of_keybs(kbd->kbs) - 1)
269     {
270         kbd->select++;
271     }
272 }