East Asian Ambiguous Character Width の確認を ICU4C で行う

特にターミナル上で作業するにあたり、East Asian Ambiguous Character Width 問題は頭がいたい。

以下は vimスクリーンショット

■とα、きれいに表示されているだろ。ウソみたいだろ。全角なんだぜ、それで・・・*1



という訳で、文字種によって、East Asian Ambiguous Character Width の属性を取得するコードを C で書いて確認してみました。

East Asian Ambiguous Character Width には、以下の属性があります。

定義 意味
U_EA_NARROW 半角
U_EA_WIDE 全角
U_EA_HALFWIDTH 半角で表す
U_EA_FULLWIDTH 全角で表す
U_EA_AMBIGUOUS 文脈に依存
U_EA_NEUTRAL 上記以外(東アジア言語の文字ではない)

属性の説明は、以下がわかりやすいです。


以下、確認コードです。ICU のダウンロード、ビルドから行うようになっていますが、環境に合わせて適宣省略・修正してください。

$ wget -c http://download.icu-project.org/files/icu4c/52.1/icu4c-52_1-src.tgz
$ tar xfv icu4c-52_1-src.tgz
$ cd icu/source
$ ./configure
$ make
$ make check

上記のように ICU をダウンロード、ビルドします。

#include <unicode/uchar.h>
#include <stdio.h>

void test(UChar32 uc) {
    char *name;
    UEastAsianWidth eaw = (UEastAsianWidth)
        u_getIntPropertyValue(uc, UCHAR_EAST_ASIAN_WIDTH);
    printf("%04x ", uc);
    switch (eaw) {
    case U_EA_WIDE:
        name = "U_EA_WIDE";
        break;
    case U_EA_FULLWIDTH:
        name = "U_EA_FULLWIDTH";
        break;
    case U_EA_NARROW:
        name = "U_EA_NARROW";
        break;
    case U_EA_NEUTRAL:
        name = "U_EA_NEUTRAL";
        break;
    case U_EA_HALFWIDTH:
        name = "U_EA_HALFWIDTH";
        break;
    case U_EA_AMBIGUOUS:
        name = "U_EA_AMBIGUOUS";
        break;
    default:
        name = "default";
        break;
    }
    printf("%s\n", name);
}

int main() {
    test(L'A');
    test(L'あ');
    test(L'〜');
    test(L'ア');
    test(L'■');
    test(L'α');

    return 0;
}

上記のようなソースコードを、以下の Makefile でビルド・実行します。

all:
	gcc AmbiguousTest.c -Iicu/source/common -Licu/source/lib -licuuc -licudata

run:
	LD_LIBRARY_PATH=icu/source/lib ./a.out

clean:
	rm -f a.out

結果は以下のとおりです。

$ make
$ make run
0041 U_EA_NARROW
3042 U_EA_WIDE
ff5e U_EA_FULLWIDTH
ff71 U_EA_HALFWIDTH
25a0 U_EA_AMBIGUOUS
03b1 U_EA_AMBIGUOUS

これで ■とαが U_EA_AMBIGUOUS で取得できています。

*1:vim なら set ambiwidth=double で全角表示が可能です