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