Subject: bug#12354: 24.2; garbage inserted at the beginning of the buffer even when xterm-extra-capabilities is t

From: Stefan Monnier <[email-masked]>
Date: Tue, 30 Jun 2015 23:19:11 -0400

> If you look at the code, you'll hopefully see that there are 2 code
> paths (one synchronous with a timeout, and one asynchronous), and
> a comment saying that the two should be merged.
> I.e. when using the synchronous path, after hitting the timeout, we
> should switch to the async path.
> Or simply just "always" use the async path.

I installed the patch below which switches to the async method in case
of a timeout.  That should hopefully solve your use case.

        Stefan

diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index f7f8007..350ab3c 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -688,6 +688,10 @@ string bytes that can be copied is 3/4 of this value."
           ;;(xterm--init-activate-get-selection)
           (xterm--init-activate-set-selection))))))
 
+(defvar xterm-query-timeout 2
+  "Seconds to wait for an answer from the terminal.
+Can be nil to mean \"no timeout\".")
+
 (defun xterm--query (query handlers &optional no-async)
   "Send QUERY string to the terminal and watch for a response.
 HANDLERS is an alist with elements of the form (STRING . FUNCTION).
@@ -696,25 +696,37 @@
   ;; rather annoying (bug#6758).  Maybe we could always use the asynchronous
   ;; approach, but it's less tested.
   ;; FIXME: Merge the two branches.
-  (if (and (input-pending-p) (not no-async))
-      (progn
+  (let ((register
+         (lambda (handlers)
         (dolist (handler handlers)
           (define-key input-decode-map (car handler)
             (lambda (&optional _prompt)
-              ;; Unregister the handler, since we don't expect further answers.
+                 ;; Unregister the handler, since we don't expect
+                 ;; further answers.
               (dolist (handler handlers)
                 (define-key input-decode-map (car handler) nil))
               (funcall (cdr handler))
-              [])))
+                 []))))))
+    (if (and (or (null xterm-query-timeout) (input-pending-p))
+             (not no-async))
+        (progn
+          (funcall register handlers)
         (send-string-to-terminal query))
     ;; Pending input can be mistakenly returned by the calls to
-    ;; read-event below.  Discard it.
+      ;; read-event below: discard it.
+      (discard-input)
     (send-string-to-terminal query)
     (while handlers
       (let ((handler (pop handlers))
             (i 0))
         (while (and (< i (length (car handler)))
-                    (let ((evt (read-event nil nil 2)))
+                      (let ((evt (read-event nil nil xterm-query-timeout)))
+                        (if (and (null evt) (= i 0) (not no-async))
+                            ;; Timeout on the first event: fallback on async.
+                            (progn
+                              (funcall register (cons handler handlers))
+                              (setq handlers nil)
+                              nil)
                       (or (eq evt (aref (car handler) i))
                           (progn (if evt (push evt unread-command-events))
                                  nil))))
@@ -724,7 +736,7 @@
                    (funcall (cdr handler)))
           (while (> i 0)
             (push (aref (car handler) (setq i (1- i)))
-                  unread-command-events)))))))
+                      unread-command-events)))))))))
 
 (defun xterm--push-map (map basemap)
   ;; Use inheritance to let the main keymaps override those defaults.