tests/interactive-ascii: add cooked.c, test of curses ICANON emul
authorMatthew Mondor <mmondor@pulsar-zone.net>
Sat, 8 Apr 2023 02:34:44 +0000 (02:34 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Sat, 8 Apr 2023 02:34:44 +0000 (02:34 +0000)
tests/interactive-ascii/cooked.c [new file with mode: 0644]

diff --git a/tests/interactive-ascii/cooked.c b/tests/interactive-ascii/cooked.c
new file mode 100644 (file)
index 0000000..3d64c44
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2023, Matthew Mondor
+ * ALL RIGHTS RESERVED.
+ *
+ * Test using curses(3)'s own cooked input mode that interprets some special
+ * characters similarly to native tty(4) cooked modes.  This can be different
+ * because curses simulates it, providing its own, when echo is enabled and
+ * multiple-character input happens.
+ * 
+ * $ cc -Wall -O0 -g -o cooked cooked.c -lcurses
+ */
+
+#include <curses.h>
+#include <err.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+
+int                    main(void);
+static void            cleanup(void);
+
+
+/* To explicitly save/restore tty(4) state despite curses(3) */
+static struct termios  old_tios;
+
+/* Curses window */
+static WINDOW          *w = NULL;
+
+
+int
+main(void)
+{
+
+       /* Setup curses */
+       (void)tcgetattr(STDIN_FILENO, &old_tios);
+       if ((w = initscr()) == NULL)
+               err(EXIT_FAILURE, "initscr()");
+
+       /* Exit cleanup hook to restore normal terminal */
+       (void)atexit(cleanup);
+
+       /* Typical mode */
+       (void)cbreak();
+       (void)nonl();
+       (void)keypad(w, TRUE);
+       (void)intrflush(stdscr, FALSE);
+       (void)timeout(-1);
+
+       /* Curses "ICANON" mode */
+       (void)curs_set(1);
+       (void)intrflush(stdscr, FALSE);
+       (void)nl();
+       (void)echo();
+       (void)scrollok(stdscr, TRUE);
+       (void)leaveok(w, FALSE);
+       (void)intrflush(w, TRUE);
+       (void)move(10, 10);
+       (void)refresh(); /* doupdate() does not update cursor pos */
+
+       for (;;) {
+               char str[1024];
+
+               if (getnstr(str, 1023) != OK)
+                       err(EXIT_FAILURE, "getnstr()");
+               (void)printw("%s\n", str);
+               (void)refresh();
+               if (strcasecmp(str, "quit") == 0) {
+                       (void)printw("Bye!\n");
+                       (void)refresh();
+                       break;
+               }
+       }
+
+       exit(EXIT_SUCCESS);
+}
+
+static void
+cleanup(void)
+{
+
+       (void)curs_set(1);
+       (void)endwin();
+       (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_tios);
+}