aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2024-09-22 12:36:34 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2024-09-22 12:47:40 +0200
commit84cc45ebbdcd62a0bad33d65223a45dc146a0f07 (patch)
tree92542e77d61b3c7f30dcb9aa9028b1fa8e9240fb
parent4ca4ba21ccfb6c415462d5a748e7dee5a82121e0 (diff)
downloadsciteco-84cc45ebbdcd62a0bad33d65223a45dc146a0f07.tar.gz
Curses: always wgetch() on a dummy pad, avoiding unnecessary wrefresh()
* This is especially important on platforms, requiring the wgetch() poll workaround to detect CTRL+C (PDCurses/WinGUI). wgetch(cmdline_window) would implicitly wrefresh(cmdline_window), which resulted in additional flickering when pressing function keys. This is no longer so important since key macros are processed as an unity and the cmdline will be updated only after processing all of the characters contained in them, ie. only once after the key press. Still, there could have still been unwanted side effects. At the very least, wgetch(input_pad) should be faster. * The XTerm clipboard implementation was getch()ing on stdscr, so potentially suffered from the same problem. It should be tested again. * Since keypad() is now always enabled even on netbsd-curses. I assume that the function key processing bug in netbsd-curses has been fixed by now. We are not building any releases with netbsd-curses. But it should be retested. * It does not resolve all flickering issues on PDCurses/WinGUI. Both the command line and the Scintilla view still flicker near the cursor. See https://github.com/Bill-Gray/PDCursesMod/issues/322
-rw-r--r--src/interface-curses/interface.c80
1 files changed, 45 insertions, 35 deletions
diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c
index f4b2796..370fc27 100644
--- a/src/interface-curses/interface.c
+++ b/src/interface-curses/interface.c
@@ -347,6 +347,11 @@ static struct {
WINDOW *cmdline_window, *cmdline_pad;
guint cmdline_len, cmdline_rubout_len;
+ /**
+ * Pad used exclusively for wgetch() as it will not
+ * result in unwanted wrefresh().
+ */
+ WINDOW *input_pad;
GQueue *input_queue;
teco_curses_info_popup_t popup;
@@ -697,12 +702,22 @@ teco_interface_init_interactive(GError **error)
curs_set(0);
teco_interface.info_window = newwin(1, 0, 0, 0);
-
teco_interface.msg_window = newwin(1, 0, LINES - 2, 0);
-
teco_interface.cmdline_window = newwin(0, 0, LINES - 1, 0);
- keypad(teco_interface.cmdline_window, TRUE);
- nodelay(teco_interface.cmdline_window, TRUE);
+
+ teco_interface.input_pad = newpad(1, 1);
+ /*
+ * Controlling function key processing is important
+ * on Unix Curses, as ESCAPE is handled as the beginning
+ * of a escape sequence when terminal emulators are
+ * involved.
+ * Still, it's now enabled always since the ESCDELAY
+ * workaround works nicely.
+ * On some Curses variants (XCurses) keypad
+ * must always be TRUE so we receive KEY_RESIZE.
+ */
+ keypad(teco_interface.input_pad, TRUE);
+ nodelay(teco_interface.input_pad, TRUE);
teco_interface.input_queue = g_queue_new();
@@ -746,8 +761,8 @@ teco_interface_restore_batch(void)
* Set window title to a reasonable default,
* in case it is not reset immediately by the
* shell.
- * FIXME: See set_window_title() why this
- * is necessary.
+ * FIXME: See teco_interface_set_window_title()
+ * why this is necessary.
*/
#if defined(CURSES_TTY) && defined(HAVE_TIGETSTR)
teco_interface_set_window_title(g_getenv("TERM") ? : "");
@@ -1328,18 +1343,18 @@ teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError
* to be on the safe side.
*/
halfdelay(1); /* 100ms timeout */
- keypad(stdscr, FALSE);
+ /* don't interpret escape sequences */
+ keypad(teco_interface.input_pad, FALSE);
/*
* Skip "\e]52;x;" (7 characters).
*/
for (gint i = 0; i < 7; i++) {
- if (getch() == ERR) {
+ if (wgetch(teco_interface.input_pad) == ERR) {
/* timeout */
- cbreak();
g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED,
"Timed out reading XTerm clipboard");
- return FALSE;
+ goto error;
}
}
@@ -1355,14 +1370,13 @@ teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError
*/
gchar buffer[MAX(3, 7)];
- gchar c = (gchar)getch();
+ gchar c = (gchar)wgetch(teco_interface.input_pad);
if (c == ERR) {
/* timeout */
- cbreak();
g_string_free(str_base64, TRUE);
g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED,
"Timed out reading XTerm clipboard");
- return FALSE;
+ goto error;
}
if (c == '\a')
break;
@@ -1381,6 +1395,7 @@ teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError
}
cbreak();
+ keypad(teco_interface.input_pad, TRUE);
if (str)
*str = str_base64->str;
@@ -1388,6 +1403,11 @@ teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError
g_string_free(str_base64, !str);
return TRUE;
+
+error:
+ cbreak();
+ keypad(teco_interface.input_pad, TRUE);
+ return FALSE;
}
#else /* !PDCURSES && !CURSES_TTY */
@@ -1497,13 +1517,17 @@ teco_interface_is_interrupted(void)
gboolean
teco_interface_is_interrupted(void)
{
- if (!teco_interface.cmdline_window)
+ if (!teco_interface.input_pad)
/* batch mode */
return teco_interrupted != FALSE;
- /* NOTE: getch() is configured to be nonblocking. */
+ /*
+ * NOTE: wgetch() is configured to be nonblocking.
+ * We wgetch() on a dummy pad, so this does not call any
+ * wrefresh().
+ */
gint key;
- while ((key = wgetch(teco_interface.cmdline_window)) != ERR) {
+ while ((key = wgetch(teco_interface.input_pad)) != ERR) {
if (G_UNLIKELY(key == TECO_CTL_KEY('C')))
return TRUE;
g_queue_push_tail(teco_interface.input_queue,
@@ -1543,35 +1567,19 @@ teco_interface_refresh(void)
static gint
teco_interface_blocking_getch(void)
{
- /*
- * Setting function key processing is important
- * on Unix Curses, as ESCAPE is handled as the beginning
- * of a escape sequence when terminal emulators are
- * involved.
- * On some Curses variants (XCurses) however, keypad
- * must always be TRUE so we receive KEY_RESIZE.
- *
- * FIXME: NetBSD's curses could be handled like ncurses,
- * but gets into an undefined state when SciTECO processes
- * escape sequences.
- */
-#ifdef NCURSES_UNIX
- keypad(teco_interface.cmdline_window, TRUE);
-#endif
-
/* no special <CTRL/C> handling */
raw();
- nodelay(teco_interface.cmdline_window, FALSE);
+ nodelay(teco_interface.input_pad, FALSE);
/*
* Memory limiting is stopped temporarily, since it might otherwise
* constantly place 100% load on the CPU.
*/
teco_memory_stop_limiting();
- gint key = wgetch(teco_interface.cmdline_window);
+ gint key = wgetch(teco_interface.input_pad);
teco_memory_start_limiting();
/* allow asynchronous interruptions on <CTRL/C> */
teco_interrupted = FALSE;
- nodelay(teco_interface.cmdline_window, TRUE);
+ nodelay(teco_interface.input_pad, TRUE);
#if defined(CURSES_TTY) || defined(PDCURSES_WINCON) || defined(NCURSES_WIN32)
noraw(); /* FIXME: necessary because of NCURSES_WIN32 bug */
cbreak();
@@ -1768,6 +1776,8 @@ teco_interface_cleanup(void)
delwin(teco_interface.cmdline_pad);
if (teco_interface.msg_window)
delwin(teco_interface.msg_window);
+ if (teco_interface.input_pad)
+ delwin(teco_interface.input_pad);
/*
* PDCurses/WinCon crashes if initscr() wasn't called.