source: main/trunk/greenstone2/perllib/cpan/Encode/Locale.pm@ 27174

Last change on this file since 27174 was 27174, checked in by davidb, 11 years ago

Perl modules from CPAN that are used in supporting activate.pl, but not part of the Perl core. Only PMs included.

File size: 10.8 KB
Line 
1package Encode::Locale;
2
3use strict;
4our $VERSION = "1.03";
5
6use base 'Exporter';
7our @EXPORT_OK = qw(
8 decode_argv env
9 $ENCODING_LOCALE $ENCODING_LOCALE_FS
10 $ENCODING_CONSOLE_IN $ENCODING_CONSOLE_OUT
11);
12
13use Encode ();
14use Encode::Alias ();
15
16our $ENCODING_LOCALE;
17our $ENCODING_LOCALE_FS;
18our $ENCODING_CONSOLE_IN;
19our $ENCODING_CONSOLE_OUT;
20
21sub DEBUG () { 0 }
22
23sub _init {
24 if ($^O eq "MSWin32") {
25 unless ($ENCODING_LOCALE) {
26 # Try to obtain what the Windows ANSI code page is
27 eval {
28 unless (defined &GetACP) {
29 require Win32::API;
30 Win32::API->Import('kernel32', 'int GetACP()');
31 };
32 if (defined &GetACP) {
33 my $cp = GetACP();
34 $ENCODING_LOCALE = "cp$cp" if $cp;
35 }
36 };
37 }
38
39 unless ($ENCODING_CONSOLE_IN) {
40 # If we have the Win32::Console module installed we can ask
41 # it for the code set to use
42 eval {
43 require Win32::Console;
44 my $cp = Win32::Console::InputCP();
45 $ENCODING_CONSOLE_IN = "cp$cp" if $cp;
46 $cp = Win32::Console::OutputCP();
47 $ENCODING_CONSOLE_OUT = "cp$cp" if $cp;
48 };
49 # Invoking the 'chcp' program might also work
50 if (!$ENCODING_CONSOLE_IN && (qx(chcp) || '') =~ /^Active code page: (\d+)/) {
51 $ENCODING_CONSOLE_IN = "cp$1";
52 }
53 }
54 }
55
56 unless ($ENCODING_LOCALE) {
57 eval {
58 require I18N::Langinfo;
59 $ENCODING_LOCALE = I18N::Langinfo::langinfo(I18N::Langinfo::CODESET());
60
61 # Workaround of Encode < v2.25. The "646" encoding alias was
62 # introduced in Encode-2.25, but we don't want to require that version
63 # quite yet. Should avoid the CPAN testers failure reported from
64 # openbsd-4.7/perl-5.10.0 combo.
65 $ENCODING_LOCALE = "ascii" if $ENCODING_LOCALE eq "646";
66
67 # https://rt.cpan.org/Ticket/Display.html?id=66373
68 $ENCODING_LOCALE = "hp-roman8" if $^O eq "hpux" && $ENCODING_LOCALE eq "roman8";
69 };
70 $ENCODING_LOCALE ||= $ENCODING_CONSOLE_IN;
71 }
72
73 if ($^O eq "darwin") {
74 $ENCODING_LOCALE_FS ||= "UTF-8";
75 }
76
77 # final fallback
78 $ENCODING_LOCALE ||= $^O eq "MSWin32" ? "cp1252" : "UTF-8";
79 $ENCODING_LOCALE_FS ||= $ENCODING_LOCALE;
80 $ENCODING_CONSOLE_IN ||= $ENCODING_LOCALE;
81 $ENCODING_CONSOLE_OUT ||= $ENCODING_CONSOLE_IN;
82
83 unless (Encode::find_encoding($ENCODING_LOCALE)) {
84 my $foundit;
85 if (lc($ENCODING_LOCALE) eq "gb18030") {
86 eval {
87 require Encode::HanExtra;
88 };
89 if ($@) {
90 die "Need Encode::HanExtra to be installed to support locale codeset ($ENCODING_LOCALE), stopped";
91 }
92 $foundit++ if Encode::find_encoding($ENCODING_LOCALE);
93 }
94 die "The locale codeset ($ENCODING_LOCALE) isn't one that perl can decode, stopped"
95 unless $foundit;
96
97 }
98
99 # use Data::Dump; ddx $ENCODING_LOCALE, $ENCODING_LOCALE_FS, $ENCODING_CONSOLE_IN, $ENCODING_CONSOLE_OUT;
100}
101
102_init();
103Encode::Alias::define_alias(sub {
104 no strict 'refs';
105 no warnings 'once';
106 return ${"ENCODING_" . uc(shift)};
107}, "locale");
108
109sub _flush_aliases {
110 no strict 'refs';
111 for my $a (keys %Encode::Alias::Alias) {
112 if (defined ${"ENCODING_" . uc($a)}) {
113 delete $Encode::Alias::Alias{$a};
114 warn "Flushed alias cache for $a" if DEBUG;
115 }
116 }
117}
118
119sub reinit {
120 $ENCODING_LOCALE = shift;
121 $ENCODING_LOCALE_FS = shift;
122 $ENCODING_CONSOLE_IN = $ENCODING_LOCALE;
123 $ENCODING_CONSOLE_OUT = $ENCODING_LOCALE;
124 _init();
125 _flush_aliases();
126}
127
128sub decode_argv {
129 die if defined wantarray;
130 for (@ARGV) {
131 $_ = Encode::decode(locale => $_, @_);
132 }
133}
134
135sub env {
136 my $k = Encode::encode(locale => shift);
137 my $old = $ENV{$k};
138 if (@_) {
139 my $v = shift;
140 if (defined $v) {
141 $ENV{$k} = Encode::encode(locale => $v);
142 }
143 else {
144 delete $ENV{$k};
145 }
146 }
147 return Encode::decode(locale => $old) if defined wantarray;
148}
149
1501;
151
152__END__
153
154=head1 NAME
155
156Encode::Locale - Determine the locale encoding
157
158=head1 SYNOPSIS
159
160 use Encode::Locale;
161 use Encode;
162
163 $string = decode(locale => $bytes);
164 $bytes = encode(locale => $string);
165
166 if (-t) {
167 binmode(STDIN, ":encoding(console_in)");
168 binmode(STDOUT, ":encoding(console_out)");
169 binmode(STDERR, ":encoding(console_out)");
170 }
171
172 # Processing file names passed in as arguments
173 my $uni_filename = decode(locale => $ARGV[0]);
174 open(my $fh, "<", encode(locale_fs => $uni_filename))
175 || die "Can't open '$uni_filename': $!";
176 binmode($fh, ":encoding(locale)");
177 ...
178
179=head1 DESCRIPTION
180
181In many applications it's wise to let Perl use Unicode for the strings it
182processes. Most of the interfaces Perl has to the outside world are still byte
183based. Programs therefore need to decode byte strings that enter the program
184from the outside and encode them again on the way out.
185
186The POSIX locale system is used to specify both the language conventions
187requested by the user and the preferred character set to consume and
188output. The C<Encode::Locale> module looks up the charset and encoding (called
189a CODESET in the locale jargon) and arranges for the L<Encode> module to know
190this encoding under the name "locale". It means bytes obtained from the
191environment can be converted to Unicode strings by calling C<<
192Encode::encode(locale => $bytes) >> and converted back again with C<<
193Encode::decode(locale => $string) >>.
194
195Where file systems interfaces pass file names in and out of the program we also
196need care. The trend is for operating systems to use a fixed file encoding
197that don't actually depend on the locale; and this module determines the most
198appropriate encoding for file names. The L<Encode> module will know this
199encoding under the name "locale_fs". For traditional Unix systems this will
200be an alias to the same encoding as "locale".
201
202For programs running in a terminal window (called a "Console" on some systems)
203the "locale" encoding is usually a good choice for what to expect as input and
204output. Some systems allows us to query the encoding set for the terminal and
205C<Encode::Locale> will do that if available and make these encodings known
206under the C<Encode> aliases "console_in" and "console_out". For systems where
207we can't determine the terminal encoding these will be aliased as the same
208encoding as "locale". The advice is to use "console_in" for input known to
209come from the terminal and "console_out" for output known to go from the
210terminal.
211
212In addition to arranging for various Encode aliases the following functions and
213variables are provided:
214
215=over
216
217=item decode_argv( )
218
219=item decode_argv( Encode::FB_CROAK )
220
221This will decode the command line arguments to perl (the C<@ARGV> array) in-place.
222
223The function will by default replace characters that can't be decoded by
224"\x{FFFD}", the Unicode replacement character.
225
226Any argument provided is passed as CHECK to underlying Encode::decode() call.
227Pass the value C<Encode::FB_CROAK> to have the decoding croak if not all the
228command line arguments can be decoded. See L<Encode/"Handling Malformed Data">
229for details on other options for CHECK.
230
231=item env( $uni_key )
232
233=item env( $uni_key => $uni_value )
234
235Interface to get/set environment variables. Returns the current value as a
236Unicode string. The $uni_key and $uni_value arguments are expected to be
237Unicode strings as well. Passing C<undef> as $uni_value deletes the
238environment variable named $uni_key.
239
240The returned value will have the characters that can't be decoded replaced by
241"\x{FFFD}", the Unicode replacement character.
242
243There is no interface to request alternative CHECK behavior as for
244decode_argv(). If you need that you need to call encode/decode yourself.
245For example:
246
247 my $key = Encode::encode(locale => $uni_key, Encode::FB_CROAK);
248 my $uni_value = Encode::decode(locale => $ENV{$key}, Encode::FB_CROAK);
249
250=item reinit( )
251
252=item reinit( $encoding )
253
254Reinitialize the encodings from the locale. You want to call this function if
255you changed anything in the environment that might influence the locale.
256
257This function will croak if the determined encoding isn't recognized by
258the Encode module.
259
260With argument force $ENCODING_... variables to set to the given value.
261
262=item $ENCODING_LOCALE
263
264The encoding name determined to be suitable for the current locale.
265L<Encode> know this encoding as "locale".
266
267=item $ENCODING_LOCALE_FS
268
269The encoding name determined to be suiteable for file system interfaces
270involving file names.
271L<Encode> know this encoding as "locale_fs".
272
273=item $ENCODING_CONSOLE_IN
274
275=item $ENCODING_CONSOLE_OUT
276
277The encodings to be used for reading and writing output to the a console.
278L<Encode> know these encodings as "console_in" and "console_out".
279
280=back
281
282=head1 NOTES
283
284This table summarizes the mapping of the encodings set up
285by the C<Encode::Locale> module:
286
287 Encode | | |
288 Alias | Windows | Mac OS X | POSIX
289 ------------+---------+--------------+------------
290 locale | ANSI | nl_langinfo | nl_langinfo
291 locale_fs | ANSI | UTF-8 | nl_langinfo
292 console_in | OEM | nl_langinfo | nl_langinfo
293 console_out | OEM | nl_langinfo | nl_langinfo
294
295=head2 Windows
296
297Windows has basically 2 sets of APIs. A wide API (based on passing UTF-16
298strings) and a byte based API based a character set called ANSI. The
299regular Perl interfaces to the OS currently only uses the ANSI APIs.
300Unfortunately ANSI is not a single character set.
301
302The encoding that corresponds to ANSI varies between different editions of
303Windows. For many western editions of Windows ANSI corresponds to CP-1252
304which is a character set similar to ISO-8859-1. Conceptually the ANSI
305character set is a similar concept to the POSIX locale CODESET so this module
306figures out what the ANSI code page is and make this available as
307$ENCODING_LOCALE and the "locale" Encoding alias.
308
309Windows systems also operate with another byte based character set.
310It's called the OEM code page. This is the encoding that the Console
311takes as input and output. It's common for the OEM code page to
312differ from the ANSI code page.
313
314=head2 Mac OS X
315
316On Mac OS X the file system encoding is always UTF-8 while the locale
317can otherwise be set up as normal for POSIX systems.
318
319File names on Mac OS X will at the OS-level be converted to
320NFD-form. A file created by passing a NFC-filename will come
321in NFD-form from readdir(). See L<Unicode::Normalize> for details
322of NFD/NFC.
323
324Actually, Apple does not follow the Unicode NFD standard since not all
325character ranges are decomposed. The claim is that this avoids problems with
326round trip conversions from old Mac text encodings. See L<Encode::UTF8Mac> for
327details.
328
329=head2 POSIX (Linux and other Unixes)
330
331File systems might vary in what encoding is to be used for
332filenames. Since this module has no way to actually figure out
333what the is correct it goes with the best guess which is to
334assume filenames are encoding according to the current locale.
335Users are advised to always specify UTF-8 as the locale charset.
336
337=head1 SEE ALSO
338
339L<I18N::Langinfo>, L<Encode>
340
341=head1 AUTHOR
342
343Copyright 2010 Gisle Aas <[email protected]>.
344
345This library is free software; you can redistribute it and/or
346modify it under the same terms as Perl itself.
347
348=cut
Note: See TracBrowser for help on using the repository browser.