aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/interface-curses
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2024-09-23 11:35:15 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2024-09-23 11:45:25 +0200
commitc2887621a37f429e2e05b561631fff01da8bd462 (patch)
tree35ece0d6ab9593bc80d8d307a4c021cc307207b5 /src/interface-curses
parentfbaa927a49694f771d770383bde3e1137fe172d4 (diff)
downloadsciteco-c2887621a37f429e2e05b561631fff01da8bd462.tar.gz
allow OSC-52 clipboards on all terminal emulators
* The XTerm version is still checked if we detect running under XTerm. * Actually, the XTerm implementation is broken for Unicode clipboard contents. * Kitty supports OSC-52, but you __must__ enable read-clipboard. With read-clipboard-ask, there will be a timeout. But we cannot read without a timeout since otherwise we would hang indefinitely if the escape sequence turns out to not work. * For urxvt, I have hacked an existing extension: https://gist.github.com/rhaberkorn/d7406420b69841ebbcab97548e38b37d * st currently supports only setting the clipboard, but not querying it.
Diffstat (limited to 'src/interface-curses')
-rw-r--r--src/interface-curses/interface.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c
index 370fc27..039577f 100644
--- a/src/interface-curses/interface.c
+++ b/src/interface-curses/interface.c
@@ -560,7 +560,7 @@ teco_interface_init_screen(void)
g_assert(teco_interface.screen_tty != NULL);
teco_interface.screen = newterm(NULL, teco_interface.screen_tty, teco_interface.screen_tty);
- if (!teco_interface.screen) {
+ if (G_UNLIKELY(!teco_interface.screen)) {
g_fprintf(stderr, "Error initializing interactive mode. "
"$TERM may be incorrect.\n");
exit(EXIT_FAILURE);
@@ -1255,9 +1255,17 @@ teco_interface_init_clipboard(void)
* must be enabled.
* There is no way to find out if they are but we must
* not register the clipboard registers if they aren't.
- * Therefore, a special XTerm clipboard ED flag an be set by the user.
+ * Still, XTerm clipboards are broken with Unicode characters.
+ * Also, there are other terminal emulators supporting OSC-52,
+ * so the XTerm version is only checked if the terminal identifies as XTerm.
+ * Also, a special clipboard ED flag must be set by the user.
+ *
+ * NOTE: Apparently there is also a terminfo entry Ms, but it's probably
+ * not worth using it since it won't always be set and even if set, does not
+ * tell you whether the terminal will actually answer to the escape sequence or not.
*/
- if (!(teco_ed & TECO_ED_XTERM_CLIPBOARD) || teco_xterm_version() < 203)
+ if (!(teco_ed & TECO_ED_OSC52) ||
+ (teco_xterm_version() >= 0 && teco_xterm_version() < 203))
return;
teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_clipboard_new(""));
@@ -1323,6 +1331,8 @@ teco_interface_set_clipboard(const gchar *name, const gchar *str, gsize str_len,
gboolean
teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError **error)
{
+ gboolean ret = TRUE;
+
/*
* Query the clipboard -- XTerm will reply with the
* OSC-52 command that would set the current selection.
@@ -1350,11 +1360,12 @@ teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError
* Skip "\e]52;x;" (7 characters).
*/
for (gint i = 0; i < 7; i++) {
- if (wgetch(teco_interface.input_pad) == ERR) {
+ ret = wgetch(teco_interface.input_pad) != ERR;
+ if (!ret) {
/* timeout */
g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED,
"Timed out reading XTerm clipboard");
- goto error;
+ goto cleanup;
}
}
@@ -1371,15 +1382,21 @@ teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError
gchar buffer[MAX(3, 7)];
gchar c = (gchar)wgetch(teco_interface.input_pad);
- if (c == ERR) {
+ ret = c != ERR;
+ if (!ret) {
/* timeout */
g_string_free(str_base64, TRUE);
g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED,
"Timed out reading XTerm clipboard");
- goto error;
+ goto cleanup;
}
if (c == '\a')
break;
+ if (c == '\e') {
+ /* OSC escape sequence can also be terminated by "\e\\" */
+ c = (gchar)wgetch(teco_interface.input_pad);
+ break;
+ }
/*
* This could be simplified using sscanf() and
@@ -1394,20 +1411,16 @@ teco_interface_get_clipboard(const gchar *name, gchar **str, gsize *len, GError
g_string_append_len(str_base64, buffer, out_len);
}
- cbreak();
- keypad(teco_interface.input_pad, TRUE);
-
if (str)
*str = str_base64->str;
*len = str_base64->len;
g_string_free(str_base64, !str);
- return TRUE;
-error:
- cbreak();
+cleanup:
keypad(teco_interface.input_pad, TRUE);
- return FALSE;
+ nodelay(teco_interface.input_pad, TRUE);
+ return ret;
}
#else /* !PDCURSES && !CURSES_TTY */