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