見出し画像

【ShellFiler開発記】半角文字と全角文字とは何か

今回の記事では、自作のファイル管理アプリ「ShellFiler」の開発を通して知ったトピックから、半角文字と全角文字の違いについて書いてみます。

半角、全角は、通販サイトなどで「住所の入力は全角」「電話番号は半角」などと指示されているアレです。
もちろん私たちは「123」は半角で「123」は全角などと知っていますが、そもそも半角と全角とは何なのでしょうか。

検討した結果、現代のコンピュータ環境で「全角」「半角」と言えるのは一般的な文字だけで、全角でも半角でもない混沌とした世界が広がっていました。

ファイルビューアの開発

ShellFilerにはテキストファイルを閲覧する機能があります。このとき、全角と半角を区別する処理が必要になりました。

画像7

普通のアプリでは、TextBoxなどの標準機能で文字列を画面表示します。
しかし、ShellFilerは多機能が売りのため、表示回りも独自実装です。テキストを範囲選択する基本機能ですら自前で用意しました。

ここで壁に当たりました。
マウスカーソルと画面上の文字の対応づけです。
Y方向は行の幅が均等なので、Y座標をフォントの高さで割るだけで行位置が分かりますが、X座標は文字の幅を考慮して計算する必要があります。
下の図でマウスカーソルが「2」の上にあると判断するのは、結構難しい処理が必要です。

画像2

考えたのは、以下のような方法でした。
・等幅フォントで文字列を表示
・半角を1文字、全角を2文字として表示中の文字列をカウント
・半角の文字幅でマウスカーソルのX座標を割って文字列と照合

画像3

残念ながら、現代のPC環境ではこの方法は使えません(等幅フォントが時代遅れなのはさておき)。
半角とも全角とも取れない文字があるためです。

以下、問題となった例を挙げます。

混沌とした文字

キリル文字
まず、キリル文字の問題にぶつかりました。
例えば、Wikipediaでモスクワのクレムリン(現地の言語)を開くと、見た目は半角で書かれた文章が表示されます。しかし、コピー&ペーストで日本語の環境に持ち込むと、同じ文字が全角として表示されます。
同じ文字が全角にも半角にもなります。
Windows以前から、キリル文字はJISコードでも全角記号だったため、全角だと思い込んでいましたが、環境次第では半角でもあることに驚きました。

画像6

ゼロ幅スペース
続いては、ゼロ幅スペースです。
この文字の用途の1つは、長い語句の折り返し位置の表現です。普段は幅が0ピクセルで表示されない文字ですが、ウィンドウサイズが小さくなり、折り返しが必要になると、ゼロ幅スペースの位置で改行されます。
半角でも半角でもなく、幅がない文字もあります。

画像6

サロゲートペア
全角/半角問題とは性質が異なりますが、サロゲートペアも厄介です。
例えば、牛丼の「𠮷野家」の「𠮷」は、上半分が「土」となるのが本来の表記だそうですが(「吉」ではなく「𠮷」)、この文字は文字列処理でトラブルが多発することで知られています。
C#などのプログラムでは、文字をUTF-16の文字コードとして扱います。
例えば半角の「a」は0061、全角の「a」はFF41、「漢」は6F22と、1文字が文字コード1つに対応します。しかし「𠮷」はD842、DFB7と2つのコードで表現します。
半角/全角以前に、文字を1つのコードで表現できない問題も出てきました。

その他
これ以外にも、囲み文字とか、結合文字とか、ややこしい文字が多数……。
私はUnicodeにそれほど詳しくはないのですが、それでも、こうした特殊な文字が多数存在することを知り、半角での文字数のカウントは現実的ではないという結論に至りました。

結局は

そもそも全角と半角の判断は、マウスポインタ直下の文字を調べるためでしたが、これは描画幅を調べることで実現しました。

文字列を1文字ずつ増やしていき、描画時の幅がマウスカーソルのX座標を超えたときの文字を、マウスカーソル直下の文字と判断できます(バイナリサーチで効率化もできる)。

画像7

この記事では扱いませんでしたが、フォントによっては、文字同士が重なり合う「合字」の問題もあるとのこと。描画幅でも怪しい可能性が……。

一方、全角/半角の観点では、「すべての文字を全角/半角に分類するのは不可能」という結論を得ました。しかし、全角/半角という呼び方は現在でも使います。

英数字や、キーボードから直接入力できる記号の多くは、同じ文字が全角と半角の2つで定義されているためはっきりと区別できます。また、日本語で使われるJIS第1水準/第2水準の漢字範囲ぐらいは安心して全角だと言えそうです。
これを超えて、海外の文字や特殊な記号にまで範囲を広げると、混沌としていてよく分からなくなるというのが印象でした。

余談:色の問題

余談ですが、文字列関連の処理では半角全角以外でも、絵文字の色も扱いが特殊です。

例えば「❗」(2757)。
若い世代からデフォルトで嫌われている我々おじさんが多用すると、目も当てられなくなる文字としても知られています。

ブラウザ上では、「お疲れサマ❗❗」のように色付きで表示されますが、これをGDI+で描画すると単一の色で表示されてしまいます。もちろん顔文字なども白黒です。

画像6

あのPower Pointでも、文字列中の絵文字がカラー化されたのは数バージョン前からと、やはり特殊そうです。ShellFilerでも、いずれ絵文字のカラー対応をしたいところです。

実世界での文字は、人間にとって基本かつ柔軟であるだけに、コンピュータ上での処理も奥が深いです。その分、理想に近づけるのは本当に大変です。