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