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.
---
CMakeLists.txt | 2 +-
autistdraw.c | 158 +++++++++++++++++++++++++++++++++++----------------------
config.h.in | 2 +-
3 files changed, 98 insertions(+), 64 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08ca44f..214e326 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,7 +43,7 @@ include_directories (${dependencies_INCLUDE_DIRS} ${Termo_INCLUDE_DIRS})
# Configuration
include (CheckFunctionExists)
set (CMAKE_REQUIRED_LIBRARIES ${dependencies_LIBRARIES})
-CHECK_FUNCTION_EXISTS ("resize_term" HAVE_RESIZE_TERM)
+CHECK_FUNCTION_EXISTS ("resizeterm" HAVE_RESIZETERM)
# Project source files
set (project_sources ${PROJECT_NAME}.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;
}
diff --git a/config.h.in b/config.h.in
index 2e0b129..27f026d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -5,7 +5,7 @@
#define PROJECT_VERSION "${project_VERSION}"
#define PROJECT_URL "${project_URL}"
-#cmakedefine HAVE_RESIZE_TERM
+#cmakedefine HAVE_RESIZETERM
#endif // ! CONFIG_H
--
cgit v1.2.3-70-g09d2