diff options
| author | Stefan Monnier | 2013-03-11 10:08:44 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2013-03-11 10:08:44 -0400 |
| commit | 2523c845da0ef83046ff6f978254d43a4851b1f2 (patch) | |
| tree | a52bb18d8f4e9f300ddf729cafab2f58dbdfded4 | |
| parent | 9b5939800615a4e08ac389813a70faf4b9e57bba (diff) | |
| download | emacs-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/ChangeLog | 7 | ||||
| -rw-r--r-- | lisp/term/xterm.el | 106 |
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 @@ | |||
| 1 | 2013-03-11 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2013-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))) |