home · contact · privacy
3ce0e440b2d319af9ff0b81d1040bc468518c10f
[plomrogue] / src / keybindings.c
1 /* keybindings.c */
2
3
4
5 #include "keybindings.h"
6 #include <stdlib.h>  /* for malloc(), free(), atoi() */
7 #include <stdint.h>  /* for uint16_t */
8 #include <ncurses.h> /* for keycode defines in get_keyname() */
9 #include <string.h>  /* for strchr(), strlen(), strcmp(), memcpy()*/
10 #include "windows.h" /* for draw_all_wins() and WinMeta struct */
11 #include "misc.h"    /* for texfile_sizes() */
12 #include "main.h"    /* for World struct */
13 #include "rexit.h"   /* for err_exit() */
14
15
16
17 extern void init_keybindings(struct World * world)
18 {
19     FILE * file = fopen("config/keybindings", "r");
20     uint16_t lines, linemax;
21     char * err = "textfile_sizes() in init_keybindings() returns error.";
22     exit_err(textfile_sizes(file, &linemax, &lines), world, err);
23     struct KeyBinding * keybindings = malloc(lines * sizeof(struct KeyBinding));
24     char * command = malloc(linemax);
25     uint16_t commcount = 0;
26     char * cmdptr;
27     while (fgets(command, linemax, file))
28     {
29         keybindings[commcount].key = atoi(command);
30         cmdptr = strchr(command, ' ') + 1;
31         keybindings[commcount].name = malloc(strlen(cmdptr));
32         memcpy(keybindings[commcount].name, cmdptr, strlen(cmdptr) - 1);
33         keybindings[commcount].name[strlen(cmdptr) - 1] = '\0';
34         commcount++;
35     }
36     free(command);
37     fclose(file);
38     struct KeysWinData * keyswindata = malloc(sizeof(struct KeysWinData));
39     keyswindata->max = lines - 1;
40     keyswindata->select = 0;
41     keyswindata->edit = 0;
42     world->keybindings = keybindings;
43     world->keyswindata = keyswindata;
44 }
45
46
47
48 extern void save_keybindings(struct World * world)
49 {
50     struct KeysWinData * keyswindata = (struct KeysWinData *)
51                                        world->keyswindata;
52     struct KeyBinding * keybindings = world->keybindings;
53     FILE * file = fopen("config/keybindings", "w");
54     uint16_t linemax = 0;
55     uint16_t i;
56     for (i = 0; i <= keyswindata->max; i++)
57     {
58         if (strlen(keybindings[i].name) > linemax)
59         {
60             linemax = strlen(keybindings[i].name);
61         }
62     }
63     linemax = linemax + 6;         /* + 6 = + 3 digits + whitespace + \n + \0 */
64     char * line = malloc(linemax);
65     for (i = 0; i <= keyswindata->max; i++)
66     {
67         snprintf(line, linemax,
68                  "%d %s\n", keybindings[i].key, keybindings[i].name);
69         fwrite(line, sizeof(char), strlen(line), file);
70     }
71     free(line);
72     fclose(file);
73 }
74
75
76
77 extern uint16_t get_action_key(struct KeyBinding * keybindings, char * name)
78 {
79     uint16_t i = 0;
80     while (strcmp(keybindings[i].name, name) )
81     {
82         i++;
83     }
84     return keybindings[i].key;
85 }
86
87
88
89 extern char * get_keyname(uint16_t keycode)
90 {
91     char * keyname;
92     keyname = malloc(15);
93     if (32 < keycode && keycode < 127)
94     {
95         sprintf(keyname, "%c", keycode);
96     }
97     else if (keycode == 9)              /* TODO: Find a way more elegant than */
98     {                                   /*       hardcoding all of this?      */
99         sprintf(keyname, "TAB");
100     }
101     else if (keycode == 10)
102     {
103         sprintf(keyname, "RETURN");
104     }
105     else if (keycode == 27)
106     {
107         sprintf(keyname, "ESCAPE");
108     }
109     else if (keycode == 32)
110     {
111         sprintf(keyname, "SPACE");
112     }
113     else if (keycode == KEY_UP)
114     {
115         sprintf(keyname, "UP");
116     }
117     else if (keycode == KEY_DOWN)
118     {
119         sprintf(keyname, "DOWN");
120     }
121     else if (keycode == KEY_LEFT)
122     {
123         sprintf(keyname, "LEFT");
124     }
125     else if (keycode == KEY_RIGHT)
126     {
127         sprintf(keyname, "RIGHT");
128     }
129     else if (keycode == KEY_HOME)
130     {
131         sprintf(keyname, "HOME");
132     }
133     else if (keycode == KEY_BACKSPACE)
134     {
135         sprintf(keyname, "BACKSPACE");
136     }
137     else if (keycode >= KEY_F0 && keycode <= KEY_F(63))
138     {
139         uint16_t f = keycode - KEY_F0;
140         sprintf(keyname, "F%d", f);
141     }
142     else if (keycode == KEY_DC)
143     {
144         sprintf(keyname, "DELETE");
145     }
146     else if (keycode == KEY_IC)
147     {
148         sprintf(keyname, "INSERT");
149     }
150     else if (keycode == KEY_NPAGE)
151     {
152         sprintf(keyname, "NEXT PAGE");
153     }
154     else if (keycode == KEY_PPAGE)
155     {
156         sprintf(keyname, "PREV PAGE");
157     }
158     else if (keycode == KEY_END)
159     {
160         sprintf(keyname, "END");
161     }
162     else
163     {
164         sprintf(keyname, "(unknown)");
165     }
166     return keyname;
167 }
168
169
170
171 extern void keyswin_mod_key(struct World * world, struct WinMeta * win_meta)
172 {
173     world->keyswindata->edit = 1;
174     exit_err(draw_all_wins(win_meta), world, "Trouble with draw_all_wins() in "
175                                              "keyswin_mod_key().");
176     int key = getch();
177     if (key < 1000)
178     {
179         world->keybindings[world->keyswindata->select].key = key;
180     }
181     world->keyswindata->edit = 0;
182 }
183
184
185
186 extern void keyswin_move_selection(struct World * world, char dir)
187 {
188     if      ('u' == dir && world->keyswindata->select > 0)
189     {
190         world->keyswindata->select--;
191     }
192     else if ('d' == dir && world->keyswindata->select < world->keyswindata->max)
193     {
194         world->keyswindata->select++;
195     }
196 }