诅咒-某些表情符号(标志)会使终端输出变形

时间:2019-03-04 12:26:34

标签: unicode ncurses curses python-curses

当我将某些表情符号(特别是标志)输出到curses的子窗口中时,即使在该子窗口之外的输出中,它也会使输出变形。

运行:


import curses

def draw_screen(stdscr):

    event = 0
    stdscr.clear()
    stdscr.refresh()

    while (event != ord('q')):

        emojis = ["", "", ""]
        # emojis = ["", "", ""]

        for i, emoji in enumerate(emojis):
            box1 = stdscr.subwin(11, 11, 0, i*12)
            box1.box()
            box1.addstr(0, 4, emoji)

        event = stdscr.getch()

if __name__ == "__main__":
    curses.wrapper(draw_screen)

产生:

enter image description here

如果仅将表情符号切换为心脏,则效果很好:

enter image description here

我了解到标志表情符号是一系列区域指示器符号,但是我认为这应该可行,并且不确定如何解决它。

我已经在Mac OS 10.13和10.14的iTerm和终端中对此进行了测试。

(我还注意到,其他一些多点表情符号(‍)在原始Python中可以很好地打印,但在curses中分为两个单独的表情符号来构成它们,我不确定这是否相关。)

1 个答案:

答案 0 :(得分:1)

ncurses使用操作系统的 wcwidth 函数来确定字符的显示宽度。 Terminal.app假定U + 1F1FA和U + 1F1F8使用两列,而 wcwidth 似乎说它们每个都只有一列。 wcwidth 和Terminal.app都将绿色心脏U+1F49A视为双倍宽度。您可以通过在表情符号符号之前和之后添加一个字符来看到这一点:在误导了ncurses的地方,显示的结果将显示重叠的字符。

illustration of overlap

直到Unicode 9(2016),根据Unicode的EastAsianWidth文件,这些特定代码均为“中性宽度” Unicode Technical Report #11 Unicode Character Property "East Asian Width" (从1999年开始)暗示(从未提供明确的定义)“中性宽度”字符的实际宽度取决于上下文,即,如果将它们与全角字符一起使用,则应为视为双倍宽度。例如说

  

在混合宽度集中,窄(中性)字符始终映射为半角字符

但仅以“全角”(两列)和“窄角”(一列)的混合形式指代“混合宽度”。

wcwidth 函数通常(MacOS可能不是例外)对于给定的代码点,将忽略区域设置而返回相同的宽度。

Unicode 8中,这些是相关的行(值的范围):

1F1E6..1F1FF;N   # So    [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
1F400..1F579;N   # So   [378] RAT..JOYSTICK

Unicode 9中,U + 1F49A是“全角”,但其他两个是中性的:

1F1E6..1F1FF;N   # So    [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
1F442..1F4FC;W   # So   [187] EAR..VIDEOCASSETTE

我看不到这些通过Unicode 12(当前)而改变了。

鉴于所有这些,它看起来像是字体和/或wcwidth的错误,它是由惯性引起的(在Apple做出 wcwidth <之前,您无能为力。 / strong>同意其字体)。

顺便说一句,您可能会发现与该问题有关的Proposal on use of ZERO WIDTH JOINER (ZWJ) between two Regional Indicator Symbols