WIN32 と UNICODE

(c) Copyright 1998-1999 by H.Fujii
(Start:06-Feb-1998, LastUpdate:06-Aug-1999)

ここに記載した情報は Microsoft Visual C++ 4.2 Enterprise Edition の オンラインヘルプから WIN32 - WIN32SDK - WIN32 Programmer's Reference - Overviews - International Features - Unicode and Character Sets を たどって得た情報を基に、筆者の理解で記述したものです。 誤解、誤読があるかも知れません。


MS-Windows(3.1/95)は、MS-DOS から出発している。Windows-NT は、MS-DOS とは独立に書かれた OS であったが、MS-ODS (like) のアプリケーションを 実行させることも強く意識されている。従って、Microsoft が扱う OS 群に おける文字セットを調べようとすると、まず MS-DOS で使っている(いた) 文字セットを知る必要がある。

OEM コードページ

MS-DOS は、基本的に PC ベンダーによる提供であった。使う PC により、 MS-DOS は(核の部分は同じでも)異なるものであった、文字セットに ついても同様で、使う PC により、文字セットは異なっていた。 この文字セットを Microsoft は OEM 文字セットと呼び、各 OEM 文字 セットをコードページと呼ばれる番号で区別していた。例えば日本語 MS-DOS で使われている文字セットのコードページは 932 であり、 アメリカ合衆国 MS-DOS で使われている文字セットのコードページは 437 という具合である(本当は、日本語 MS-DOS でも例えば NEC と富士通 では異なる文字があったりしたのだが、どちらも 932)。

当然のことながら、Windows-95 や Windows-NT でも、この OEM コード ページの概念がある。WIN32-SDK には、GetOEMCP() という OEM コード ページを得る関数が用意されている。例えば、次のような簡単なプログラム を作って、コンパイル・リンクして MS-DOS プロンプトで実行してみれば OEM コードページがわかる。

    /* Test of the GetOEMCP */
    #include <windows.h>
    #include <stdio.h>
    void main()
    { 
      printf( "OEM Code Page:%d\n", (int)GetOEMCP() );
    }


ANSI コードページ

Windows の時代になって、Graphical User Interface (GUI) で用いる文字は ソフトウェア的に生成されるようになる。そこで、ここでも文字コードページ の概念が必要になる。例えば東ヨーロッパ用 Windows 3.1 の文字セットの コードページとか、ギリシャ用 Windows 3.1 の文字セットのコードページ などと言ったものが導入される。これらが本当に ANSI で定められたものに なっているかどうか筆者は知らないが、Microsoft は Windows で使用する これらのコードページを ANSI コードページと呼び、先に述べた OEM コード ページと区別する。また、GetOEMCP() に対応した、GetACP() なる関数が用意されている。

しかし、一方 Windows 3.x ではファイルシステムは MS-DOS のファイルシステムのままであるために、Windows 3.x の GUI は ANSI コードページで指定される文字セット、一方ファイルシステム (MS-DOS FAT ファイルシステム)は OEM コードページで指定される 文字セットということになった。当然、この OEM コードページの文字と ANSI コードページの文字との対応(相互変換)が必要となるが、WIN32-SDK では

という関数が用意されている。


UNICODE

ネットワークが発達し、文書ファイルが文字セットの異なる国々で交換 されるようになると、異なる文字セット間の変換とか、複数文字セットを 一つの文書ファイルに納める必要が出てくる。そこで、「世界中の文字を 全部含んだ一つの文字セット」を使おうと考えるのは、当然の成り行きで あろう。Windows-NT では文字セットとして、 Unicode 文字セット(正しくは、国際符号化文字集合(UCS) の基本多言語面(BMP - Basic Multilingual Plane)とでも言うのかな)が選べる ようになった。

さて、こうなると話は更にややこしくなる。OEM 文字セット、 Microsoft の言うところの ANSI 文字セット(この言葉は誤解を招く。 ANSI コードページにより指定される文字セットとでも呼ぶべきもの) 及び Unicode 文字セットの間でコード変換が必要になる。 WIN32 では、これらを行う関数として

なる関数が用意されている(MultiByte が Unicode か、WideChar が Unicode か?いかにも誤解を招きそうな関数名をありがとう、Microsoft!(涙)。正解は WideChar が Unicode だそうだ)。どのコードページ群(OEM コードページ なのか、ANSI コードページなのか)を対象にするかは、引数の 一つに、それを指定するフラグがある。OEM コードページ、 ANSI コードページの他に Macintosh コードページの指定もできる!


変換プログラム

名前のまぎらわしさはともかく、変換用の関数が用意されているので、変換 そのものは簡単である。例として、OEM コードで入れた文字を Unicode に 変換して、16進でダンプするプログラムを示す。

    /* OEM code to Unicode converter */
    #include <stdio.h>
    #include <windows.h>

    #define MAX_WBUF 255
    static WCHAR wbuf[(MAX_WBUF+1)];

    void main(int argc, char* argv[])
    {
      int i, n;
      if(argc != 2)
      {
        fprintf(stderr, "Usage: %s string\n", argv[0]);
        return;
      }
      n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED,
            argv[1], -1, wbuf, MAX_WBUF );
      for( i = 0; i < n; i++ )
        printf( "%5d: 0x%04x\n", i, wbuf[i] );
      return;
    }
このプログラムを oemtouni という名前にしよう。例えば

oemtouni "藤井 啓文"

とすると、
    0: 0x85e4
    1: 0x4e95
    2: 0x0020
    3: 0x5553
    4: 0x6587
    5: 0x0000
という結果が得られる(コンパイル・リンク済みの実行ファイルと、この ソースを一緒にした tar ファイルは oemtouni.tar (26624 bytes))。
参考規格