From df344bde2bbe459eb5aea668388d2606a38fe12c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sat, 3 Aug 2019 12:08:27 +0200 Subject: [PATCH] Fix XTerm OSC 52 selection retrieval (bug#36879) When asking XTerm for the selection via OSC 52, set the quit char to something other than BEL since that char is used as string terminator in the reply. Otherwise, the pty will raise SIGINT as soon as it sees the BEL, discarding any unread chars. Also allow the reply to be terminated by ST as well as BEL. * lisp/term/xterm.el (gui-backend-get-selection): Change quit char temporarily. Detect ST as string terminator in reply. Use time-out when reading reply. --- lisp/term/xterm.el | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index c4b0a8fb6e..29460ea55b 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el @@ -954,14 +954,35 @@ gui-backend-get-selection (query (concat "\e]52;" (xterm--selection-char type) ";"))) (with-temp-buffer (set-buffer-multibyte nil) - (xterm--query - (concat (when screen "\eP") query "?\a" (when screen "\e\\")) - (list (cons query (lambda () - (while (let ((char (read-char))) - (unless (eq char ?\a) - (insert char) - t)))))) - 'no-async) + (let ((old-quit-char (nth 3 (current-input-mode)))) + ;; Temporarily set the quit char to something else, because + ;; C-g may be sent from the terminal as a string terminator, + ;; and the resulting SIGINT (which occurs when the interrupt + ;; char is received by the tty, not when we read it) would + ;; flush unread chars from the tty input queue. + (unwind-protect + (progn + (set-quit-char ?\377) + (xterm--query + (concat (when screen "\eP") query "?\a" (when screen "\e\\")) + (list (cons query + (lambda () + ;; Read data up to the string terminator, + ;; either ST (ESC \) or BEL. + (let (char last) + (while (and (setq char (read-char + nil nil + xterm-query-timeout)) + (not (or (eq char ?\a) + (and (eq char ?\\) + (eq last ?\e))))) + (when last + (insert last)) + (setq last char)) + (when (eq char ?\a) + (insert last)))))) + 'no-async)) + (set-quit-char old-quit-char))) (base64-decode-region (point-min) (point-max)) (decode-coding-region (point-min) (point-max) 'utf-8-unix t)))) -- 2.21.0