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