aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2013-03-11 10:08:44 -0400
committerStefan Monnier2013-03-11 10:08:44 -0400
commit2523c845da0ef83046ff6f978254d43a4851b1f2 (patch)
treea52bb18d8f4e9f300ddf729cafab2f58dbdfded4
parent9b5939800615a4e08ac389813a70faf4b9e57bba (diff)
downloademacs-2523c845da0ef83046ff6f978254d43a4851b1f2.tar.gz
emacs-2523c845da0ef83046ff6f978254d43a4851b1f2.zip
* lisp/term/xterm.el (xterm--report-background-handler): Don't burp
upon timeout. (xterm--version-handler): Extract from terminal-init-xterm. (xterm--query): Don't mishandle timeout. Remove debugging messages. Allow multiple handlers. (terminal-init-xterm): Handle OSX's Terminal.app's incorrect answer. Fixes: debbugs:6758
-rw-r--r--lisp/ChangeLog7
-rw-r--r--lisp/term/xterm.el106
2 files changed, 65 insertions, 48 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 60e01ae2d71..1f136ca398a 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,12 @@
12013-03-11 Stefan Monnier <monnier@iro.umontreal.ca> 12013-03-11 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * term/xterm.el (xterm--report-background-handler): Don't burp
4 upon timeout.
5 (xterm--version-handler): Extract from terminal-init-xterm.
6 (xterm--query): Don't mishandle timeout. Remove debugging messages.
7 Allow multiple handlers.
8 (terminal-init-xterm): Handle OSX's Terminal.app's incorrect answer.
9
3 * term/xterm.el: Don't discard input (bug#6758). Use lexical-binding. 10 * term/xterm.el: Don't discard input (bug#6758). Use lexical-binding.
4 (xterm--report-background-handler, xterm--query): New functions. 11 (xterm--report-background-handler, xterm--query): New functions.
5 (terminal-init-xterm): Use them. 12 (terminal-init-xterm): Use them.
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index a7e137bee99..dcf32e5c595 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -470,7 +470,7 @@ The relevant features are:
470 (let ((str "") 470 (let ((str "")
471 chr) 471 chr)
472 ;; The reply should be: \e ] 11 ; rgb: NUMBER1 / NUMBER2 / NUMBER3 \e \\ 472 ;; The reply should be: \e ] 11 ; rgb: NUMBER1 / NUMBER2 / NUMBER3 \e \\
473 (while (not (equal (setq chr (read-event nil nil 2)) ?\\)) 473 (while (and (setq chr (read-event nil nil 2)) (not (equal chr ?\\)))
474 (setq str (concat str (string chr)))) 474 (setq str (concat str (string chr))))
475 (when (string-match 475 (when (string-match
476 "rgb:\\([a-f0-9]+\\)/\\([a-f0-9]+\\)/\\([a-f0-9]+\\)" str) 476 "rgb:\\([a-f0-9]+\\)/\\([a-f0-9]+\\)/\\([a-f0-9]+\\)" str)
@@ -489,34 +489,65 @@ The relevant features are:
489 (when recompute-faces 489 (when recompute-faces
490 (tty-set-up-initial-frame-faces)))))) 490 (tty-set-up-initial-frame-faces))))))
491 491
492(defun xterm--query (query reply-prefix handler) 492(defun xterm--version-handler ()
493 (let ((str "")
494 chr)
495 ;; The reply should be: \e [ > NUMBER1 ; NUMBER2 ; NUMBER3 c
496 ;; If the timeout is completely removed for read-event, this
497 ;; might hang for terminals that pretend to be xterm, but don't
498 ;; respond to this escape sequence. RMS' opinion was to remove
499 ;; it completely. That might be right, but let's first try to
500 ;; see if by using a longer timeout we get rid of most issues.
501 (while (and (setq chr (read-event nil nil 2)) (not (equal chr ?c)))
502 (setq str (concat str (string chr))))
503 (when (string-match "0;\\([0-9]+\\);0" str)
504 (let ((version (string-to-number (match-string 1 str))))
505 ;; If version is 242 or higher, assume the xterm supports
506 ;; reporting the background color (TODO: maybe earlier
507 ;; versions do too...)
508 (when (>= version 242)
509 (xterm--query "\e]11;?\e\\"
510 '(("\e]11;" . xterm--report-background-handler))))
511
512 ;; If version is 216 (the version when modifyOtherKeys was
513 ;; introduced) or higher, initialize the
514 ;; modifyOtherKeys support.
515 (when (>= version 216)
516 (terminal-init-xterm-modify-other-keys))))))
517
518(defun xterm--query (query handlers)
493 ;; We used to query synchronously, but the need to use `discard-input' is 519 ;; We used to query synchronously, but the need to use `discard-input' is
494 ;; rather annoying (bug#6758). Maybe we could always use the asynchronous 520 ;; rather annoying (bug#6758). Maybe we could always use the asynchronous
495 ;; approach, but it's less tested. 521 ;; approach, but it's less tested.
496 ;; FIXME: Merge the two branches. 522 ;; FIXME: Merge the two branches.
497 (if (input-pending-p) 523 (if (input-pending-p)
498 (progn 524 (progn
499 (message "Doing %S asynchronously" query) 525 (dolist (handler handlers)
500 (define-key input-decode-map reply-prefix 526 (define-key input-decode-map (car handler)
501 (lambda (&optional _prompt) 527 (lambda (&optional _prompt)
502 ;; Unregister the handler, since we don't expect further answers. 528 ;; Unregister the handler, since we don't expect further answers.
503 (define-key input-decode-map reply-prefix nil) 529 (dolist (handler handlers)
504 (funcall handler) 530 (define-key input-decode-map (car handler) nil))
505 [])) 531 (funcall (cdr handler))
532 [])))
506 (send-string-to-terminal query)) 533 (send-string-to-terminal query))
507 ;; Pending input can be mistakenly returned by the calls to 534 ;; Pending input can be mistakenly returned by the calls to
508 ;; read-event below. Discard it. 535 ;; read-event below. Discard it.
509 (message "Doing %S synchronously" query)
510 (send-string-to-terminal query) 536 (send-string-to-terminal query)
511 (let ((i 0)) 537 (while handlers
512 (while (and (< i (length reply-prefix)) 538 (let ((handler (pop handlers))
513 (eq (read-event nil nil 2) (aref reply-prefix i))) 539 (i 0))
514 (setq i (1+ i))) 540 (while (and (< i (length (car handler)))
515 (if (= i (length reply-prefix)) 541 (let ((evt (read-event nil nil 2)))
516 (funcall handler) 542 (or (eq evt (aref (car handler) i))
517 (push last-input-event unread-command-events) 543 (progn (if evt (push evt unread-command-events))
518 (while (> i 0) 544 nil))))
519 (push (aref reply-prefix (setq i (1- i))) unread-command-events)))))) 545 (setq i (1+ i)))
546 (if (= i (length (car handler)))
547 (funcall (cdr handler))
548 (while (> i 0)
549 (push (aref (car handler) (setq i (1- i)))
550 unread-command-events)))))))
520 551
521(defun terminal-init-xterm () 552(defun terminal-init-xterm ()
522 "Terminal initialization function for xterm." 553 "Terminal initialization function for xterm."
@@ -545,37 +576,16 @@ The relevant features are:
545 (if (eq xterm-extra-capabilities 'check) 576 (if (eq xterm-extra-capabilities 'check)
546 ;; Try to find out the type of terminal by sending a "Secondary 577 ;; Try to find out the type of terminal by sending a "Secondary
547 ;; Device Attributes (DA)" query. 578 ;; Device Attributes (DA)" query.
548 (xterm--query 579 (xterm--query "\e[>0c"
549 "\e[>0c" "\e[>" 580 ;; Some terminals (like OS X's Terminal.app) respond to
550 (lambda () 581 ;; this query as if it were a "Primary Device Attributes"
551 (let ((str "") 582 ;; query instead, so we should handle that too.
552 chr) 583 '(("\e[?" . xterm--version-handler)
553 ;; The reply should be: \e [ > NUMBER1 ; NUMBER2 ; NUMBER3 c 584 ("\e[>" . xterm--version-handler)))
554 ;; If the timeout is completely removed for read-event, this
555 ;; might hang for terminals that pretend to be xterm, but don't
556 ;; respond to this escape sequence. RMS' opinion was to remove
557 ;; it completely. That might be right, but let's first try to
558 ;; see if by using a longer timeout we get rid of most issues.
559 (while (not (equal (setq chr (read-event nil nil 2)) ?c))
560 (setq str (concat str (string chr))))
561 (when (string-match "0;\\([0-9]+\\);0" str)
562 (let ((version (string-to-number (match-string 1 str))))
563 ;; If version is 242 or higher, assume the xterm supports
564 ;; reporting the background color (TODO: maybe earlier
565 ;; versions do too...)
566 (when (>= version 242)
567 (xterm--query "\e]11;?\e\\" "\e]11;"
568 #'xterm--report-background-handler))
569
570 ;; If version is 216 (the version when modifyOtherKeys was
571 ;; introduced) or higher, initialize the
572 ;; modifyOtherKeys support.
573 (when (>= version 216)
574 (terminal-init-xterm-modify-other-keys)))))))
575 585
576 (when (memq 'reportBackground xterm-extra-capabilities) 586 (when (memq 'reportBackground xterm-extra-capabilities)
577 (xterm--query "\e]11;?\e\\" "\e]11;" 587 (xterm--query "\e]11;?\e\\"
578 #'xterm--report-background-handler)) 588 '(("\e]11;" . xterm--report-background-handler))))
579 589
580 (when (memq 'modifyOtherKeys xterm-extra-capabilities) 590 (when (memq 'modifyOtherKeys xterm-extra-capabilities)
581 (terminal-init-xterm-modify-other-keys))) 591 (terminal-init-xterm-modify-other-keys)))