我相信以下内容是相关的,可以在此问题下发布。在这里我将使用
utfinfo.pl(还可以在
超级用户上查看)。
首先,对于标准ASCII字符集,Unicode代码点和字节编码是相同的:
$ echo 'a' | perl utfinfo.pl
Char: 'a' u: 97 [0x0061] b: 97 [0x61] n: LATIN SMALL LETTER A [Basic Latin]
那么在Python的curses
模块中,我们可以这样做:
window.addch('a')
window.border('a')
...并且它按预期工作。
然而,如果一个字符位于基本ASCII之上,则会存在差异,addch
文档没有明确指出。首先,我可以这样做:
window.addch(curses.ACS_PI)
window.border(curses.ACS_PI)
如果你使用gnome-terminal
,那么Unicode字符'π'将被渲染。然而,如果你检查ACS_PI
,你会看到它是一个整数,值为4194427 (0x40007b);因此,下面的代码也会渲染相同的字符(或者说字形?)'π':
window.addch(0x40007b)
window.border(0x40007b)
为了了解发生了什么,我在
ncurses
源代码中进行了grep搜索,并找到了以下内容:
#define ACS_PI NCURSES_ACS('{')
#define NCURSES_ACS(c) (acs_map[NCURSES_CAST(unsigned char,c)])
#define NCURSES_CAST(type,value) static_cast<type>(value)
#lib_acs.c: NCURSES_EXPORT_VAR(chtype *) _nc_acs_map(void): MyBuffer = typeCalloc(chtype, ACS_LEN);
#define typeCalloc(type,elts) (type *)calloc((elts),sizeof(type))
#./widechar/lib_wacs.c: { '{', { '*', 0x03c0 }},
在这里注释:
$ echo '{π' | perl utfinfo.pl
Got 2 uchars
Char: '{' u: 123 [0x007B] b: 123 [0x7B] n: LEFT CURLY BRACKET [Basic Latin]
Char: 'π' u: 960 [0x03C0] b: 207,128 [0xCF,0x80] n: GREEK SMALL LETTER PI [Greek and Coptic]
两者都与 ACS_PI
的值4194427 (0x40007b) 无关。
因此,当addch
和/或border
看到一个高于ASCII的字符(基本上是一个unsigned int
,而不是unsigned char
)时,它们(至少在这种情况下)使用该数字不是作为Unicode代码点或UTF-8编码字节表示 - 而是将其用作acs_map
映射函数的查找索引(尽管最终会模拟VT-100返回Unicode代码点)。 这就是以下规范的原因:
window.addch('π')
window.border('π')
在Python 2.7中,将会出现argument 1 or 3 must be a ch or an int
的错误;而在Python 3.2中,它将只呈现为空格而不是字符。当我们指定'π'
时,实际上指定了UTF-8编码[0xCF,0x80],但即使我们指定Unicode代码点:
window.addch(0x03C0)
window.border0x03C0)
在Python 2.7和3.2中,如果直接使用addch
函数输出字符串,会导致输出为空格。
但请注意,addstr
函数可以正常接受UTF-8编码的字符串并输出:
window.addstr('π')
对于边框 - 因为border()
显然与addch()
以相同的方式处理字符 - 对于任何未明确指定为ACS
常量的内容(而且这些常量并不多),我们似乎没有办法。
希望这能帮助到某些人,
干杯!
python -c 'import pprint,inspect,curses ; curses.initscr() ; outstr= pprint.pformat(inspect.getmembers(curses)); curses.endwin() ; print(outstr)' | grep ACS
。祝好! - sdaau