home · contact · privacy
Moved keybindings manipulation stuff into its own library.
[plomrogue] / keybindings.c
1 #include <ncurses.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include "windows.h"
5 #include "roguelike.h"
6 #include "keybindings.h"
7
8 void init_keybindings(struct World * world) {
9 // Initialize keybindings from file "keybindings".
10   FILE * file = fopen("keybindings", "r");
11   int lines = 0;
12   int c = 0;
13   int linemax = 0;
14   int c_count = 0;
15   while (EOF != c) {
16     c_count++;
17     c = getc(file);
18     if ('\n' == c) {
19       if (c_count > linemax)
20         linemax = c_count + 1;
21       c_count = 0;
22       lines++; } }
23   struct KeyBinding * keybindings = malloc(lines * sizeof(struct KeyBinding));
24   fseek(file, 0, SEEK_SET);
25   char * command = malloc(linemax);
26   int commcount = 0;
27   char * cmdptr;
28   while (fgets(command, linemax, file)) {
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   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 void save_keybindings(struct World * world) {
45 // Write keybindings to keybindings file.
46   struct KeysWinData * keyswindata = (struct KeysWinData *) world->keyswindata;
47   struct KeyBinding * keybindings = world->keybindings;
48   FILE * file = fopen("keybindings", "w");
49   int linemax = 0;
50   int i;
51   for (i = 0; i <= keyswindata->max; i++)
52     if (strlen(keybindings[i].name) > linemax)
53       linemax = strlen(keybindings[i].name);
54   linemax = linemax + 6;                                // + 6 = + 3 digits + whitespace + newline + null byte
55   char * line = malloc(linemax);
56   for (i = 0; i <= keyswindata->max; i++) {
57     snprintf(line, linemax, "%d %s\n", keybindings[i].key, keybindings[i].name);
58     fwrite(line, sizeof(char), strlen(line), file); }
59   free(line);
60   fclose(file); }
61
62 int get_action_key (struct KeyBinding * keybindings, char * name) {
63 // Return key matching name in keybindings.
64   int i = 0;
65   while (strcmp(keybindings[i].name, name) )
66     i++;
67   return keybindings[i].key; }
68
69 char * get_keyname(int keycode) {
70 // Translate some keycodes to readable names of max 9 chars.
71   char * keyname;
72   keyname = malloc(15);
73   if (32 < keycode && keycode < 127)
74     sprintf(keyname, "%c", keycode);
75   else if (keycode == 9)
76     sprintf(keyname, "TAB");
77   else if (keycode == 10)
78     sprintf(keyname, "RETURN");
79   else if (keycode == 27)
80     sprintf(keyname, "ESCAPE");
81   else if (keycode == 32)
82     sprintf(keyname, "SPACE");
83   else if (keycode == KEY_UP)
84     sprintf(keyname, "UP");
85   else if (keycode == KEY_DOWN)
86     sprintf(keyname, "DOWN");
87   else if (keycode == KEY_LEFT)
88     sprintf(keyname, "LEFT");
89   else if (keycode == KEY_RIGHT)
90     sprintf(keyname, "RIGHT");
91   else if (keycode == KEY_HOME)
92     sprintf(keyname, "HOME");
93   else if (keycode == KEY_BACKSPACE)
94     sprintf(keyname, "BACKSPACE");
95   else if (keycode >= KEY_F0 && keycode <= KEY_F(63)) {
96     int f = keycode - KEY_F0;
97     sprintf(keyname, "F%d", f); }
98   else if (keycode == KEY_DC)
99     sprintf(keyname, "DELETE");
100   else if (keycode == KEY_IC)
101     sprintf(keyname, "INSERT");
102   else if (keycode == KEY_NPAGE)
103     sprintf(keyname, "NEXT PAGE");
104   else if (keycode == KEY_PPAGE)
105     sprintf(keyname, "PREV PAGE");
106   else if (keycode == KEY_END)
107     sprintf(keyname, "END");
108   else
109     sprintf(keyname, "(unknown)");
110   return keyname;  }
111
112 void keyswin_mod_key (struct World * world, struct WinMeta * win_meta) {
113 // In keybindings window, mark selection modifiable, modify key. Ensure max of three digits in key code field.
114   world->keyswindata->edit = 1;
115   draw_all_windows (win_meta);
116   int key = getch();
117   if (key < 1000)
118     world->keybindings[world->keyswindata->select].key = key;
119   world->keyswindata->edit = 0; }
120
121 void keyswin_move_selection (struct World * world, char dir) {
122 // In keybindings window, move selection upwards or downwards (if within limits of list length).
123   if ('u' == dir && world->keyswindata->select > 0)
124     world->keyswindata->select--;
125   else if ('d' == dir && world->keyswindata->select < world->keyswindata->max)
126     world->keyswindata->select++; }