WindowsでJISコード

巷ではシフトJISが嫌だ、みたいな話が多いですが、今回はシフトが付かないJISの話です。正式名称は大体ISO-2022-JPという名前です。もう知らない人も多いと思いますが、電子メールの世界ではまだ使用されているコードだったりします。

2024年2月9日現在、日本語Windowsのデフォルトシステムロケールでコードページは932ですが、一応別のコードページ50220〜50222でJISコードを扱うことが出来るので、それを調べてみるというのが今回のお題です。

目的

コードページ50220〜50222、特に50221についてどんなコードなのかを調査すること。

背景

何か古すぎて知らない人が多い上に、なぜか知りたがる人がいるようなので、少しまとめるべきか?と思った次第です。過去にまとめられている資料も多くあるのですが、特にコード付きで確認できる資料があまりないようなので、それを念頭にまとめてみたいと思います。

前提

文字コードの歴史

Windows3.1以前の日本語文字コードは文字コードが乱立しており、同じ文字コードでも機種依存が多く、統一されていなかった。そんな中、広く世界的に文字コードの統一を試みていたのがISO-2022だった。

ISO-2022

ISO-2022は文字コードをエスケープシーケンスなどで切り替えて全世界の文字を扱えるようにする、という方法を取っている。当時の通信手段を考慮して、原則最上位bitを使用せず7bitだけで伝送できるようになっている。

今回調査しようとしているJISコードとは、このISO-2022の日本語用の派生であり、ISO-2022-JPが正式名称になっている。ISO-2022-JPでは切り替える7bit文字セットを2つ持っていて、1つが1byteの文字セットであるJIS X 201、もう1つが2byteの文字セットであるJIS X 208である。

文字セットはJISが規定しており、西暦とともにいくつかの版があるが、切り替えるエスケープシーケンスが版ごとに異なっている。

文字セットについて

文字セットが規定しているのはエンコーディングではなく(最近はあまり区別がないが)、文字自体の定義で、この文字セットのこの番号はこの文字みたいな決め方になっている。そして、1バイト文字セットは日本語だと半角で、英数字や記号や半角カタカナが該当する。日本語だと2バイト文字セットが全角で、漢字と記号などが色々入っている。

そして日本語だとJISが規定した文字以外の文字を空いている番号に割り振ったのが悪名高い機種依存文字である。元をただすとこの時代に作られたもの。基本的に漢字など全角文字を拡張しているので、JIS X 208の空いている番号を使っている。異なる機種でその文字を出そうとすると、存在しないので文字化けするわけである。

Windows 3.1の到来

庶民が使える初のGUIのOSがWindows 3.1である。それまでに普及していたx86系の16bit CPUを持つ機種はMS-DOSが大抵動くようになっており、その上でGUIまで共通して動くOSがWindows 3.1だった。それまでのOSは今のLinuxのようにCLIしか持っておらず、しかもその上で起動するアプリケーションがデバイスを直接操作してグラフィックを表示させていた。なので、プログラムを作っても計算用途でない限り、ほとんど全てのプログラムがその機種でしか動かなかった。しかしWindows 3.1はGUIでもOSが提供するライブラリ(API)を使うことで、どの機種でも動くようになった。

これはそれまでの機種依存文字の意味が大幅に変わるという意味である。

シフトJIS(CP932/Windows-31J)

Windows 3.1の土台であるMS-DOSでも日本語をCLIで共通に扱えるように、シフトJISコードを用意していた(他にも関わった人や会社はある)。CLIには当時機種依存する漢字ROMに依存した表示をしており、機種固有の文字を表示できる代わりに他の機種では文字化けするのもやむなしという形を取っていた。つまり機種依存文字を除けば、JISの規格の文字と可換なコード体型であるということである。

シフトJIS2バイトコードからJIS X 208区点を算出する

実際に可換であることを示すためにコードを提示する。

https://www.kijineko.co.jp/7-3-%E3%82%B7%E3%83%95%E3%83%88jis%E3%81%AE2%E3%83%90%E3%82%A4%E3%83%88%E6%96%87%E5%AD%97%E2%87%94%E5%8C%BA%E7%82%B9%E7%95%AA%E5%8F%B7-jis-euc-jp%E5%A4%89%E6%8F%9B/

上のリンク先にコードがある。ちなみに区点とはコードの1バイト目を区、2バイト目を点と呼んでるだけ。実際に可換なことが分かると思う。

Microsoftコードページ932へ

話を戻してWindows 3.1はROMではなくフォントを使って任意の文字を表示することができる。それまでの漢字ROMに依存しない表示が可能ということで、Windowsが動けばどこでもその文字が表示できる。Windows 3.1でも日本語にはMS-DOS同様シフトJISが採用されるが、ご存知のとおり、Windowsでは文字コードをコードページと呼んでおり、正式名称をMicrosoftコードページ932と変え、IANAにもWindows-31Jで登録した。この際に機種依存文字の取捨選択が行われ、それぞれ名称と番号が与えられ、Windows-31Jで正式に以下の文字が追加された(上記リンク先より引用)。

  • NEC特殊文字(13区83文字)
  • NEC選定IBM拡張文字(89 – 92区374文字)
  • IBM拡張文字(115 – 119区388文字)

これらが(当時の機種とは違うが)、Windows固有の文字ということになる。

なお、以下のサイトによると、機種依存文字の中には外字と呼ばれるユーザー定義の文字が入る枠もあり、それらは文字コードとして番号があるが、文字自体は定義されていない(95~114区)。

Windows-31J の文字セット
https://www2d.biglobe.ne.jp/~msyk/charcode/cp932/Windows-31J-charset.html

その後のシフトJIS

Unicodeが登場し、それまでのISO-2022のようなエスケープシーケンスによる切り替えを必要としない世界中の文字コードを統一する動きが起きてきて、Windowsもその潮流に乗っている。その間もJISは文字セットを相変わらず規定しており、Windows固有の機種依存文字を取り込むべくJIS X 212JIS X 213を出している。それらはUnicodeに取り込まれており、JIS規格が決めた参考エンコーディングとしてのShift_JIS-2004もあるが、IANAへの登録もされておらず、当のWindowsが互換性がないと実装していない(JIS X 213のリンク先より)ので、絵に描いた餅である。

Unicode時代

現代ではUnicodeが標準になっており、他の文字コードは利用自体が推奨されていない。Unicode以前にはシフトJIS以外にもEUC-JPやISO-2022-JPなど日本語を扱える文字コードが複数存在していたが、現在はシフトJISを除いた他の文字セットは見る影もない。冒頭に書いたとおり、電子メールでISO-2022-JPが使用されることがある程度である(電子メールも最近はUTF-8が主流)。

先のMicrosoftがShift_JIS-2004に対応しないのも、Unicodeへの移行を促す意味があると推察する。Windowsは内部的にはUnicode(ワイド文字列)で動いており、ロケール設定に従い、必要に応じてマルチバイトで出力するだけである。その意味でマルチバイトは(ほぼ変換の要らない)UTF-8のみあれば十分で、シフトJISを含むそれ以外のマルチバイトなエンコーディングは不要なのだ。

ISO-2022-JP

そういう歴史的経緯の中、ISO-2022-JPを改めて見る。ISO-2022-JPは元来、

  • ISO-2022のサブセットで、ASCIIと日本語の文字(JIS X 201/JIS X 208)が使える
  • 半角仮名が使えない
  • (本来)機種依存文字が使えない
  • 8bit禁止
  • 電子メールで使用されるが、それ以外ではあまり使用されない

という特徴があった。しかし、WindowsのOutlookでは仕様にない半角カナのエスケープシーケンスを使って半角カナを送ったり、機種依存文字も構わず送信してしまうため、Macなどで文字化けで見れないといった現象が起こっていた。

ISO-2022-JP-1

こうしたこともあり、(機種依存文字を含む)JIS X 212を取り込んだISO-2022-JP-1が作成された。このエンコーディングはRFC 2237で、作成したのがMicrosoftであることから恐らく、今回調査対象となるコードページ50220〜50222に近いのではないかと考える。なお、このエンコーディングはiconvには存在していない。IANAでは以下のリンク先にISO-2022-JPのsee alsoで先のRFC-2237がリンクされている。

https://www.iana.org/assignments/character-sets/character-sets.xhtml

ISO-2022-JP-2

他にISO-2022-JP-2というのもある。内容的にはISO-2022-JP-1に加えてKS X 1001(韓国)、GB 2312(中国)、ISO 8859-1(ラテン)、ISO 8859-7(ギリシア)が追加されたもの。ただ時系列的にはISO-2022-JP-1より古く見える。RFC 1554で規定されており、IANAにも登録されており、iconvにも存在する。

iconvで使ってみると分かるが、①みたいな日本語でお馴染みの文字がJIS Xの文字にならずGB 2312(中国)になったりする誰得仕様。

$ echo '①' | iconv -t ISO-2022-JP-2 | hexdump -C
00000000  1b 24 41 22 59 1b 28 42  0a                       |.$A"Y.(B.|
00000009
$

cp50220〜がこれである可能性もあるので確認の際にはこのシーケンスにも対応してみた。

ISO-2022-JP-3

次はまさかのISO-2022-JP-3。JIS X 0213を使う案らしい。RFCは存在せずIANAへの登録も却下されているが、iconvには存在する。よく知らないが、シフトJISですら拒んだJIS X 0213をMicrosoftが使うはずがないので未調査。

まとめ

歴史的経緯から、Windowsにとっては日本語はシフトJISが基軸に見える。Windows上の資産はシフトJISで記述されており、その中には少なからず機種依存文字が入っているから。前提知識の段階ではコードページ50220がISO-2022-JP-1ではないかという予想が出来る。

調査

方針

コードページ50220がISO-2022-JP-1であることを想定しているが、念の為

とほほの文字コード入門 – とほほのWWW入門
https://www.tohoho-web.com/ex/charset.html#iso-2022-jp

にあるエスケープシーケンスを加えて、シフトJISの全文字がコードページ50221にどうマップされるかを調べることにする。

コード

今回のコードは以下にある。

https://git.elephantcat.work/first_user/csISO2022JP_test

ソリューションファイルを開いてビルドした後、cat.batを実行すると、htmlファイルを作成して勝手に開く。

結果

作成したHTMLファイルはページの末尾に埋め込もうとしたが、このバージョンのLuxeritusでは保存できなかった。コード(git)の方に生成済みHTMLを入れた。テーマ変えねば…

しかしそれでも直にHTMLを見れず、仕方がないのでnginxに直に置いた。

https://elephantcat.work/csISO2022JP_test/csISO2022JP.html

考察

想定したとおり、コードページ50221はISO-2022-JP-1に半角カナを追加したものだった。機種依存文字のうち、NEC特殊文字はJIS X 208の未定義部分のままで、NEC選定IBM拡張文字とIBM拡張文字はJIS X 212に定義されていればきちんとマッピングしており、定義されていなければJIS X 212の未定義部分に移動している。飛び番がある理由などは分からないが、概ね予想通りだった。ユーザー定義文字については、JIS X 208・JIS X 212両方にある。Windowsユーザー以外は未定義部分に困るが、それ以外はJIS X 212を使うなら合理的な設計だと思う。

まとめ

Unicode全盛の現在JISコードなんて誰も使わない。極力労力は使わないべき。