Python 未使用Ruby打印的Unicode方框图形字符

Python 未使用Ruby打印的Unicode方框图形字符,python,c,ruby,linux,ncurses,Python,C,Ruby,Linux,Ncurses,我用Ruby做了一个游戏。它使用ncurses绘制窗口内容并刷新屏幕。这一切在macOS上都很好,我在macOS上开发这些东西。但在Linux上,当从Ruby或纯C与ncurses接口时,除了普通ASCII之外,我无法打印任何东西 例如,我得到以下输出: Hello, world! M-b~U~TM-b~U~PM-b~U~WM-b~U~QM-b~U~QM-b~U~ZM-b~U~PM-b~U~]M-b~U~_M-b~T~@M-b~UM-" 而不是我在源代码中输入的内容: Hello, world

我用Ruby做了一个游戏。它使用ncurses绘制窗口内容并刷新屏幕。这一切在macOS上都很好,我在macOS上开发这些东西。但在Linux上,当从Ruby或纯C与ncurses接口时,除了普通ASCII之外,我无法打印任何东西

例如,我得到以下输出:

Hello, world! M-b~U~TM-b~U~PM-b~U~WM-b~U~QM-b~U~QM-b~U~ZM-b~U~PM-b~U~]M-b~U~_M-b~T~@M-b~UM-"
而不是我在源代码中输入的内容:

Hello, world! ╔═╗║║╚═╝╟─╢
文件编码为UTF-8、
env
locale
输出报告
LANG
LC.*
变量为
en_-US
en_-US.UTF-8
。终端可以很好地打印这些字符,因此这不是字体或终端模拟器设置

Python 3也可以很好地工作。Ruby和C没有

(在安装了
libncurse5 dev
的全新Linux Mint 19设置上测试。)

那么,我是缺少了一些设置,还是Python绑定有点特别,我运气不好?


它看起来像什么 它应该是这样的(macOS):

但实际上是这样的:

Python代码 这段代码工作得很好:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import locale
import curses

locale.setlocale(locale.LC_ALL, '')

stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.addstr(0, 0, "╔═╗║║╚═╝╟─╢") # dont even need .encode('UTF-8')
stdscr.refresh()
stdscr.getkey()
curses.endwin()
“诅咒”模块的文档说明,自ncurses 5开始,您必须执行此操作:

从5.4版开始,ncurses库决定如何使用nl_langinfo函数解释非ASCII数据。这意味着您必须在应用程序中调用locale.setlocale(),并使用系统的一种可用编码对Unicode字符串进行编码

Ruby代码 尝试使用
ffi ncurses
gem而不是
curses
,但无效。输出是相同的

C代码 我用

gcc -finput-charset=UTF-8 -fexec-charset=UTF-8 -pedantic -Wall -o main main.c -lncurses
代码如下:

// Most of the code is sample code from "CURHELLO.C"
// (c) Copyright Paul Griffiths 1999

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <langinfo.h>
#include <locale.h>
#include <ncurses.h>

int main(void) {

    // Here I tried to copy what Python is doing:
    setlocale(LC_ALL, ""); // Also tried "C.UTF-8", "en_US.UTF-8"
    nl_langinfo(CODESET);


    WINDOW * mainwin;
    if ( (mainwin = initscr()) == NULL ) {
        fprintf(stderr, "Error initialising ncurses.\n");
        exit(EXIT_FAILURE);
    }

    start_color();
    clear();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    mvaddstr(1, 1, "Hello, world! ╔═╗║║╚═╝╟─╢");
    refresh();
    sleep(3);

    delwin(mainwin);
    endwin();
    refresh();

    return EXIT_SUCCESS;
}
//大部分代码是“CURHELLO.C”中的示例代码
//(c)版权所有Paul Griffiths 1999
#包括
#包括
#包括
#包括
#包括
#包括
内部主(空){
//在这里,我尝试复制Python正在做的事情:
setlocale(LC_ALL,“”;//还尝试了“C.UTF-8”、“en_US.UTF-8”
nl_langinfo(代码集);
窗口*mainwin;
如果((mainwin=initscr())==NULL){
fprintf(stderr,“初始化ncurses时出错。\n”);
退出(退出失败);
}
启动颜色();
清除();
cbreak();
noecho();
键盘(stdscr,真);
mvaddstr(1,1,“你好,世界!╔═╗║║╚═╝╟─╢");
刷新();
睡眠(3);
德尔温(缅因州);
endwin();
刷新();
返回退出成功;
}
编辑 通过链接到
ncursesw
(注意后面的
W
!),它可以正常工作,但是它在Linux上使用Ubuntu Mono以文本宽度的两倍显示特殊字符,与我在OSX和iTerm上使用的字体相同


实际上,这应该是几个问题,但最近的一个问题是如何将字符显示为双倍宽度

屏幕截图与给定的示例程序不匹配。这只绘制了几个示例字符,而屏幕截图显示的是方框

但是,与区域设置表相比,特定的线条绘制字符可能是问题所在(并且取决于所使用的实际程序)。这是因为这些代码是(请参阅)。标准将它们视为单宽还是双宽由实现者决定。并非所有人都同意实际宽度


如果这是一个问题,我会使用实际的程序源代码进行测试,但我怀疑问题出在Ruby中。

实际上这应该是几个问题,但最近的一个问题是如何将字符显示为双宽度

屏幕截图与给定的示例程序不匹配。这只绘制了几个示例字符,而屏幕截图显示的是方框

但是,与区域设置表相比,特定的线条绘制字符可能是问题所在(并且取决于所使用的实际程序)。这是因为这些代码是(请参阅)。标准将它们视为单宽还是双宽由实现者决定。并非所有人都同意实际宽度


如果这是一个问题,我会使用实际的程序源代码进行测试,但怀疑问题出在Ruby上。

将C代码与
ncursesw
链接起来,它就会工作。(虽然ncursesw为宽字符添加了新的类型和接口,但它也为标准ncurses函数添加了UTF-8多字节支持。)另外,Ruby应该更喜欢ncursesw而不是ncurses,因此您可能没有安装ncursesw包。该库由Debian、Ubuntu、Mint上的
libncursesw5
提供(您可能没有安装该库)。如果您还想在C中尝试ncursesw中的其他接口,请同时安装
libncursesw5 dev
包。最后,我建议您使用
gcc-Wall-O2$(pkg config--cflags ncursesw)main.C$(pkg config--libs ncursesw)-o main
编译C程序。我刚刚检查了一下,注意到块元素字符,如
,在Ubuntu Mono、Oxygen Mono、Noto Mono或Linux Libertine Mono字体中不是等距字体:即使它们声称是等距字体,块元素也不是等距字体!在我的系统中,Nimbus Mono L、Monospace、Liberation Mono、FreeMono、DejaVu Sans Mono、Bitstream Vera Sans Mono和Andale Mono字体似乎都有适当的等距字体phs甚至适用于方框图和块元素,因此我建议您使用这些字体中的一种(并在您的文档中提及问题和字体!)您不能从终端内运行的程序更改字体;必须指示用户更改字体。对于gnome终端,请选择编辑,然后选择配置文件首选项,然后选择常规选项卡,选中自定义字体复选框,然后使用复选框右侧的按钮选择字体。在mate终端中,字体位于同一选项卡上,但您需要取消选中e使用系统字体来选择字体。我从未使用过X终端模拟器,它不允许我选择字体。请尝试运行
// Most of the code is sample code from "CURHELLO.C"
// (c) Copyright Paul Griffiths 1999

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <langinfo.h>
#include <locale.h>
#include <ncurses.h>

int main(void) {

    // Here I tried to copy what Python is doing:
    setlocale(LC_ALL, ""); // Also tried "C.UTF-8", "en_US.UTF-8"
    nl_langinfo(CODESET);


    WINDOW * mainwin;
    if ( (mainwin = initscr()) == NULL ) {
        fprintf(stderr, "Error initialising ncurses.\n");
        exit(EXIT_FAILURE);
    }

    start_color();
    clear();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    mvaddstr(1, 1, "Hello, world! ╔═╗║║╚═╝╟─╢");
    refresh();
    sleep(3);

    delwin(mainwin);
    endwin();
    refresh();

    return EXIT_SUCCESS;
}