commit 00f06c0f2ecfad3c26b8a3e3ea1114908a6dc8d0
Author: Louis Burda <quent.burda@gmail.com>
Date: Mon, 3 Oct 2022 01:49:49 +0200
Initial prototype
Diffstat:
A | .gitignore | | | 1 | + |
A | Makefile | | | 10 | ++++++++++ |
A | lut.c | | | 40 | ++++++++++++++++++++++++++++++++++++++++ |
A | morse.c | | | 121 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 172 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+morse
diff --git a/Makefile b/Makefile
@@ -0,0 +1,10 @@
+LDLIBS = -lX11
+
+all: morse
+
+clean:
+ rm -f morse
+
+morse: morse.c
+
+.PHONY: all clean
diff --git a/lut.c b/lut.c
@@ -0,0 +1,40 @@
+static const char *morse_lut[] = {
+ "A" ".-",
+ "B" "-...",
+ "C" "-.-.",
+ "D" "-..",
+ "E" ".",
+ "F" "..-.",
+ "G" "--.",
+ "H" "....",
+ "I" "..",
+ "J" ".---",
+ "K" "-.-",
+ "L" ".-..",
+ "M" "--",
+ "N" "-.",
+ "O" "---",
+ "P" ".--.",
+ "Q" "--.-",
+ "R" ".-.",
+ "S" "...",
+ "T" "-",
+ "U" "..-",
+ "V" "...-",
+ "W" ".--",
+ "X" "-..-",
+ "Y" "-.--",
+ "Z" "--..",
+ "1" ".----",
+ "2" "..---",
+ "3" "...--",
+ "4" "....-",
+ "5" ".....",
+ "6" "-....",
+ "7" "--...",
+ "8" "---..",
+ "9" "----.",
+ "0" "-----"
+};
+
+
diff --git a/morse.c b/morse.c
@@ -0,0 +1,121 @@
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include <time.h>
+#include <unistd.h>
+#include <time.h>
+#include <err.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "lut.c"
+
+#define ARRLEN(x) (sizeof(x) / sizeof((x)[0]))
+
+static char translate(const char *seq);
+
+static const int long_ms = 300;
+static const int letter_ms = 1000;
+
+static char seqbuf[64];
+static int seqlen;
+
+char
+translate(const char *seq)
+{
+ int i;
+
+ for (i = 0; i < ARRLEN(morse_lut); i++) {
+ if (!strcmp(seq, morse_lut[i] + 1))
+ return morse_lut[i][0];
+ }
+
+ return '?';
+}
+
+int
+main(int argc, const char **argv)
+{
+ struct timespec press, release;
+ unsigned long diff_ms;
+ bool is_pressed;
+ int timeout_cnt;
+ Display *display;
+ XEvent event;
+ Window root;
+ int sleep_cnt;
+ int x11fd;
+ int ret;
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ display = XOpenDisplay(NULL);
+ if (!display) errx(1, "No display found");
+
+ root = DefaultRootWindow(display);
+ XGrabKey(display, XKeysymToKeycode(display, 'n'), 0, root,
+ False, GrabModeAsync, GrabModeAsync);
+
+ memset(&press, 0, sizeof(struct timespec));
+ memset(&release, 0, sizeof(struct timespec));
+
+ seqlen = 0;
+ seqbuf[seqlen] = '\0';
+
+ x11fd = XConnectionNumber(display);
+
+ timeout_cnt = 10;
+ is_pressed = false;
+ while (true) {
+ /* inaccurate and hacky but select()
+ * with XGrabKey is not working */
+ sleep_cnt = 0;
+ while (!XPending(display) && sleep_cnt < letter_ms) {
+ usleep(1000);
+ sleep_cnt++;
+ }
+
+ if (!XPending(display)) {
+ if (!is_pressed) {
+ timeout_cnt++;
+ if (timeout_cnt == 1) {
+ putchar(translate(seqbuf));
+ seqlen = 0;
+ seqbuf[seqlen] = '\0';
+ }
+ if (timeout_cnt == 2)
+ putchar(' ');
+ }
+ continue;
+ } else {
+ timeout_cnt = 0;
+ }
+
+ XNextEvent(display, &event);
+ if (event.type == KeyPress && !is_pressed) {
+ is_pressed = true;
+ if (clock_gettime(CLOCK_REALTIME, &press))
+ err(1, "clock_gettime");
+ } else if (event.type == KeyRelease && is_pressed) {
+ is_pressed = false;
+ if (clock_gettime(CLOCK_REALTIME, &release))
+ err(1, "clock_gettime");
+ if (press.tv_sec == 0) continue;
+ diff_ms = (release.tv_sec - press.tv_sec) * 1000
+ + (release.tv_nsec - press.tv_nsec) / 1000000;
+ if (seqlen >= sizeof(seqbuf) - 1)
+ continue;
+ if (diff_ms > long_ms) {
+ seqbuf[seqlen++] = '-';
+ } else {
+ seqbuf[seqlen++] = '.';
+ }
+ seqbuf[seqlen] = '\0';
+ }
+ }
+
+ XCloseDisplay(display);
+}