★来週、7/29から8/2まで本ブログはお休みします

7月20日土曜日、また文字コードの宴会に参加した。
お題は「MacのHFS+でUnicodeの正規化が変になる件について」。
普通そんなことで飲み会しますか。
Test unicode tifinagh
MacのHFS+でUnicodeの正規化が変になる件とは何か。

参考ページ(ものかのさんのブログ)
 Unicodeの合成除外とHFS+の正規化
 Unicode正規化 用語の混乱について
 Unicode正規化

ここだけ読んでスッキリした人は、今日のエントリーを読み飛ばしてもいいかもしれない。
以下は屋上屋を架すというか、ぼくなりに説明を(主に自分自身に対して)試みてみる。

たとえばMacで「が」という字のテキストファイルを作る。
(カンタンのためUnicodeのUTF-16BEにしてみた。テキストエディタはCotEditorを使った)。
ga

で、これのダンプを取ってみると、304cになる。
gadump

「が」はUnicodeでU+304Cなので、予定の行動だ。

Cyber Librarian Unicode平仮名

で、この字をクリップボードにコピーし、Finderで新規フォルダを作り、そのフォルダの名前をクリップボードからテキストエディタペーストして「が」というフォルダを作る。
gafolder

で、その名前をコピーして、さっきのテキストファイルに追加すると、「がが」になる。
gaga

で、そのテキストファイルをダンプするとどうなるだろうか。
「が」が304cだったのだから、「がが」だと304c304cになると思われる。



実際にはこうなる。
gagadump

304c 304b 3099となっている。
304cは「が」だが、304b 3099ってなんだろうか。
さっきのコード表Cyber Librarian Unicode平仮名を見ると、U+304Bは「か」で、U+3099は「Combining Katakana-Hiragana Voiced Sound Mark」になる。
「結合用のかたかな、ひらがなの濁点符号」という感じだろうか。
つまり、「が」=「か+゛」という分解が起こっている。
(上の行の説明用には便宜上結合用でない濁点「゛」を使いました)

これはAppleのOS XのファイルシステムHFS+の仕様で(?HFS+のOS X実装の仕様で?)UnicodeのNFDに従うとされているが、実際には特例として
 U+2000~U+2FFF
 U+F900~U+FAFF
 U+2F800~U+2FAFF
の場合は分解対象から除外するとしている。
(これを便宜上 Modified NFDと呼ぼうという話だ。)
http://developer.apple.com/library/mac/#qa/qa1173/_index.html
たとえばFA19という字があるが、これは神(示申)という字だ。
神(ネ申)の旧字体である。



なぜこの字がこの話題に出てくるかというと、神(示申)は神(ネ申)にNFDによって「分解」されることがあることがUnicodeで定められているからだ。
おかしい。
「が」が「か+゛」になるのは分解で、「か+゛」が「が」になるのは合成。
それは理解できる。

「神」(示申、1文字)が「神」(ネ申、1文字)になるのは分解なんだろうか。
変身、と言った方がいいんじゃないだろうか。

もっとすごいのが、合成によって「神」(ネ申、1文字)は「神」(示申、1文字)に戻れない。
これを合成除外文字と言う。

まず、Macの文字ビューアでFA19という字を探して、神(示申)を表示する。
viewer

で、Finderで新規フォルダを作り、命名の瞬間に文字ビューアでその文字をクリックすると、神(示申)というフォルダが出来る。

(※ちなみに、FirefoxでさっきのUnihan Databaseを表示させてCotEditorやFinderにコピペするとこの時点で神(ネ申)に変わってしまうようだ)

このフォルダ名をCotEditorにコピペすると、依然として神(示申)である。
gagakami

ダンプしてみても、最後の文字は正しくfa19になる。
gagakamidump

このFA19は、さっきの特例に入っているので、ちゃんと「分解しないようにしている」ようだ。

さて、これは、見た目上分解されていないだけで、システム内部ではこっそり分解されて解釈されているようだ。
それが分かるのはファイルのソート時である。

Finderで神(ネ申)というフォルダを作る。
選択して⌘(コマンド)+C、⌘(コマンド)+Vという操作をすると「神(ネ申)のコピー」というフォルダが出来る。

さっき作った神(示申)というフォルダも選択して、選択して⌘(コマンド)+C、⌘(コマンド)+Vという操作をすると「神(示申)のコピー」というフォルダが出来る。

で、これをFinderの詳細画面で名前順に表示すると

 神(ネ申)<神(ネ申)のコピー<神(示申)<神(示申)のコピー

ではなく、

 神(ネ申)<神(示申)<神(ネ申)のコピー<神(示申)のコピー

の順番で並ぶ。
kamisort

つまり、神(ネ申)と神(示申)は同じ文字として考え、神(ネ申)と神(示申)の差異よりも「のコピー」の有無を基準にソートしているのだ。

さて、上の
 神(ネ申)と神(示申)は同じ文字として考え
という文は少し不正確かもしれない。
というのは、神(示申)と「神(ネ申)のコピー」だったら必ず神(示申)が上に来るけれど、神(ネ申)と神(示申)だったら必ず神(ネ申)が上に来るからだ。

「神(ネ申)のコピー」と「神(示申)のコピー」だったら必ず「神(ネ申)のコピー」が上に来る。

つまり、それ以外の要素があるんだったら神(ネ申)と神(示申)以外の部分を優先してソートするが、違いが神(ネ申)と神(示申)の差異しかない場合は、神(ネ申)と神(示申)の差異に基づいてソートしているんじゃないだろうか。
つまり、ソート前に合成はしているが、合成する前の字も勘案してソートしている。

もう一つ変なことに気がついた。

「神(ネ申)のコピー」を選択して⌘(コマンド)+C、⌘(コマンド)+Vという操作をすると「神(ネ申)のコピー 2」というフォルダが出来る。
これは予定の行動である。

ところがここで、「神(示申)のコピー」を選択して⌘(コマンド)+C、⌘(コマンド)+Vという操作をすると「神(ネ申)のコピー 3」というフォルダが出来る。

これは、事前に「神(ネ申)のコピー 2」というフォルダがあったから、遠慮して(重ならないように)「神(ネ申)のコピー 3」にしている。
事前に「神(ネ申)のコピー 2」を削除した状態でやったら、「神(示申)のコピー」をコピペすることによって、「神(ネ申)のコピー 2」が出来る。

つまり、MacのFinderには、「神(示申)のコピー」を作る機能はあるが、「神(示申)のコピー 2(以上)」を作る能力はなく、その場合は「神(ネ申)のコピー 2(以上)」になってしまう!!!

なぜだろう~。

わからないなりに、次、U+20F800領域(SIP)いってみよう。
UTF-16の1文字であらわせないので、俗に言うサロゲート・ペア文字である。

冬(U+2781A)という字がある。
冬の下の点々がカタカナのンみたいになっている字だ。

ふゆン。

そういう読み方をする字ではないと思うが、今後はブラウザーで見られない人のために、「冬(冬ン)」と言うことにする。
冬は「冬(冬ニ)」。

「冬(冬ン)」はU+2F81A
これを文字ビューアで出してみる。
fuyun

★★★注意!この辺から危険な動作になります。実験する人は自己責任でお願いします。まずは下まで読み通すことをお勧めします。

で、この名前のフォルダを作ってみる。
error

変なエラーが出た。

でも、出たなりに、フォルダは出来ているのである。
fuyunfolder

ところが、このフォルダがやっかいである。
 ・⌘(コマンド)+C、⌘(コマンド)+Vで「冬(冬ン)のコピー」を作ろうとしても「クリップボード上の項目はこの場所にペーストできません。 いくつかの項目が削除されているか、すでに使用できなくなっています」と言われ、コピペできない
 ・Dropboxにこのフォルダを作ると、なぜかアップロードされない
 ・選択して右クリックで「ゴミ箱に入れる」を選択しても「いくつかの必要な項目が見つからなかったため、操作を完了できません。(エラーコード -43)」と言われ、削除できない
 ・このフォルダの親フォルダ(ここではDesktop/foo)をゴミ箱に入れると、入れられるが、ゴミ箱を空にしようとしても、fooと、foo/冬(冬ン)だけは残る。

消せない!

これは困る。

実際にはターミナル(コマンドライン シェル。bash)で消せた。
rmdir

あと、シェル画面では神(ネ申)も神(示申)も神(ネ申)に見え、冬(冬ニ)も冬(冬ン)も冬(冬ニ)に見える。
だから、mkdirで神(示申)を作ると、神(ネ申)が出来てしまって、正規化が行われたのかと思うが、実際にそのときできたフォルダをFinderで見てみると、神(示申)が出来ている。
シェル(ターミナル)のフォントが問題なのかと思ったが、どれに変えても、変わらなかった。

まず画面ではlsでfooの中身を表示している。
なぜか冬(冬ン)ではなくて冬(冬ニ)というフォルダ名がある。

そこでrmdir 冬(冬ニ)と入れてみると、そんなフォルダないから消せないよと言われる。

そこで文字ビューアを使ってrmdir 冬(冬ン)とやると、消えた。

ちなみに、Finderのフォルダ名からCotEditorに冬(冬ン)をコピペし、UTF-32で保存して、hexdumpでダンプしてみると00 02 78 1aになった。
文字コードも保存されている。

さて、冬(冬ン)を正規化分解すると何になるかというと、それは当然冬(冬ニ)である。
fuyusort

画面は
 冬(冬ニ)+半角0
 冬(冬ン)+半角1
 冬(冬ニ)+半角2
 冬(冬ン)+全角3
 冬(冬ニ)+半角4
 冬(冬ン)+半角4
であるが、この順で並ぶ。
冬(冬ニ)と冬(冬ン)の差よりも、後ろの数字の差が優先されていることが分かる。
同じ「+半角4」であれば、冬(冬ニ)が冬(冬ン)より前に並ぶ。 また、半角2<全角3<半角4であって、このソートのバックで動いている正規化がNFDではなくてNFKDであることが分かる。

でもこれは、神(ネ申)と神(示申)の場合と同じように思える。
フォルダ名をCotEditorにコピペしたら正規化されていなかった(同じ字だった)。
ソートしてみると、バックエンドでNFKDが動いている、という状態だ。
なので、「SIPでは(Appleの仕様に反して)正規化が行われている」という問題は、ぼくには分からなかった。

なお、ぼくの環境は以下の通り。
 MacBook Air 11-inch
 Late 2010
 CPU: Intel Core 2 Duo 1.4 GHz
 Mem: 2 GB 1067 MHz DDR3
 GPU: NVIDIA GeForce 320M 256 MB
 OS: Mac OS X Lion 10.7.5 (11G63)

ま、このへんが今日のお題のようだ。

★★★ここから宴会

ここからが本題で、宴会を一応ノートパソコンでログってみたのだが、やっぱり飲食しながらのログは無理があって、読み返しても良く分からない。
分からないなりに、雰囲気をお伝えします。

・正規化というと、「が」が「か+゛」になったりするやつ
・神(示申)が神(ネ申)になるパターンもある。1字が1字になるのに、分解と言っている
・しかもこの字は分解したあと合成ができない
・これを合成除外文字といい、1120個ある
・正規化を通すと勝手に変えられてしまう
・これがちゃんとフォルダ名になるのか分からないので、全部フォルダを作ってみました
・フォルダが出来たのか、出来たとしても名前を変えられてしまったのか、一覧表を作りました
・これに使うのが、REALBasicか、AppleScriptか、mkdirかで結果が違う



・CJK互換漢字は分解されない
・BMP以外の(U+20000以上の)CJK互換追加が、Appleは変えないといってるのに変えてる
・OS X 10.8では変わる
・REALbasicでソフトを組むとこういう異常な名前のフォルダが作れてしまう



・HFS+のapiが悪さをしているのか
・Finderからだと手で打ち込むとmkdirと一緒の結果が得られる
・mkdirだと作れない(深沢注:ぼくの手元では作れたようだ)
・Finderだと打ち込みエラーになる(深沢注:エラーになるなりに、作れたようだ)
・REALbasicだと作れる
・変な字だけの場合と、変な字が3文字目に来る場合でちがったりする
・10.4は手で入れると全部正規化されていた
・10.5以降は神(示申)は変わらなくなったけどU+20000以降は入らなくなった(深沢注:エラーになるなりに、入ったようだ)

・10.5からNSファイルマネージャーを使うようになった

・(一度正規化すると、情報が欠損するので)元に戻せない
・Firefoxはコピーした瞬間に正規化する(深沢注:これは正規化を確認)
・アドビもそう

・アドビはクロスプラットフォームだから、AppleのAPIが使えなかった
・CS2でガが分かれた。これはNFKD
・CS3で直った
・CS4でNFDになった

・Unicodeで文字の並び順が決まっている
・1<02<3<04となる(文字コード順では02<04<1<3になるはず)
・ネ申と示申を隣に並べたい
・こういう用途で、裏方で働くべきなのにユーザーがいじれる状態で正規化しちゃう

・全角の1はNFCで全角の1のまま
・全角の1はNFKCで半角の1になる(NFKCはより強烈な正規化)
・①もNFKCで半角の1になる

・これは、検索とかソートでファジーにやりたいときに使う
・Unicode正規化は分解がまずありき

・変換した後だと元に戻せない
・InDesignからEPUBに書き出すと基底文字だけになる
・置換文字にして色を変えている

・InDesignは小塚明朝がトンボ外でOsakaになっちゃう
・プリントすると出て来ちゃう
・Osakaになってますよ、と校正で赤字を入れられる
・マンガがマンカ+豆腐になったりする
・でも、トンボの外に赤字入れなくていいんじゃないの

・iPhoneのAdobe Readerで第2面の文字をテキストに落とすと第1面になっちゃう

・「か+゛」という合成文字を「が」として表示しているが、ちゃんとした「が」を出している
・この、「か+゛」と「が」をどこでマッピングしてるのかが昔から謎
・フォントにはそういう情報はない
・OSがやってるはず
・CID番号は一緒だから同じ字ではある

・cocoaだと(マウスのクリック&ドラッグで、合成文字の「か」と「゛」を)バラバラには選択できない
・carbonだとできる
・「か」を「あ」に検索置換すると、「が」まで引っ掛かっちゃって「あ゛」になっちゃう

・アイヌ語の発音を写すための「カ゜」とかはどうなのか
・あれはまた話が別。別の文字としてUnicodeにないから、合成しかできない

・でも試みにカ+゜をNFCすると「゜カ」になった。。
・これはcarbonだから
・cocoaだと大丈夫
・フォントによっても違う
・ヒラギノProだと「゜カ」になる
・ヒラギノProNだと「カ゜」になる

・なんでだろ
・GSUBじゃないの

・ヒラギノPro Nだとフィーチャーが増えたんだよ。CCNP。あれがやってんじゃないか
・AppleのAPIレベルでCCNP絶対掛かるから、carbon/cocoa関係なく出来る

・ものかのさんピザ食べますか
・食べるたべる

・前田年昭さんって人が組継(くみつぎ)って技法をやっていて、これがすごい
・紙に穴を開けて通していくだけで製本する。糸も、紙も、糊もいらない
・面付けが難しそうだなー
・自動化も難しそう

・こういうセッションを記録してブログに上げる人いるけど、自分に分かるところだけ切り取って上げるから、本質を離れた話になってて、自分が言ったことじゃないことが自分の発言として載ってるんだよなー
(スミマセン)



他にも、
・マイナンバー制度が始まるけど、住基文字や登記文字で標準化していない字をどうやって電子化するのか
・縦中横(「たてちゅうよこ」と読む)の問題
などが繰り広げられたようだ。

全体としては楽しかったけど、半分も理解できなかった。
もっともっと濃い人になりたいなーと思ったのである。