Files
dusk/src/input.c
2025-06-08 17:36:13 -05:00

103 lines
2.1 KiB
C

/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "input.h"
#include "util/memory.h"
#include "assert/assert.h"
#include <fcntl.h>
input_t INPUT;
inputmap_t INPUT_MAP[] = {
{"w", INPUT_UP},
{"s", INPUT_DOWN},
{"a", INPUT_LEFT},
{"d", INPUT_RIGHT},
{" ", INPUT_ACTION},
{"e", INPUT_ACTION},
{"\n", INPUT_ACTION}, // Enter key
{"\x1B", INPUT_CANCEL}, // Escape key
{"\033[A", INPUT_UP}, // Up arrow
{"\033[B", INPUT_DOWN}, // Down arrow
{"\033[C", INPUT_RIGHT}, // Right arrow
{"\033[D", INPUT_LEFT}, // Left arrow
{ 0 }
};
void inputEnableRawMode() {
if (INPUT.isRawMode) return;
tcgetattr(STDIN_FILENO, &INPUT.origin);
struct termios raw = INPUT.origin;
raw.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &raw);
INPUT.isRawMode = 1;
}
void inputDisableRawMode() {
if(!INPUT.isRawMode) return;
tcsetattr(STDIN_FILENO, TCSANOW, &INPUT.origin);
INPUT.isRawMode = 0;
}
void inputSetNonBlocking() {
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
}
void inputInit() {
memoryZero(&INPUT, sizeof(input_t));
inputEnableRawMode();
inputSetNonBlocking();
}
void inputUpdate() {
char_t buffer[INPUT_BUFFER_SIZE];
ssize_t n = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
if(n < 0) {
INPUT.previous = INPUT.current;
INPUT.current = 0;
return;
}
assertTrue(n < INPUT_BUFFER_SIZE, "Input buffer overflow");
uint8_t val = 0;
inputmap_t *map;
uint8_t len;
char_t *c;
for(uint8_t i = 0; i < n; i++) {
map = INPUT_MAP;
do {
len = strlen(map->key);
if(i + len > n) {
map++;
continue;
}
c = buffer + i;
if(memoryCompare(c, map->key, len) != 0) {
map++;
continue;
}
// Button was pressed
val |= map->value;
i += len - 1;
} while(map->key);
}
INPUT.previous = INPUT.current;
INPUT.current = val;
}
void inputDispose() {
inputDisableRawMode();
}