简短版本:当使用emacs的xterm-mouse-mode时,Somebody(emacs?bash?xterm?)拦截xterm的控制序列并用\ 0替换它们。这是宽屏显示器的痛苦,因为只有前223列有鼠标。
罪魁祸首是什么,我该如何解决?
据我所知,这与Unicode / UTF-8支持有关,因为5 - 6年前我上次使用大显示器时不是问题。
血腥的细节如下......
谢谢!
Emacs xterm-mouse-mode有一个众所周知的弱点,处理从x = 95开始的鼠标点击。最近版本的emacs采用的A workaround将问题推迟到x = 223。
几年前,我发现xterm以7位八位字节编码位置。给定位置'x'进行编码,X = x-96,发送:
\40+x (x < 96)
\300+X/64 \200+X%64 (otherwise)
我们必须从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 !
而是emacs报告(对于任何col&gt; 223)
ESC [ M SPC C-@ ! ESC [ M # C-@ !
我怀疑Unicode / UTF-8支持是罪魁祸首。一些挖掘显示the Unicode standard allowed C0 and C1 sequences as part of UTF-8 until Nov 2000,我猜有人没有得到备忘录(幸运的是)。但是,\ 302 \ 200 - \ 302 \ 237是Unicode control sequences,所以有人将它们甩了起来(做谁知道什么与他们!)并返回\ 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);
希望这个(或类似的东西)将出现在xterm的未来版本中...补丁使得xterm开箱即用emacs-23(假定utf-8输入)并修复了xt的现有问题-mouse.el也。要与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) ) )))
在您登录的所有计算机上将defun作为.emacs的一部分进行分发,并在您使用的任何计算机上修补xterm。瞧!
警告:使用xterm的鼠标模式但不将其输入视为utf-8的应用程序会被此修补程序弄糊涂,因为鼠标转义序列会变长。然而,这些应用程序与当前xterm可怕地破坏,因为鼠标位置x> 1。 95看起来像utf-8代码,但不是。我为xterm创建了一个新的鼠标模式,但是某些应用程序(gnu screen!)会过滤掉未知的转义序列。 Emacs是我使用的唯一终端鼠标应用程序,因此我认为该补丁是净胜利,但是YMMV。
答案 0 :(得分:6)
xterm-262
添加了上面内联的补丁,但是,这个补丁完全被设计破坏了。 Rxvt-unicode
的开发人员意识到了这一点,并添加了另一个更好的扩展来报告鼠标坐标。
现在我正致力于获得广泛的支持。 Rxvt-unicode
和iTerm2
已经支持这两种扩展。我为xterm
创建了补丁(以支持urxvt
扩展名),为gnome-terminal
,konsole
和putty
创建了补丁以支持这两个新扩展。至于应用程序,我已将urxvt
扩展程序的支持添加到Midnight Commander
。
请与我一起努力,并试图说服更多的终端开发者和应用程序实现这些扩展(至少urxvt
一个,因为另一个扩展无法被应用程序正确识别。)
请参阅http://www.midnight-commander.org/ticket/2662了解技术细节和进一步的指示。
答案 1 :(得分: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),但我不确定它会如何发展。
答案 2 :(得分:2)
我认为导致您的解决方法(以及其中一个v22版本中包含的上游修补程序)在23.2中停止工作的问题在Emacs本身内部。 23.1可以使用urxvt,gnu screen,putty或iTerm处理第95列之后的鼠标点击,但是23.2不能。将设置为latin-1的所有设置都没有区别。 23.1在xt-mouse.el中具有相同的代码。然而,src / lread.c和src / character.h发生了变化,一目了然我猜这个bug就在那里。至于第223栏后发生的事情,我没有任何线索。
为了其他任何对23.2中的xt-mouse回归感到恼火的人的好处,这里有一个xterm-mouse-event-read的修改版本,可以使用鼠标点击直到第222列(对于&gt; 222溢出,可归功于Ryan处理我原来的修复缺乏)。这可能在23.1或之前不起作用。
(defun xterm-mouse-event-read ()
(let ((c (read-char)))
(cond ((= c 0) #x100)
; for positions past col 222 emacs just delivers
; 0x0, best we can do is stay at eol
((= 0 (logand c (- #x100))) c)
((logand c #xff)))))
...编辑: 这是Emacs 24(bzr head)的版本。它在23.2到222版再次工作,但缺少处理Ryan建议的&gt; 222溢出eol:
(defun xterm-mouse-event-read ()
(let ((c (read-char)))
(if (> c #x3FFF80)
(+ 128 (- c #x3FFF80))
c)))
答案 3 :(得分:1)
虽然xterm现在可以在带有补丁的utf-8模式下工作,但是这个utf-8 hack会在任何其他语言环境中以最糟糕的方式中断,因为除非可以表示,否则将删除unicode字符。
rxvt-unicode(在9.09之后的版本中)有一个1015模式,它使用十进制数发送“ESC [code; x; y M”]形式的回复。这样做的好处是不需要从应用程序进行任何探测,也可以在非utf-8语言环境中工作。