azawawi / raku-ncurses

Raku interface to NCurses library
MIT License
23 stars 9 forks source link

garbled Chinese character #18

Open ohmycloud opened 6 years ago

ohmycloud commented 6 years ago

When I pass some Chinese to mvaddstr function, for example: 你好, the output is OK, but when I pass some other Chinese/Japanese to mvaddstr, such as 彩虹, 哈哈 , ウルヰ, the out put is not ok.

use v6;
use NCurses;

# Initialize curses window
my $win = initscr() or die "Failed to initialize ncurses\n";
start_color;

# Initialize colors
init_pair(1, COLOR_WHITE, COLOR_RED);
init_pair(2, COLOR_WHITE, COLOR_BLUE);

# Print Hello World
color_set(1, 0);
mvaddstr( 10, 10, "你好");    # ok
mvaddstr( 15, 10, "彩虹");    # not ok, becomes: 彩?~Y?
mvaddstr( 15, 10, "哈哈");    # not ok, becomes: ?~S~H?~S~H
color_set(2, 0);
mvaddstr( LINES() - 2, 2, "Press any key to exit..." );

# Refresh (this is needed)
nc_refresh;

# Wait for a keypress
getch;

# Cleanup
LEAVE {
    delwin($win) if $win;
    endwin;
}
HegemonsHerald commented 6 years ago

I've had the same problem with NCurses's support for wide/unicode characters. Apparently NCurses uses its default locale settings (which only includes ASCII characters) unless it's explicitly told to use a full UTF-8 locale.

In C you tell NCurses to use utf8 by calling libc's setlocale() function. You can do the same with NativeCall!

This code works for me:

use v6;
use NCurses;
use NativeCall;

# get setlocale bindings going
sub setlocale(int32, Str) returns Str is native(Str) {*};
# note: for some reason native(Str) refers to whatever version of libc is installed...

# set C-locale to en_US.UTF-8
setlocale(0, "");

my $win = initscr() or die "Failed to initialize ncurses\n";
# ...
# Put the rest of your code here!

Quickly credit where credit is due: I found the NativeCall version of setlocale in the Term::Choose module

ohmycloud commented 5 years ago

Thanks very much! my script now works!

jonathanstowe commented 5 years ago

For anyone else who might come upon this and can't get the above to work, you might find that you need to force the use of libncursesw rather than libncurses by doing something like PERL6_NCURSES_LIB=libncursesw.so.6 before starting the program.

It might be worth considering changing the order that the two versions of the library are considered, such that if both are installed (as seems fairly common on recent Linux distributions,) then it gets the wide character enable version.