atom feed1 message in org.perl.perl-i18nPrinting non-ascii on the Win32 console
FromSent OnAttachments
Bjoern HoehrmannJul 1, 2008 1:13 pm 
Subject:Printing non-ascii on the Win32 console
From:Bjoern Hoehrmann (bjo@hoehrmann.de)
Date:Jul 1, 2008 1:13:57 pm
List:org.perl.perl-i18n

Hi,

Writing an example script for Win32::MultiLanguage that simply lists all supported code pages in the user's default language, I naturally got all the umlauts in the german output messed up in the console. Wondering how to fix that I thought there should be a simple way to say, e.g.,

binmode STDOUT => ':encoding(:terminal)' if -t STDOUT;

I only found the :locale sub-pragma in open.pm and encoding.pm and it seems it does not work with binmode at all and would also fail on Win32 systems due to not setting the relevant environment variables. So I've implemented a crude and simple solution like this:

use Encode; use Encode::Alias;

sub terminal_encoding { my $encoding;

if ($^O eq 'MSWin32') { eval { require Win32::API; $encoding = "cp" . Win32::API->new('kernel32', 'UINT GetConsoleOutputCP()')->Call(); }; } else { require encoding; $encoding = encoding::_get_locale_encoding(); }

return $encoding; }

define_alias(qr/^:terminal$/ => __PACKAGE__ . '->terminal_encoding()');

I then wondered about putting this into a module, but there seem too many problems with this at the moment, one obvious thing is calling the supposedly private _get_locale_encoding function to provide a fallback on non-Win32 systems, then there are some codepages that might be used as default somewhere that Encode supports but does not support the cp alias for it (I could not find a list of those in use, presumably only the three digit pages are default oem code pages and Encode supports the cp alias for the encodings it support it seems), needing a C compiler on Windows is kind of annoying (it would be nice if a Core module would ex- pose GetConsoleOutputCP), and error handling seems tricky.

For example, it seems not possible to control the Encode fallback beha- vior only for the one file handle in question, falling back to "no encoding" if the terminal encoding is unsupported is not possible either (unless someone makes a 'raw' encoding I suppose), the encoding finder code cannot croak as it's running in a string eval, and I am not sure there is a good way to generate a warning if and only if the code doing the binmode has warnings turned on. So while this seemed elegant at first, I've ditched the idea. Perhaps someone else is going to take this up.

regards,