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