From ee5f1b4cf2b82af47cc55af1334c866bf14945fa Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Fri, 24 Oct 2014 22:59:24 +0200
Subject: Rewrite to use libuv
Also instead of resize_term() we use resizeterm() because the former
seems to cause massive glitches. Not flicker-free in urxvt anymore
though.
---
autistdraw.c | 158 ++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 96 insertions(+), 62 deletions(-)
(limited to 'autistdraw.c')
diff --git a/autistdraw.c b/autistdraw.c
index f7c52de..4f1b6e4 100644
--- a/autistdraw.c
+++ b/autistdraw.c
@@ -17,8 +17,6 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
-// might need this for sigset_t
-#define _XOPEN_SOURCE 600
#include
#include
@@ -27,9 +25,9 @@
#include
#include
-#include
#include
+#include
#include
#include "termo.h"
@@ -45,6 +43,11 @@ struct app_context
{
termo_t *tk; ///< Termo instance
+ uv_tty_t tty; ///< TTY
+ uv_poll_t tty_watcher; ///< TTY input watcher
+ uv_timer_t tty_timer; ///< TTY timeout timer
+ uv_signal_t winch_watcher; ///< SIGWINCH watcher
+
chtype palette[2 * 9]; ///< Attribute palette
uint8_t *bitmap; ///< Canvas data for drawing
@@ -74,7 +77,14 @@ app_init (app_context_t *self)
memset (self, 0, sizeof *self);
}
-static int g_winch_pipe[2];
+static void
+app_free (app_context_t *self)
+{
+ if (self->tk)
+ termo_destroy (self->tk);
+
+ free (self->bitmap);
+}
static void
display (const char *format, ...)
@@ -526,11 +536,74 @@ on_key (app_context_t *app, termo_key_t *key)
return true;
}
+static bool
+xstrtoul (unsigned long *out, const char *s, int base)
+{
+ char *end;
+ errno = 0;
+ *out = strtoul (s, &end, base);
+ return errno == 0 && !*end && end != s;
+}
+
static void
-winch_handler (int signum)
+on_winch (uv_signal_t *handle, int signum)
{
+ app_context_t *app = handle->loop->data;
(void) signum;
- write (g_winch_pipe[1], "x", 1);
+
+#ifdef HAVE_RESIZETERM
+ int w, h;
+ if (!uv_tty_get_winsize (&app->tty, &w, &h))
+ {
+ char *row = getenv ("LINES");
+ char *col = getenv ("COLUMNS");
+ unsigned long tmp;
+ resizeterm (
+ (row && xstrtoul (&tmp, row, 10)) ? (int) tmp : h,
+ (col && xstrtoul (&tmp, col, 10)) ? (int) tmp : w);
+ }
+#else // ! HAVE_RESIZETERM
+ endwin ();
+ refresh ();
+#endif // ! HAVE_RESIZETERM
+
+ update_canvas_for_screen (app);
+ redraw (app);
+ redraw_canvas (app);
+}
+
+static void
+on_key_timer (uv_timer_t *handle)
+{
+ app_context_t *app = handle->loop->data;
+
+ termo_key_t key;
+ if (termo_getkey_force (app->tk, &key) == TERMO_RES_KEY)
+ if (!on_key (app, &key))
+ uv_stop (handle->loop);
+}
+
+static void
+on_tty_readable (uv_poll_t *handle, int status, int events)
+{
+ // Ignoring and hoping for the best
+ (void) status;
+ (void) events;
+
+ app_context_t *app = handle->loop->data;
+
+ uv_timer_stop (&app->tty_timer);
+ termo_advisereadable (app->tk);
+
+ termo_key_t key;
+ termo_result_t ret;
+ while ((ret = termo_getkey (app->tk, &key)) == TERMO_RES_KEY)
+ if (!on_key (app, &key))
+ uv_stop (handle->loop);
+
+ if (ret == TERMO_RES_AGAIN)
+ uv_timer_start (&app->tty_timer,
+ on_key_timer, termo_get_waittime (app->tk), 0);
}
int
@@ -542,18 +615,6 @@ main (int argc, char *argv[])
TERMO_CHECK_VERSION;
setlocale (LC_CTYPE, "");
- struct sigaction act;
- act.sa_handler = winch_handler;
- act.sa_flags = SA_RESTART;
- sigemptyset (&act.sa_mask);
-
- // Set up a self-pipe so that we can actually poll on SIGWINCH
- if (sigaction (SIGWINCH, &act, NULL) || pipe (g_winch_pipe))
- {
- fprintf (stderr, "Cannot set up signal handler\n");
- exit (EXIT_FAILURE);
- }
-
termo_t *tk = termo_new (STDIN_FILENO, NULL, 0);
if (!tk)
{
@@ -575,56 +636,29 @@ main (int argc, char *argv[])
app_init (&app);
app.tk = tk;
- init_palette (&app);
- update_canvas_for_screen (&app);
- redraw (&app);
- redraw_canvas (&app);
-
- termo_result_t ret;
- termo_key_t key;
-
- // We listen for mouse/key input and terminal resize events
- struct pollfd fds[2] =
- {
- { .fd = STDIN_FILENO, .events = POLLIN },
- { .fd = g_winch_pipe[0], .events = POLLIN },
- };
+ uv_loop_t *loop = uv_default_loop ();
+ loop->data = &app;
- // Run a simple event loop with poll()
- int nextwait = -1;
- bool running = true;
- while (running)
- {
- if (!poll (fds, 2, nextwait))
- if (termo_getkey_force (tk, &key) == TERMO_RES_KEY)
- running &= on_key (&app, &key);
-
- if (fds[1].revents & (POLLIN | POLLHUP | POLLERR))
- {
- char x;
- read (fds[1].fd, &x, 1);
+ uv_signal_init (loop, &app.winch_watcher);
+ uv_signal_start (&app.winch_watcher, on_winch, SIGWINCH);
- // The "official" simple and flicker-prone method of resizing
- // the internal buffers of curses
- endwin ();
- refresh ();
+ uv_tty_init (loop, &app.tty, STDOUT_FILENO, false);
- update_canvas_for_screen (&app);
- redraw (&app);
- redraw_canvas (&app);
- }
- if (fds[0].revents & (POLLIN | POLLHUP | POLLERR))
- termo_advisereadable (tk);
+ uv_poll_init (loop, &app.tty_watcher, STDIN_FILENO);
+ uv_poll_start (&app.tty_watcher, UV_READABLE, on_tty_readable);
- while ((ret = termo_getkey (tk, &key)) == TERMO_RES_KEY)
- running &= on_key (&app, &key);
+ uv_timer_init (loop, &app.tty_timer);
- nextwait = -1;
- if (ret == TERMO_RES_AGAIN)
- nextwait = termo_get_waittime (tk);
- }
+ init_palette (&app);
+ update_canvas_for_screen (&app);
+ redraw (&app);
+ redraw_canvas (&app);
+ uv_run (loop, UV_RUN_DEFAULT);
endwin ();
- termo_destroy (tk);
+
+ uv_loop_close (loop);
+ app_free (&app);
+ return 0;
}
--
cgit v1.2.3-54-g00ecf