Emacs,unicode,xterm鼠标转义序列和宽终端

Rya*_*yan 13 unicode emacs mouse xterm utf-8

简短版本:当使用emacs的xterm-mouse-mode时,Somebody(emacs?bash?xterm?)拦截xterm的控制序列并用\ 0替换它们.这是宽屏显示器的痛苦,因为只有前223列有鼠标.

罪魁祸首是什么,我该如何解决?

据我所知,这与Unicode/UTF-8支持有关,因为5 - 6年前我上次使用大显示器时不是问题.

血腥细节如下......

谢谢!

Emacs xterm-mouse-mode有一个众所周知的弱点,处理从x = 95开始的鼠标点击.最近版本的emacs采用的解决方法将问题推迟到x = 223.

几年前,我发现xterm以7位八位字节编码位置.给定位置'x'进行编码,X = x-96,发送:

\40+x (x < 96)  
\300+X/64 \200+X%64 (otherwise)  
Run Code Online (Sandbox Code Playgroud)

我们必须从emacs中添加一个给定的x位置,因为xterm中的位置从1开始,而不是零.因此,魔术x = 95数字会弹出,因为它被编码为"\ 300\200" - 第一个转义的数字.有人(emacs?bash?xterm?)对待那些来自ISO 2022的 "C0"控制序列.从x = 159开始,我们改为"C1"序列(\ 301\200),它们也是ISO 2022的一部分.

使用\ 302序列遇到问题,这与当前的x = 223限制相对应.几年前,我能够扩展黑客手动拦截\ 302和\ 303序列,从而解决了这个问题.快进几年,今天我发现我被困在x = 223,因为有人用\ 0取代了这些序列.

所以,我期望点击第1行,第250列来制作

ESC [ M SPC \303\207 ! ESC [ M # \303\207 !
Run Code Online (Sandbox Code Playgroud)

相反,emacs报告(对于任何col> 223)

ESC [ M SPC C-@ ! ESC [ M # C-@ !
Run Code Online (Sandbox Code Playgroud)

我怀疑Unicode/UTF-8支持是罪魁祸首.一些挖掘表明,Unicode标准允许C0和C1序列作为UTF-8的一部分,直到2000年11月,我猜有人没有得到备忘录(幸运的是).但是,\ 302\200 - \302\237是Unicode控制序列,所以有人哄骗它们(用谁知道它们!)并返回\ 0而不是.

一些更详细的问题:
- 这是谁有人在达到emacs的损失缓冲区之前拦截代码?
- 如果它真的只是关于控制序列,为什么\ 302\237之后的字符(也就是可打印的Unicode的UTF-8编码)也会回来为\ 0?
- 是什么让emacs决定是否将丢失显示为unicode字符或八进制转义序列,为什么两者不匹配?例如,我自建的cygwin emacs 23.2.1(xterm 229)报告了第161列的\ 301\202,但是我的rhel5.5提供的emacs 22.3.1(xterm 215)报告"Â"(latin A with circumflex) ,这实际上是UTF-8中的\ 303\202!

更新:

这是一个针对xterm-261的补丁,它使它以utf-8格式发出鼠标位置:

diff -r button.c button.utf-8-fix.c
--- a/button.c  Sat Aug 14 08:23:00 2010 +0200
+++ b/button.c  Thu Aug 26 16:16:48 2010 +0200
@@ -3994,1 +3994,27 @@
-#define MOUSE_LIMIT (255 - 32)
+#define MOUSE_LIMIT (2047 - 32)
+#define MOUSE_UTF_8_START (127 - 32)
+
+static unsigned
+EmitMousePosition(Char line[], unsigned count, int value)
+{
+    /* Add pointer position to key sequence
+     * 
+     * Encode large positions as two-byte UTF-8 
+     *
+     * NOTE: historically, it was possible to emit 256, which became
+     * zero by truncation to 8 bits. While this was arguably a bug,
+     * it's also somewhat useful as a past-end marker so we keep it.
+     */
+    if(value == MOUSE_LIMIT) {
+       line[count++] = CharOf(0);
+    }
+    else if(value < MOUSE_UTF_8_START) {
+       line[count++] = CharOf(' ' + value + 1);
+    }
+    else {
+       value += ' ' + 1;
+       line[count++] = CharOf(0xC0 + (value >> 6));
+       line[count++] = CharOf(0x80 + (value & 0x3F));
+    }
+    return count;
+}
@@ -4001,1 +4027,1 @@
-    Char line[6];
+    Char line[9]; /* \e [ > M Pb Pxh Pxl Pyh Pyl */
@@ -4021,2 +4047,0 @@
-    else if (row > MOUSE_LIMIT)
-       row = MOUSE_LIMIT;
@@ -4028,1 +4052,5 @@
-    else if (col > MOUSE_LIMIT)
+
+    /* Limit to representable mouse dimensions */
+    if (row > MOUSE_LIMIT)
+       row = MOUSE_LIMIT;
+    if (col > MOUSE_LIMIT)
@@ -4090,2 +4118,2 @@
-       line[count++] = CharOf(' ' + col + 1);
-       line[count++] = CharOf(' ' + row + 1);
+       count = EmitMousePosition(line, count, col);
+       count = EmitMousePosition(line, count, row);
Run Code Online (Sandbox Code Playgroud)

希望这个(或类似的东西)将出现在xterm的未来版本中...补丁使得xterm开箱即用的emacs-23(假设utf-8输入)并修复了xt-mouse的现有问题.埃尔也.要与emacs-22一起使用它需要重新定义它用于解码鼠标位置的功能(新的定义也适用于emacs-23):

(defadvice xterm-mouse-event-read (around utf-8 compile activate)
  (setq ad-return-value
        (let ((c (read-char)))
          (cond
           ;; mouse clicks outside the encodable range produce 0
           ((= c 0) #x800)
           ;; must convert UTF-8 to unicode ourselves
           ((and (>= c #xC2) (< emacs-major-version 23))
            (logior (lsh (logand c #x1F) 6) (logand (read-char) #x3F)))
           ;; normal case
           (c) ) )))
Run Code Online (Sandbox Code Playgroud)

在您登录的所有计算机上将defun作为.emacs的一部分进行分发,并在您工作的任何计算机上修补xterm.瞧!

警告:使用xterm鼠标模式但不将其输入视为utf-8的应用程序将会被此修补程序弄糊涂,因为鼠标转义序列会变长.但是,这些应用程序在当前xterm中可怕地崩溃,因为x> 95的鼠标位置看起来像utf-8代码但不是.我为xterm创建了一个新的鼠标模式,但是某些应用程序(gnu screen!)会过滤掉未知的转义序列.Emacs是我使用的唯一终端鼠标应用程序,因此我认为该补丁是净胜利,但是YMMV.

小智 6

xterm-262添加了上面内联的补丁,然而,这个补丁完全被设计破坏了.Rxvt-unicode开发人员意识到这一点并添加了另一个更好的扩展来报告鼠标坐标.

现在我正在努力获得广泛的支持.Rxvt-unicode并且iTerm2已经支持这两种扩展.我为xterm(支持urxvt扩展)创建了补丁gnome-terminal,konsoleputty支持和支持这两个扩展.至于应用程序,我已经添加了对urxvt扩展的支持Midnight Commander.

请加入我的努力,并试图说服更多的终端开发人员和应用程序实现这些扩展(至少是urxvt一个,因为另一个不能被应用程序正确地自动识别).

有关技术细节和进一步的指示,请参见http://www.midnight-commander.org/ticket/2662.


Rya*_*yan 4

好吧,想通了。实际上有两个问题。

首先,一些源码分析显示 xterm 将窗口的鼠标启用区域裁剪为 223x223 个字符,并为所有其他位置发送 0x0。

其次,emacs-23 能够识别 UTF-8,并且会被 x>160 和 y>94 的鼠标事件混淆;在这些情况下,xterm 对 x 和 y 的编码看起来像一个两字节的 UTF-8 字符(例如 0xC2 0x80),因此鼠标序列似乎短了一个字符。

我正在为 xterm 开发一个补丁,使鼠标事件发出 UTF-8(这既可以消除 emacs-23 的混淆,又允许终端高达 2047x2047),但我还不确定结果如何。