aboutsummaryrefslogtreecommitdiffstats
path: root/kbd.c
blob: d5f01917d4b5535a529c6e4d48e14faf9c98fbbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#include <time.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <termios.h>

#include "kbd.h"

/* ---------------------------------------------------------------------- */

struct termctrl {
    const char *seq;
    uint32_t code;
    uint32_t mod;
};

static struct termctrl termctrl[] = {
    { .seq = "a", .code = KEY_A },
    { .seq = "b", .code = KEY_B },
    { .seq = "c", .code = KEY_C },
    { .seq = "d", .code = KEY_D },
    { .seq = "e", .code = KEY_E },
    { .seq = "f", .code = KEY_F },
    { .seq = "g", .code = KEY_G },
    { .seq = "h", .code = KEY_H },
    { .seq = "i", .code = KEY_I },
    { .seq = "j", .code = KEY_J },
    { .seq = "k", .code = KEY_K },
    { .seq = "l", .code = KEY_L },
    { .seq = "m", .code = KEY_M },
    { .seq = "n", .code = KEY_N },
    { .seq = "o", .code = KEY_O },
    { .seq = "p", .code = KEY_P },
    { .seq = "q", .code = KEY_Q },
    { .seq = "r", .code = KEY_R },
    { .seq = "s", .code = KEY_S },
    { .seq = "t", .code = KEY_T },
    { .seq = "u", .code = KEY_U },
    { .seq = "v", .code = KEY_V },
    { .seq = "w", .code = KEY_W },
    { .seq = "x", .code = KEY_X },
    { .seq = "y", .code = KEY_Y },
    { .seq = "z", .code = KEY_Z },

    { .seq = "A", .code = KEY_A, .mod = KEY_MOD_SHIFT },
    { .seq = "B", .code = KEY_B, .mod = KEY_MOD_SHIFT },
    { .seq = "C", .code = KEY_C, .mod = KEY_MOD_SHIFT },
    { .seq = "D", .code = KEY_D, .mod = KEY_MOD_SHIFT },
    { .seq = "E", .code = KEY_E, .mod = KEY_MOD_SHIFT },
    { .seq = "F", .code = KEY_F, .mod = KEY_MOD_SHIFT },
    { .seq = "G", .code = KEY_G, .mod = KEY_MOD_SHIFT },
    { .seq = "H", .code = KEY_H, .mod = KEY_MOD_SHIFT },
    { .seq = "I", .code = KEY_I, .mod = KEY_MOD_SHIFT },
    { .seq = "J", .code = KEY_J, .mod = KEY_MOD_SHIFT },
    { .seq = "K", .code = KEY_K, .mod = KEY_MOD_SHIFT },
    { .seq = "L", .code = KEY_L, .mod = KEY_MOD_SHIFT },
    { .seq = "M", .code = KEY_M, .mod = KEY_MOD_SHIFT },
    { .seq = "N", .code = KEY_N, .mod = KEY_MOD_SHIFT },
    { .seq = "O", .code = KEY_O, .mod = KEY_MOD_SHIFT },
    { .seq = "P", .code = KEY_P, .mod = KEY_MOD_SHIFT },
    { .seq = "Q", .code = KEY_Q, .mod = KEY_MOD_SHIFT },
    { .seq = "R", .code = KEY_R, .mod = KEY_MOD_SHIFT },
    { .seq = "S", .code = KEY_S, .mod = KEY_MOD_SHIFT },
    { .seq = "T", .code = KEY_T, .mod = KEY_MOD_SHIFT },
    { .seq = "U", .code = KEY_U, .mod = KEY_MOD_SHIFT },
    { .seq = "V", .code = KEY_V, .mod = KEY_MOD_SHIFT },
    { .seq = "W", .code = KEY_W, .mod = KEY_MOD_SHIFT },
    { .seq = "X", .code = KEY_X, .mod = KEY_MOD_SHIFT },
    { .seq = "Y", .code = KEY_Y, .mod = KEY_MOD_SHIFT },
    { .seq = "Z", .code = KEY_Z, .mod = KEY_MOD_SHIFT },

    { .seq = "0", .code = KEY_0, },
    { .seq = "1", .code = KEY_1, },
    { .seq = "2", .code = KEY_2, },
    { .seq = "3", .code = KEY_3, },
    { .seq = "4", .code = KEY_4, },
    { .seq = "5", .code = KEY_5, },
    { .seq = "6", .code = KEY_6, },
    { .seq = "7", .code = KEY_7, },
    { .seq = "8", .code = KEY_8, },
    { .seq = "9", .code = KEY_9, },

    { .seq = "\x1b[A",    .code = KEY_UP       },
    { .seq = "\x1b[B",    .code = KEY_DOWN     },
    { .seq = "\x1b[C",    .code = KEY_RIGHT    },
    { .seq = "\x1b[D",    .code = KEY_LEFT     },
    { .seq = "\x1b[F",    .code = KEY_END      },
    { .seq = "\x1b[H",    .code = KEY_HOME     },

    { .seq = "\x1b[1~",   .code = KEY_HOME     },
    { .seq = "\x1b[2~",   .code = KEY_INSERT   },
    { .seq = "\x1b[3~",   .code = KEY_DELETE   },
    { .seq = "\x1b[4~",   .code = KEY_END      },
    { .seq = "\x1b[5~",   .code = KEY_PAGEUP   },
    { .seq = "\x1b[6~",   .code = KEY_PAGEDOWN },

    { .seq = "\x01", .code = KEY_A, .mod = KEY_MOD_CTRL },
    { .seq = "\x02", .code = KEY_B, .mod = KEY_MOD_CTRL },
    { .seq = "\x03", .code = KEY_C, .mod = KEY_MOD_CTRL },
    { .seq = "\x04", .code = KEY_D, .mod = KEY_MOD_CTRL },
    { .seq = "\x05", .code = KEY_E, .mod = KEY_MOD_CTRL },
    { .seq = "\x06", .code = KEY_F, .mod = KEY_MOD_CTRL },
    { .seq = "\x07", .code = KEY_G, .mod = KEY_MOD_CTRL },
    { .seq = "\x08", .code = KEY_H, .mod = KEY_MOD_CTRL },
    { .seq = "\x09", .code = KEY_I, .mod = KEY_MOD_CTRL },
    { .seq = "\x0a", .code = KEY_J, .mod = KEY_MOD_CTRL },
    { .seq = "\x0b", .code = KEY_K, .mod = KEY_MOD_CTRL },
    { .seq = "\x0c", .code = KEY_L, .mod = KEY_MOD_CTRL },
    { .seq = "\x0d", .code = KEY_M, .mod = KEY_MOD_CTRL },
    { .seq = "\x0e", .code = KEY_N, .mod = KEY_MOD_CTRL },
    { .seq = "\x0f", .code = KEY_O, .mod = KEY_MOD_CTRL },
    { .seq = "\x10", .code = KEY_P, .mod = KEY_MOD_CTRL },
    { .seq = "\x11", .code = KEY_Q, .mod = KEY_MOD_CTRL },
    { .seq = "\x12", .code = KEY_R, .mod = KEY_MOD_CTRL },
    { .seq = "\x13", .code = KEY_S, .mod = KEY_MOD_CTRL },
    { .seq = "\x14", .code = KEY_T, .mod = KEY_MOD_CTRL },
    { .seq = "\x15", .code = KEY_U, .mod = KEY_MOD_CTRL },
    { .seq = "\x16", .code = KEY_V, .mod = KEY_MOD_CTRL },
    { .seq = "\x17", .code = KEY_W, .mod = KEY_MOD_CTRL },
    { .seq = "\x18", .code = KEY_X, .mod = KEY_MOD_CTRL },
    { .seq = "\x19", .code = KEY_Y, .mod = KEY_MOD_CTRL },
    { .seq = "\x1a", .code = KEY_Z, .mod = KEY_MOD_CTRL },
    { .seq = "\x1b", .code = KEY_ESC },

    { /* EOF */ }
};

uint32_t kbd_parse(const char *key, uint32_t *mod)
{
    int i;

    for (i = 0; termctrl[i].seq != NULL; i++) {
        if (strcmp(key, termctrl[i].seq) == 0) {
            *mod = termctrl[i].mod;
            return termctrl[i].code;
        }
    }
    *mod = 0;
    return KEY_RESERVED;
}

/* ---------------------------------------------------------------------- */

struct termios  saved_attributes;
int             saved_fl;

void tty_raw(void)
{
    struct termios tattr;

    fcntl(STDIN_FILENO, F_GETFL, &saved_fl);
    tcgetattr (0, &saved_attributes);

    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
    memcpy(&tattr,&saved_attributes,sizeof(struct termios));
    tattr.c_lflag &= ~(ICANON|ECHO);
    tattr.c_cc[VMIN] = 1;
    tattr.c_cc[VTIME] = 0;
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &tattr);
}

void tty_restore(void)
{
    fcntl(STDIN_FILENO, F_SETFL, saved_fl);
    tcsetattr(STDIN_FILENO, TCSANOW, &saved_attributes);
}