/[pub]/test/oldencodeutils/lib/M17N/Code/JA.pm
Suika

Diff of /test/oldencodeutils/lib/M17N/Code/JA.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by wakaba, Mon Dec 24 08:13:56 2001 UTC revision 1.3 by wakaba, Sat Jul 20 08:49:09 2002 UTC
# Line 1  Line 1 
1    
2    =head1 NAME
3    
4    M17N::Code::JA --- Perl module for convertion between
5    coding systems of string written in Japanese language
6    
7    =cut
8    
9  package M17N::Code::JA;  package M17N::Code::JA;
10  use strict;  use strict;
11  use vars qw(%re %internalo);  use vars qw(%re %_cp);
12    
13  %re = (  %re = (
14    94x1  => qr/\x1B\x28([\x40-\x7D])((?:[\x21-\x7E])*)/,    94x1  => qr/\x1B\x28[\x40-\x7D](?:[\x21-\x7E])*/,
15    94x2  => qr/(?:\x1B\x26([\x40-\x7E]))?\x1B\x24\x28?([\x40-\x5F])((?:[\x21-\x7E][\x21-\x7E])*)/,    94x2  => qr/(?:\x1B\x26[\x40-\x7E])?\x1B\x24\x28?[\x40-\x5F](?:[\x21-\x7E][\x21-\x7E])*/,
16    96x1  => qr/\x1B\x2C([\x40-\x7D])((?:[\x20-\x7F])*)/,    96x1  => qr/\x1B\x2C[\x40-\x7D](?:[\x20-\x7F])*/,
17    utf8  => qr/\x1B\x25(?:\x47|\x2F[\x47-\x49])((?:[\x20-\x7F]|(?:[\xC0-\xFD][\x80-\xBF]+))*)\x1B\x25\x40/,    utf8  => qr/\x1B\x25(?:\x47|\x2F[\x47-\x49])(?:[\x20-\x7F]|(?:[\xC0-\xFD][\x80-\xBF]+))*\x1B\x25\x40/,
18      M_94x1        => qr/\x1B\x28([\x40-\x7D])((?:[\x21-\x7E])*)/,
19      M_94x2        => qr/(?:\x1B\x26([\x40-\x7E]))?\x1B\x24\x28?([\x40-\x5F])((?:[\x21-\x7E][\x21-\x7E])*)/,
20      M_96x1        => qr/\x1B\x2C([\x40-\x7D])((?:[\x20-\x7F])*)/,
21      M_utf8        => qr/\x1B\x25(?:\x47|\x2F[\x47-\x49])((?:[\x20-\x7F]|(?:[\xC0-\xFD][\x80-\xBF]+))*)\x1B\x25\x40/,
22  );  );
23  %internalo = (  %_cp = (
24    94x1  => 0xE90940,    94x1  => 0xE90940,
25    94x2  => 0xE9F6C0,    94x2  => 0xE9F6C0,
26    96x1  => 0xE926A0,    96x1  => 0xE926A0,
27    jisx02081990  => 0xE9F6C0 + 94*94*79,    jisx02081990  => 0xE9F6C0 + 94*94*79,
28      ## (0xFC - 0x3F - 1) * (0xFC - 0xEF) = 2444
29      x_cp932       => 0xE000,      x_cp932_last    => 0xE000 + 2443,
30      x_imode_doti  => 0xFE000,
31      x_jsky        => 0xFFB00,
32    );
33    %_cp = (%_cp,
34      jisx0201kana  => $_cp{94x1} + 94 * (0x49-0x30),
35      jisx0201kana_last1    => $_cp{94x1} + 94 * (0x49-0x30+1) -0x21,
36      jisx0201kana_last     => $_cp{94x1} + 94 * (0x49-0x30+1) -1,
37      jisx0201latin => $_cp{94x1} + 94 * (0x4A-0x30),
38      jisx0201latin_last    => $_cp{94x1} + 94 * (0x4A-0x30+1) -1,
39      jisx02081978  => $_cp{94x2} + 94*94 * (0x40-0x30),
40      jisx02081978_last     => $_cp{94x2} + 94*94 * (0x40-0x30+1) -1,
41      jisx02081983  => $_cp{94x2} + 94*94 * (0x42-0x30),
42      jisx02081983_last     => $_cp{94x2} + 94*94 * (0x42-0x30+1) -1,
43      jisx02081990_last     => $_cp{jisx02081990} + 94*94 -1,
44      jisx02121990  => $_cp{94x2} + 94*94 * (0x44-0x30),
45      jisx02121990_last     => $_cp{94x2} + 94*94 * (0x44-0x30+1) -1,
46      jisx02132000_1        => $_cp{94x2} + 94*94 * (0x4F-0x30),
47      jisx02132000_1_last   => $_cp{94x2} + 94*94 * (0x4F-0x30+1) -1,
48      jisx02132000_2        => $_cp{94x2} + 94*94 * (0x50-0x30),
49      jisx02132000_2_last   => $_cp{94x2} + 94*94 * (0x50-0x30+1) -1,
50      ## (0xF7 - 0xEF - 1) * (0xFC - 0xEF) = 1316
51      x_doti        => $_cp{x_imode_doti},
52      x_doti_last   => $_cp{x_imode_doti} + 1316-1,
53      x_imode       => $_cp{x_imode_doti} + 1316,
54      x_imode_last  => $_cp{x_imode_doti} + 2443,
55  );  );
56  %internalo = (%internalo,  my %SJIS_G3_to_KUe = (  ## KU-1
57    jisx0201kana  => $internalo{94x1} + 94 * (0x49-0x30),          0xF0    => 7,   0xF1    => 3,   0xF2    => 11,  0xF3    => 13,
58    jisx0201kana_end      => $internalo{94x1} + 94 * (0x49-0x30+1) -1,          0xF4    => 77,  0xF5    => 79,  0xF6    => 81,  0xF7    => 83,
59    jisx0201latin => $internalo{94x1} + 94 * (0x4A-0x30),          0xF8    => 85,  0xF9    => 87,  0xFA    => 89,  0xFB    => 91,
60    jisx0201latin_end     => $internalo{94x1} + 94 * (0x4A-0x30+1) -1,          0xFC    => 93,
   jisx02081978  => $internalo{94x2} + 94*94 * (0x40-0x30),  
   jisx02081978_end      => $internalo{94x2} + 94*94 * (0x40-0x30+1) -1,  
   jisx02081983  => $internalo{94x2} + 94*94 * (0x42-0x30),  
   jisx02081983_end      => $internalo{94x2} + 94*94 * (0x42-0x30+1) -1,  
   jisx02081990_end      => $internalo{jisx02081990} + 94*94 -1,  
   jisx02121990  => $internalo{94x2} + 94*94 * (0x44-0x30),  
   jisx02121990_end      => $internalo{94x2} + 94*94 * (0x44-0x30+1) -1,  
   jisx02132000_1        => $internalo{94x2} + 94*94 * (0x4F-0x30),  
   jisx02132000_1_end    => $internalo{94x2} + 94*94 * (0x4F-0x30+1) -1,  
   jisx02132000_2        => $internalo{94x2} + 94*94 * (0x50-0x30),  
   jisx02132000_2_end    => $internalo{94x2} + 94*94 * (0x50-0x30+1) -1,  
61  );  );
62    my %SJIS_G3_to_KUo = (  ## KU-1
63            0xF0    => 0,   0xF1    => 2,   0xF2    => 4,   0xF3    => 12,
64            0xF4    => 14,  0xF5    => 78,  0xF6    => 80,  0xF7    => 82,
65            0xF8    => 84,  0xF9    => 86,  0xFA    => 88,  0xFB    => 90,
66            0xFC    => 92,
67    );      ## KU-1
68    my %_KU_to_SJIS_G3 = reverse (%SJIS_G3_to_KUe, %SJIS_G3_to_KUo);
69    
70  my %_charset_name_n11n_table = (  my %_charset_name_n11n_table = (
71    euc   => "euc-jp",    ascii => 'us-ascii',
72    "euc-japan"   => "euc-jp",    euc   => 'euc-jp',
73    "euc-jisx0208"        => "euc-jp",    'euc-japan'   => 'euc-jp',
74    "euc-jisx0213"        => "euc-jp:2000",    'euc-jisx0208'        => 'euc-jp',
75    jis   => "junet",    'euc-jisx0213'        => ['euc-jp', 2000],
76    "shift-jis"   => "shift_jis",    jis   => 'junet',
77    "shift-jisx0213"      => "shift_jis:2000",    'shift-jis'   => 'shift_jis',
78    shift_jisx0213        => "shift_jis:2000",    'shift-jisx0213'      => ['shift_jis', 2000],
79    sjis  => "shift_jis",    shift_jisx0213        => ['shift_jis', 2000],
80    "x-euc-jisx0213"      => "euc-jp:2000",    sjis  => 'shift_jis',
81    "x-euc-jp"    => "euc-jp",    'sjis-doti'   => ['shift_jis', 1997, 'doti'],
82    "x-shift_jisx0213"    => "shift_jis:2000",    'sjis-imode'  => ['shift_jis', 1997, 'imode'],
83    "x-sjis"      => "shift_jis",    'sjis-jsky'   => ['shift_jis', 1997, 'jsky'],
84      'unicode-2-0-utf-8'   => 'utf-8',
85      utf8  => 'utf-8',
86      'utf-8n'      => 'utf-8',
87      'x-euc-jisx0213'      => ['euc-jp', 2000],
88      'x-euc-jp'    => 'euc-jp',
89      'x-shift_jisx0213'    => ['shift_jis', 2000],
90      'x-sjis'      => 'shift_jis',
91      'x-sjis-doti' => ['shift_jis', 1997, 'doti'],
92      'x-sjis-imode'        => ['shift_jis', 1997, 'imode'],
93      'x-sjis-jsky' => ['shift_jis', 1997, 'jsky'],
94  );  );
95  sub _charset_name_n11n ($;$) {  sub _charset_name_n11n ($;$) {
96    my $name = lc shift;  my $year = shift;    my ($name, $year, $ext) = (shift, shift, lc shift);
97    $name = $_charset_name_n11n_table{$name} || $name;    $name = $_charset_name_n11n_table{lc $name} || $name;
98    if ($name =~ /^(.+):(\d+)$/) {    if (ref $name eq 'ARRAY') {
99      $name = $1;      ($name, $year, $ext) = @$name;
     $year ||= $2;  
100    }    }
101    ($name, $year);    (lc $name, $year, $ext);
102  }  }
103    
104  =head2 convert ($string, $output_code, $input_code, $options)  =head2 convert ($string, $output_code, $input_code, $options)
# Line 65  Convert coded charset of string. Line 108  Convert coded charset of string.
108  =cut  =cut
109    
110  sub convert ($;$$$) {  sub convert ($;$$$) {
111    my ($string, $output_code, $input_code, $options) = @_;    my ($string, $o_code, $i_code, $options) = @_;
112    $string = \$string unless ref $string;    my ($i_edition, $o_edition, $i_ext, $o_ext);
113    my ($input_edition, $output_edition);    ($i_code, $i_edition, $i_ext) = _charset_name_n11n ($i_code);
114    ($input_code, $input_edition) = _charset_name_n11n ($input_code);    ($o_code, $o_edition, $o_ext) = _charset_name_n11n ($o_code || "junet");
115    ($output_code, $output_edition) = _charset_name_n11n ($output_code || "junet");    if ($i_code eq "euc-jp") {
116    if ($input_code eq "euc-jp") {      eucjapan_to_internal ($string, -edition => $i_edition, -extension => $i_ext);
117      eucjapan_to_internal ($string, edition => $input_edition);    } elsif ($i_code eq "junet" || $i_code =~ /^iso-2022-jp/
118    } elsif ($input_code eq "junet" || $input_code =~ /^iso-2022-jp/) {      || $i_code eq 'us-ascii') {
119      junet_to_internal ($string);      junet_to_internal ($string);
120      } elsif ($i_code eq "shift_jis") {
121        shiftjis_to_internal ($string, -edition => $i_edition, -extension => $i_ext);
122    }    }
123        
124    if ($output_code eq "euc-jp") {    if ($o_code eq "euc-jp") {
125      internal_to_eucjapan ($string, edition => $output_edition);      internal_to_eucjapan ($string, -edition => $o_edition, -extension => $o_ext);
126    } elsif ($output_code eq "junet" || $output_code =~ /^iso-2022-jp/) {    } elsif ($o_code eq "junet" || $o_code =~ /^iso-2022-jp/
127        || $o_code eq 'us-ascii') {
128      internal_to_junet ($string);      internal_to_junet ($string);
129      } elsif ($o_code eq "shift_jis") {
130        internal_to_shiftjis ($string, -edition => $o_edition, -extension => $o_ext);
131    }    }
132  }  }
133    
# Line 91  Convert junet coded string to internal c Line 139  Convert junet coded string to internal c
139    
140  sub junet_to_internal ($) {  sub junet_to_internal ($) {
141    my $s = shift;    my $s = shift;
142    $s = \$s unless ref $s;    #$s = \$s unless ref $s;
143    $$s =~ s{    $s =~ s{
144      ($re{94x1} | $re{94x2} | $re{96x1} | $re{utf8})      ($re{94x1} | $re{94x2} | $re{96x1} | $re{utf8})
145    }{    }{
146      my $st = $1;      my $st = $1;
147      if ($st =~ /$re{94x1}/) {      if ($st =~ /$re{M_94x1}/) {
148        my ($f, $str) = ($1, $2);        my ($f, $str) = ($1, $2);
149        $f = unpack 'C', $f;        $f = unpack 'C', $f;
150        $f = $f == 0x42 ? 0x21 : $internalo{94x1} + 94 * ($f - 0x30);        $f = $f == 0x42 ? 0x21 : $_cp{94x1} + 94 * ($f - 0x30);
151        $str =~ s{([\x21-\x7E])}{        $str =~ s{([\x21-\x7E])}{
152          _u8($f + unpack('C', $1) - 0x21);          _u8($f + unpack('C', $1) - 0x21);
153        }goesx;        }goesx;
154        $st = $str;        $st = $str;
155      } elsif ($st =~ /$re{94x2}/) {      } elsif ($st =~ /$re{M_94x2}/) {
156        my ($rev, $f, $str) = ($1, $2, $3);        my ($rev, $f, $str) = ($1, $2, $3);
157        if ($rev eq '@' && $f eq 'B') {        if ($rev eq '@' && $f eq 'B') {
158          $f = $internalo{jisx02081990};          $f = $_cp{jisx02081990};
159        } else {        } else {
160          $f = unpack 'C', $f;          $f = unpack 'C', $f;
161          $f = $internalo{94x2} + 94*94 * ($f - 0x30);          $f = $_cp{94x2} + 94*94 * ($f - 0x30);
162        }        }
163        $str =~ s{([\x21-\x7E])([\x21-\x7E])}{        $str =~ s{([\x21-\x7E])([\x21-\x7E])}{
164          _u8($f + (unpack('C', $1) - 0x21)*94 + unpack('C', $2) - 0x21);          _u8($f + (unpack('C', $1) - 0x21)*94 + unpack('C', $2) - 0x21);
165        }goesx;        }goesx;
166        $st = $str;        $st = $str;
167      } elsif ($st =~ /$re{96x1}/) {      } elsif ($st =~ /$re{M_96x1}/) {
168        my ($f, $str) = ($1, $2);        my ($f, $str) = ($1, $2);
169        $f = unpack 'C', $f;        $f = unpack 'C', $f;
170        $f = $f == 0x41 ? 0xA0 : $internalo{96x1} + 96 * ($f - 0x30);        $f = $f == 0x41 ? 0xA0 : $_cp{96x1} + 96 * ($f - 0x30);
171        $str =~ s{([\x20-\x7F])}{        $str =~ s{([\x20-\x7F])}{
172          _u8($f + unpack('C', $1) - 0x20);          _u8($f + unpack('C', $1) - 0x20);
173        }goesx;        }goesx;
174        $st = $str;        $st = $str;
175      } elsif ($st =~ /$re{utf8}/) {      } elsif ($st =~ /$re{M_utf8}/) {
176        $st = $1;        $st = $1;
177      }      }
178      $st;      $st;
179    }goesx;    }goesx;
180    $$s;    $s;
181  }  }
182    
183  sub _u8 ($) {  sub _u8 ($) {
# Line 208  internal_to_eucjapan (\$s, jisx0201kana Line 256  internal_to_eucjapan (\$s, jisx0201kana
256    
257  sub internal_to_eucjapan ($;%) {  sub internal_to_eucjapan ($;%) {
258    my $s = shift;    my $s = shift;
259    $s = \$s unless ref $s;    #$s = \$s unless ref $s;
260    my %output = @_;    my %output = @_;
261    my $year = $output{edition} || -1;    ## -1 (= all unify), 1983, 1990 = 1997, 2000    my $year = $output{edition} || -1;    ## -1 (= all unify), 1983, 1990 = 1997, 2000
262    $output{jisx02081978} = 1 if $year < 1983;    $output{jisx02081978} = 1 if $year < 1983;
# Line 218  sub internal_to_eucjapan ($;%) { Line 266  sub internal_to_eucjapan ($;%) {
266    $output{jisx02132000_1} = 1 if $year == -1 || (2000 <= $year);    $output{jisx02132000_1} = 1 if $year == -1 || (2000 <= $year);
267    $output{jisx02132000_2} = 1 if $year == -1 || (2000 <= $year);    $output{jisx02132000_2} = 1 if $year == -1 || (2000 <= $year);
268    $output{undefchar} ||= "\xA2\xAE";    $output{undefchar} ||= "\xA2\xAE";
269    $$s =~ s{([\xC0-\xFF][\x80-\xBF]*)}{    $s =~ s{([\xC0-\xFF][\x80-\xBF]*)}{
270      my $char = $1;  my $code = _ucode($char);  my $ret = "";      my $char = $1;  my $code = _ucode($char);  my $ret = "";
271      if ($code < 0x7F) { ## G0 = ASCII      if ($code < 0x7F) { ## G0 = ASCII
272        $ret = pack("C", $code);        $ret = pack("C", $code);
273      } elsif ($output{jisx0201latin} && $internalo{jisx0201latin} < $code      } elsif ($output{jisx0201latin} && $_cp{jisx0201latin} < $code
274        && $code < $internalo{jisx0201latin_end}) {       ## G0 = JIS X 0201 latin        && $code < $_cp{jisx0201latin_last}) {    ## G0 = JIS X 0201 latin
275        $ret = pack("C", $code - $internalo{jisx0201latin} + 0x21);        $ret = pack("C", $code - $_cp{jisx0201latin} + 0x21);
276      } elsif ($output{jisx02081978}      } elsif ($output{jisx02081978}
277        && ($internalo{jisx02081978} < $code && $code < $internalo{jisx02081978_end})        && ($_cp{jisx02081978} < $code && $code < $_cp{jisx02081978_last})
278        ) {       ## G1 = JIS X 0208-1978        ) {       ## G1 = JIS X 0208-1978
279        my $ku = $code - $internalo{jisx02081978};        my $ku = $code - $_cp{jisx02081978};
280        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;
281        $ret = pack("CC", $ku, $ten);        $ret = pack("CC", $ku, $ten);
282      } elsif ($output{jisx02081983}      } elsif ($output{jisx02081983}
283        && ($internalo{jisx02081983} < $code && $code < $internalo{jisx02081983_end})        && ($_cp{jisx02081983} < $code && $code < $_cp{jisx02081983_last})
284        ) {       ## G1 = JIS X 0208-1983        ) {       ## G1 = JIS X 0208-1983
285        my $ku = $code - $internalo{jisx02081983};        my $ku = $code - $_cp{jisx02081983};
286        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;
287        $ret = pack("CC", $ku, $ten);        $ret = pack("CC", $ku, $ten);
288      } elsif ($output{jisx02081990}      } elsif ($output{jisx02081990}
289        && ($internalo{jisx02081990} < $code && $code < $internalo{jisx02081990_end})        && ($_cp{jisx02081990} < $code && $code < $_cp{jisx02081990_last})
290        ) {       ## G1 = JIS X 0208-1990 / JIS X 0208:1997        ) {       ## G1 = JIS X 0208-1990 / JIS X 0208:1997
291        my $ku = $code - $internalo{jisx02081990};        my $ku = $code - $_cp{jisx02081990};
292        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;
293        $ret = pack("CC", $ku, $ten);        $ret = pack("CC", $ku, $ten);
294      } elsif ($output{jisx02132000_1}      } elsif ($output{jisx02132000_1}
295      && ($internalo{jisx02132000_1} < $code && $code < $internalo{jisx02132000_1_end})      && ($_cp{jisx02132000_1} < $code && $code < $_cp{jisx02132000_1_last})
296        ) {       ## G1 = JIS X 0213:2000 plane 1        ) {       ## G1 = JIS X 0213:2000 plane 1
297        my $ku = $code - $internalo{jisx02132000_1};        my $ku = $code - $_cp{jisx02132000_1};
298        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;
299        $ret = pack("CC", $ku, $ten);        $ret = pack("CC", $ku, $ten);
300      } elsif ($output{jisx0201kana} && $internalo{jisx0201kana} < $code      } elsif ($output{jisx0201kana} && $_cp{jisx0201kana} < $code
301        && $code < $internalo{jisx0201kana_end}) {        ## G2 = JIS X 0201 katakana        && $code < $_cp{jisx0201kana_last}) {     ## G2 = JIS X 0201 katakana
302        $ret = "\x8E" . pack("C", $code - $internalo{jisx0201kana} + 0xA1);        $ret = "\x8E" . pack("C", $code - $_cp{jisx0201kana} + 0xA1);
303      } elsif ($output{jisx02121990}      } elsif ($output{jisx02121990}
304      && ($internalo{jisx02121990} < $code && $code < $internalo{jisx02121990_end})      && ($_cp{jisx02121990} < $code && $code < $_cp{jisx02121990_last})
305        ) {       ## G3 = JIS X 0213:2000 plane 2        ) {       ## G3 = JIS X 0213:2000 plane 2
306        my $ku = $code - $internalo{jisx02121990};        my $ku = $code - $_cp{jisx02121990};
307        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;
308        $ret = "\x8F" . pack("CC", $ku, $ten);        $ret = "\x8F" . pack("CC", $ku, $ten);
309      } elsif ($output{jisx02132000_2}      } elsif ($output{jisx02132000_2}
310      && ($internalo{jisx02132000_2} < $code && $code < $internalo{jisx02132000_2_end})      && ($_cp{jisx02132000_2} < $code && $code < $_cp{jisx02132000_2_last})
311        ) {       ## G3 = JIS X 0213:2000 plane 2        ) {       ## G3 = JIS X 0213:2000 plane 2
312        my $ku = $code - $internalo{jisx02132000_2};        my $ku = $code - $_cp{jisx02132000_2};
313        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;        my $ten = ($ku % 94) + 0xA1; $ku = int($ku / 94) + 0xA1;
314        $ret = "\x8F" . pack("CC", $ku, $ten);        $ret = "\x8F" . pack("CC", $ku, $ten);
315      } else {      } else {
# Line 269  sub internal_to_eucjapan ($;%) { Line 317  sub internal_to_eucjapan ($;%) {
317      }      }
318      $ret;      $ret;
319    }goex;    }goex;
320    $$s;    $s;
321  }  }
322    
323  =head2 internal_to_junet ($sering, [%option])  =head2 internal_to_junet ($sering, [%option])
# Line 285  Convert internal coded string to junet c Line 333  Convert internal coded string to junet c
333    
334  sub internal_to_junet ($;%) {  sub internal_to_junet ($;%) {
335    my $s = shift;    my $s = shift;
336    $s = \$s unless ref $s;    #$s = \$s unless ref $s;
337    my %output = @_;  my $mode = "\x1B\x28\x42";    my %output = @_;  my $mode = "\x1B\x28\x42";
338    $output{undefchar} ||= 0x3F-0x21;    $output{undefchar} ||= 0x3F-0x21;
339    $output{undefcharset} ||= "\x1B\x28\x42";    $output{undefcharset} ||= "\x1B\x28\x42";
340    $$s =~ s{([\x00-\x7F]|(?:[\xC0-\xFF][\x80-\xBF]*))}{    $s =~ s{([\x00-\x7F]|(?:[\xC0-\xFF][\x80-\xBF]*))}{
341      my $char = $1;  my $code = _ucode($char);  my $ret = "";      my $char = $1;  my $code = _ucode($char);  my $ret = "";
342      if ($code < 0x9F) { ## ASCII      if ($code < 0x9F) { ## ASCII
343        $ret = _2022_putchar(\$mode => "\x1B\x28\x42", $code-0x21);        $ret = _2022_putchar(\$mode => "\x1B\x28\x42", $code-0x21);
344      } elsif ($code < 0xFF) {    ## ISO 8859-1 right half      } elsif ($code < 0xFF) {    ## ISO 8859-1 right half
345        $ret = _2022_putchar(\$mode => "\x1B\x2C\x41", $code-0xA0);        $ret = _2022_putchar(\$mode => "\x1B\x2C\x41", $code-0xA0);
346      } elsif ($internalo{94x1} < $code && $code < $internalo{94x1} + 94*78 -1) {      } elsif ($_cp{94x1} < $code && $code < $_cp{94x1} + 94*78 -1) {
347          ## 94 charsets          ## 94 charsets
348        my $final = pack("C", int(($code - $internalo{94x1}) / 94) + 0x30);        my $final = pack("C", int(($code - $_cp{94x1}) / 94) + 0x30);
349        $ret = _2022_putchar(\$mode => "\x1B\x28".$final,        $ret = _2022_putchar(\$mode => "\x1B\x28".$final,
350                             ($code - $internalo{94x1}) % 94);                             ($code - $_cp{94x1}) % 94);
351      } elsif ($output{g0_96}      } elsif ($output{g0_96}
352        && $internalo{96x1} < $code && $code < $internalo{96x1} + 96*78 -1) {        && $_cp{96x1} < $code && $code < $_cp{96x1} + 96*78 -1) {
353          ## 96 charsets          ## 96 charsets
354        my $final = pack("C", int(($code - $internalo{96x1}) / 96) + 0x30);        my $final = pack("C", int(($code - $_cp{96x1}) / 96) + 0x30);
355        $ret = _2022_putchar(\$mode => "\x1B\x2C".$final,        $ret = _2022_putchar(\$mode => "\x1B\x2C".$final,
356                             ($code - $internalo{96x1}) % 96);                             ($code - $_cp{96x1}) % 96);
357      } elsif ($internalo{94x2} < $code && $code < $internalo{94x2} + 94*94*78 -1) {      } elsif ($_cp{94x2} < $code && $code < $_cp{94x2} + 94*94*78 -1) {
358          ## 94x2 charsets          ## 94x2 charsets
359        my $final = pack("C", int(($code - $internalo{94x2}) / (94*94)) + 0x30);        my $final = pack("C", int(($code - $_cp{94x2}) / (94*94)) + 0x30);
360        $ret = _2022_putchar(\$mode => "\x1B\x24\x28".$final,        $ret = _2022_putchar(\$mode => "\x1B\x24\x28".$final,
361                             ($code - $internalo{94x2}) % (94*94));                             ($code - $_cp{94x2}) % (94*94));
362      } elsif ($internalo{jisx02081990} < $code      } elsif ($_cp{jisx02081990} < $code
363            && $code < $internalo{jisx02081990} + 94*94 -1) {            && $code < $_cp{jisx02081990} + 94*94 -1) {
364        $ret = _2022_putchar(\$mode => "\x1B\x26\x40\x1B\x24B",        $ret = _2022_putchar(\$mode => "\x1B\x26\x40\x1B\x24B",
365                             ($code - $internalo{94x2}) % (94*94));                             ($code - $_cp{94x2}) % (94*94));
366      } elsif ($output{utf8}) {      } elsif ($output{utf8}) {
367        $ret = _2022_putchar(\$mode => "\x1B\x25G", $char)        $ret = _2022_putchar(\$mode => "\x1B\x25G", $char)
368      } else {      } else {
# Line 322  sub internal_to_junet ($;%) { Line 370  sub internal_to_junet ($;%) {
370      }      }
371      $ret;      $ret;
372    }goesx;    }goesx;
373    $$s;    $s .= _2022_putchar (\$mode => "\x1B\x28\x42" => '');
374      $s;
375  }  }
376  sub _2022_putchar ($$$) {  sub _2022_putchar ($$$) {
377    my ($mode, $newmode, $char) = @_;    my ($mode, $newmode, $char) = @_;
# Line 333  sub _2022_putchar ($$$) { Line 382  sub _2022_putchar ($$$) {
382      if ($$mode eq "\x1B\x25G") {      if ($$mode eq "\x1B\x25G") {
383        $ret = "\x1B\x25\x40\x1B\x28\x42";        $ret = "\x1B\x25\x40\x1B\x28\x42";
384      }      }
385      if ($is{multibyte} || $is{set96} || $newmode eq "\x1B\x25G") {      if (($is{multibyte} && $newmode ne "\x1B\x24\x28\x42"
386        $ret .= "\x1B\x28\x42";                          && $newmode ne "\x1B\x24\x28\x40")
387         || $is{set96} || $newmode eq "\x1B\x25G") {
388        ## If it is not well-known escape sequence(s),
389        ## designate ASCII for safe.
390          $ret .= "\x1B\x28\x42" unless $$mode eq "\x1B\x28\x42";
391      }      }
392      if ($newmode =~ /\x1B\x24\x28([\x40-\x42])/) {      if ($newmode =~ /\x1B\x24\x28([\x40-\x42])/) {
393        $ret .= "\x1B\x24$1";        $ret .= "\x1B\x24$1";
# Line 343  sub _2022_putchar ($$$) { Line 396  sub _2022_putchar ($$$) {
396      }      }
397      $$mode = $newmode;      $$mode = $newmode;
398    }    }
399      if (length $char) {
400    if ($is{multibyte} && $is{set96}) {   ## 96x2    if ($is{multibyte} && $is{set96}) {   ## 96x2
401      $ret .= pack("CC", int($char / 96) + 0x20, ($char % 96) + 0x20);      $ret .= pack("CC", int($char / 96) + 0x20, ($char % 96) + 0x20);
402    } elsif ($is{multibyte}) {    ## 94x2    } elsif ($is{multibyte}) {    ## 94x2
# Line 354  sub _2022_putchar ($$$) { Line 408  sub _2022_putchar ($$$) {
408    } else {      ## 94x1    } else {      ## 94x1
409      $ret .= pack("C", $char + 0x21);      $ret .= pack("C", $char + 0x21);
410    }    }
411      }
412    $ret;    $ret;
413  }  }
414    
415  sub eucjapan_to_internal ($;%) {  sub eucjapan_to_internal ($;%) {
416    my $s = shift;    my $s = shift;
   $s = \$s unless ref $s;  
417    my %option = @_;    my %option = @_;
418    my $year = $option{edition} || 2000;  ## 1978, 1983, 1990=1997, 2000    my $year = $option{edition} || 2000;  ## 1978, 1983, 1990=1997, 2000
419    $option{G0start} ||= 0x21;  $option{G2start} ||= $internalo{jisx0201kana};    $option{G0start} ||= 0x21;  $option{G2start} ||= $_cp{jisx0201kana};
420    if ($option{G1start} && $option{G3start}) {}    if ($option{G1start} && $option{G3start}) {}
421    elsif ($year < 1983)    elsif ($year < 1983)
422      {$option{G1start} ||= $internalo{jisx02081978}; $option{G3start} ||= -1}      {$option{G1start} ||= $_cp{jisx02081978}; $option{G3start} ||= -1}
423    elsif (1983 <= $year && $year < 1990)    elsif (1983 <= $year && $year < 1990)
424      {$option{G1start} ||= $internalo{jisx02081983}; $option{G3start} ||= -1}      {$option{G1start} ||= $_cp{jisx02081983}; $option{G3start} ||= -1}
425    elsif (1990 <= $year && $year < 2000)    elsif (1990 <= $year && $year < 2000)
426      {$option{G1start} ||= $internalo{jisx02081990}; $option{G3start} ||= -1}      {$option{G1start} ||= $_cp{jisx02081990}; $option{G3start} ||= -1}
427    else #elsif (2000 <= $year)    else #elsif (2000 <= $year)
428      {$option{G1start} ||= $internalo{jisx02132000_1}; $option{G3start} ||= -1}      {$option{G1start} ||= $_cp{jisx02132000_1}; $option{G3start} ||= -1}
429    $$s =~ s{([\x21-\x7E]|\x8E[\xA1-\xFE]|\x8F?[\xA1-\xFE][\xA1-\xFE])}{    $s =~ s{([\x21-\x7E]|\x8E[\xA1-\xFE]|\x8F?[\xA1-\xFE][\xA1-\xFE])}{
430      my $char = $1;  my $ret = "";      my $char = $1;  my $ret = "";
431      if ($char =~ /[\x21-\x7E]/) {      if ($char =~ /[\x21-\x7E]/) {
432        $ret = _u8(unpack("C", $char) - 0x21 + $option{G0start});        $ret = _u8(unpack("C", $char) - 0x21 + $option{G0start});
# Line 382  sub eucjapan_to_internal ($;%) { Line 436  sub eucjapan_to_internal ($;%) {
436        if ($option{G3start} == -1) {        if ($option{G3start} == -1) {
437          if (77 <= $ku || $ku == 0 || $ku == 2 || $ku == 3 || $ku == 4          if (77 <= $ku || $ku == 0 || $ku == 2 || $ku == 3 || $ku == 4
438            || $ku == 7 || $ku == 11 || $ku == 12 || $ku == 13 || $ku == 14) {            || $ku == 7 || $ku == 11 || $ku == 12 || $ku == 13 || $ku == 14) {
439            $ret = _u8($ku * 94 + $ten + $internalo{jisx02132000_2});            $ret = _u8($ku * 94 + $ten + $_cp{jisx02132000_2});
440          } else {          } else {
441            $ret = _u8($ku * 94 + $ten + $internalo{jisx02121990});            $ret = _u8($ku * 94 + $ten + $_cp{jisx02121990});
442          }          }
443        } else {        } else {
444          $ret = _u8($ku * 94 + $ten + $option{G3start});          $ret = _u8($ku * 94 + $ten + $option{G3start});
# Line 398  sub eucjapan_to_internal ($;%) { Line 452  sub eucjapan_to_internal ($;%) {
452      }      }
453      $ret;      $ret;
454    }goex;    }goex;
455      $s;
456  }  }
457    
458  =head1 NAME  =item M17N::Code::JA::shiftjis_to_internal ($string, [%options])
459    
460  M17N::Code::JA --- Japanese string coding system convertion  Converts string from shift-jis to internal code.
461    
462  =head1 LICENSE  Available options:
463    
464    =over 4
465    
466    =item -edition => 1978 / 1983 / 1990 / 2000
467    
468    Edition of double byte character set (Default: 2000)
469    
470    =item -extension => [none] / cp932 / mac / imode / doti / jsky
471    
472    Type of private (non official) extension  (Default: no private extensions)
473    
474    =back
475    
476    This program is free software; you can redistribute it and/or  =cut
477    modify it under the same terms as Perl itself.  
478    ## G0 = 0x21-0x7E
479    ## G1 = 0xA1-0xDE
480    ## G2 = 0x8141-0x9FFC, 0xE041-0xEFFC
481    ## G3 = 0xF041-0xFCFC
482    my %S2I;        ## cache
483    sub shiftjis_to_internal ($;%) {
484      my $s = shift;  my %o = @_;
485      my $year = $o{-edition} || 2000;
486      my $legacy = 0;       ## legacy variants before X0213 G3
487      $o{-G0start} ||= 0x21;  $o{-G1start} ||= $_cp{jisx0201kana};
488      if ($o{-G2start} && $o{-G3start}) {}
489      elsif ($year < 1983)
490        {$o{-G2start} ||= $_cp{jisx02081978}; $o{-G3start} ||= $_cp{jisx02132000_2}}
491      elsif (1983 <= $year && $year < 1990)
492        {$o{-G2start} ||= $_cp{jisx02081983}; $o{-G3start} ||= $_cp{jisx02132000_2}}
493      elsif (1990 <= $year && $year < 2000)
494        {$o{-G2start} ||= $_cp{jisx02081990}; $o{-G3start} ||= $_cp{jisx02132000_2}}
495      else #elsif (2000 <= $year)
496        {$o{-G2start} ||= $_cp{jisx02132000_1}; $o{-G3start} ||= $_cp{jisx02132000_2}}
497      if ($o{-extension} eq 'imode' || $o{-extension} eq 'doti') {
498        $o{-G3start} = $_cp{x_imode_doti}; $legacy = 1;
499      }
500      $s =~ s{
501              ([\x21-\x7E])
502            | ([\x81-\x9F\xE0-\xEF][\x40-\x7E\x80-\xFC])
503            | ([\xF0-\xFC][\x40-\x7E\x80-\xFC])
504            | ([\xA1-\xDF])
505            | ([\x80-\xFF])
506      }{
507        my ($g0, $g2, $g3, $g1, $broken) = ($1, $2, $3, $4, $5);
508        my $ret = '';
509        if ($g0) {
510          $S2I{$g0}->{$o{-G0start}} = _u8(unpack('C', $g0) - 0x21 + $o{-G0start})
511            unless $S2I{$g0}->{$o{-G0start}};
512          $ret = $S2I{$g0}->{$o{-G0start}};
513        } elsif ($g2) {
514          unless ($S2I{$g2}->{$o{-G2start}}) {
515            my ($f, $s) = unpack ('CC', $g2);
516            if (0x9E < $s) {
517              $f = $f * 2 - ($f >= 0xE0 ? 0x181 : 0x101);  $s -= 0x9F;
518            } else {
519              $f = $f * 2 - ($f >= 0xE0 ? 0x182 : 0x102);  $s -= 0x40 + ($s > 0x7F);
520            }
521            $S2I{$g2}->{$o{-G2start}} = _u8 ($f * 94 + $s + $o{-G2start});
522          }
523          $ret = $S2I{$g2}->{$o{-G2start}};
524        } elsif ($g3) {
525          unless ($S2I{$g3}->{$o{-G3start}}) {
526            my ($f, $s) = unpack ('CC', $g3);
527            if ($legacy) {
528              $s -= 0x40 + ($s > 0x7F);
529              $S2I{$g3}->{$o{-G3start}} = _u8 (($f - 0xF0) * 188 + $s + $o{-G3start});
530            } else {        ## X0213
531              if (0x9F <= $s) {
532                $f = $SJIS_G3_to_KUe{$f};  $s -= 0x9F;
533              } else {
534                $f = $SJIS_G3_to_KUo{$f};  $s -= 0x40 + ($s > 0x7F);
535              }
536              $S2I{$g3}->{$o{-G3start}} = _u8 ($f * 94 + $s + $o{-G3start});
537            }
538          }
539          $ret = $S2I{$g3}->{$o{-G3start}};
540        } elsif ($g1) {
541          $S2I{$g1}->{$o{-G1start}} = _u8(unpack('C', $g1) - 0xA1 + $o{-G1start})
542            unless $S2I{$g1}->{$o{-G1start}};
543          $ret = $S2I{$g1}->{$o{-G1start}};
544        }
545        $ret;
546      }gex;
547      $s;
548    }
549    
550    =item $s = M17N::Code::JA::internal_to_shiftjis ($s, [%options])
551    
552    Converts internal coded string to shift-jis coded string.
553    
554    =cut
555    
556    my (%_I2S_1, %_I2S_2, %_I2S_2L, %_I2S); ## caches
557    sub internal_to_shiftjis ($;%) {
558      my $s = shift;  my %o = @_;
559      my $year = $o{-edition};      ## 0 (= all unify), 1983, 1990 = 1997, 2000
560      $o{-x0201_latin} ||= 1;  $o{-x0201_katakana} ||= 1;
561      $o{-x0208_78} = 1 if $year < 1983;
562      $o{-x0208_83} = 1 if !$year || (1983 <= $year && $year < 1990);
563      $o{-x0208_90} = 1 if !$year || (1990 <= $year && $year < 2000);
564      if (!$year || ($year >= 2000)) {
565        $o{-x0213_A0_1} = 1; $o{-x0213_A0_2} = 1;
566      }
567      if ($o{-extension}) { ## one of private extensions
568        $o{-x0213_A0_2} = 0;  $o{ '-' . $o{-extension} } = 1;
569      }
570      $o{-undefchar} ||= "\x81\xAC";
571      $s =~ s{([\xC0-\xFF][\x80-\xBF]*)}{
572        my ($code, $ret) = (_ucode($1), '');
573        #if ($code < 0x7F) {        ## G0 = ASCII
574        #  $ret = pack("C", $code);
575        #} els
576        if ($o{-x0201_latin}
577          && $_cp{jisx0201latin} <= $code && $code < $_cp{jisx0201latin_last}) {
578          $_I2S{$code} = pack("C", $code - $_cp{jisx0201latin} + 0x21)
579            unless $_I2S{$code};
580          $ret = $_I2S{$code};
581        } elsif ($o{-x0208_78}
582          && $_cp{jisx02081978} <= $code && $code < $_cp{jisx02081978_last}) {
583          $code -= $_cp{jisx02081978};
584          unless ($_I2S_1{$code}) {
585            my ($c1, $c2) = (int($code / 94) + 0x21, ($code % 94) + 0x21);
586            $_I2S_1{$code} = pack('CC', (($c1 - 1) >> 1) + ($c1 < 0x5F ? 0x71 : 0xb1),
587                   $c2 + (($c1 & 1) ? ($c2 < 0x60 ? 0x1F : 0x20) : 0x7E));
588          }
589          $ret = $_I2S_1{$code};
590        } elsif ($o{-x0208_83}
591          && $_cp{jisx02081983} <= $code && $code < $_cp{jisx02081983_last}) {
592          $code -= $_cp{jisx02081983};
593          unless ($_I2S_1{$code}) {
594            my ($c1, $c2) = (int($code / 94) + 0x21, ($code % 94) + 0x21);
595            $_I2S_1{$code} = pack('CC', (($c1 - 1) >> 1) + ($c1 < 0x5F ? 0x71 : 0xb1),
596                   $c2 + (($c1 & 1) ? ($c2 < 0x60 ? 0x1F : 0x20) : 0x7E));
597          }
598          $ret = $_I2S_1{$code};
599        } elsif ($o{-x0208_90}
600          && $_cp{jisx02081990} <= $code && $code < $_cp{jisx02081990_last}) {
601          $code -= $_cp{jisx02081990};
602          unless ($_I2S_1{$code}) {
603            my ($c1, $c2) = (int($code / 94) + 0x21, ($code % 94) + 0x21);
604            $_I2S_1{$code} = pack('CC', (($c1 - 1) >> 1) + ($c1 < 0x5F ? 0x71 : 0xb1),
605                   $c2 + (($c1 & 1) ? ($c2 < 0x60 ? 0x1F : 0x20) : 0x7E));
606          }
607          $ret = $_I2S_1{$code};
608        } elsif ($o{-x0213_A0_1}
609        && $_cp{jisx02132000_1} <=$code && $code < $_cp{jisx02132000_1_last}) {
610          $code -= $_cp{jisx02132000_1};
611          unless ($_I2S_1{$code}) {
612            my ($c1, $c2) = (int($code / 94) + 0x21, ($code % 94) + 0x21);
613            $_I2S_1{$code} = pack('CC', (($c1 - 1) >> 1) + ($c1 < 0x5F ? 0x71 : 0xb1),
614                   $c2 + (($c1 & 1) ? ($c2 < 0x60 ? 0x1F : 0x20) : 0x7E));
615          }
616          $ret = $_I2S_1{$code};
617        } elsif ($o{-x0201_katakana}
618          && $_cp{jisx0201kana} <= $code && $code < $_cp{jisx0201kana_last1}) {
619          $_I2S{$code} = pack("C", $code - $_cp{jisx0201kana} + 0xA1)
620            unless $_I2S{$code};
621          $ret = $_I2S{$code};
622        } elsif ($o{-x0213_A0_2}
623          && ($_cp{jisx02132000_2} <= $code && $code < $_cp{jisx02132000_2_last})) {
624          $code -= $_cp{jisx02132000_2};
625          unless ($_I2S_2{$code}) {
626            my ($c1, $c2) = (int($code / 94), ($code % 94) + 0x21);
627            $_I2S_2{$code} = pack('CC', $_KU_to_SJIS_G3{ $c1 },
628                   $c2 + (($c1 & 1) ? 0x7E : ($c2 < 0x60 ? 0x1F : 0x20)));
629          }
630          $ret = $_I2S_2{$code};
631        } elsif ($o{-imode} && $_cp{x_imode} <= $code && $code < $_cp{x_imode_last}) {
632          $code -= $_cp{x_imode_doti};
633          unless ($_I2S_2L{$code}) {
634            my $c2 = $code % 188;  $_I2S_2L{$code} = pack('CC',
635              int($code / 188) + 0xF0, $c2 + ($c2 > 0x3E ? 0x41 : 0x40));
636          }
637          $ret = $_I2S_2L{$code};
638        } elsif ($o{-doti} && $_cp{x_doti} <= $code && $code < $_cp{x_doti_last}) {
639          $code -= $_cp{x_imode_doti};
640          unless ($_I2S_2L{$code}) {
641            my $c2 = $code % 188;  $_I2S_2L{$code} = pack('CC',
642              int($code / 188) + 0xF0, $c2 + ($c2 > 0x3E ? 0x41 : 0x40));
643          }
644          $ret = $_I2S_2L{$code};
645        } else {
646          $ret = $o{-undefchar};
647        }
648        $ret;
649      }goex;
650      $s;
651    }
652    
653    =head1 SEE ALSO
654    
655    =over 4
656    
657    =item ASTEL Emoji
658    
659    <http://www.ttnet.co.jp/tokyodenwa_astel/doti/siyou/emoji.htm>
660    
661    =back
662    
663    =head1 LICENSE
664    
665  =head1 AUTHOR  This program is free software; you can redistribute it and/or
666    modify it under the same terms as Perl itself.
667    
668  wakaba <wakaba@suika.fam.cx>  =head1 CHANGE
669    
670  $Id$  See F<ChangeLog>.
671    $Date$
672    
673  =cut  =cut
674    

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24