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