・
Unicode
Windows の Unicode (WideString) は Win9x (多分 NT3x / 4.0 も) に於いては UCS-2、2000 / XP / Vista では UTF-16 で表現される。
UCS-2 は 「Unicode って、完全 2 バイトだよね?」 と言われるアレ。すべての文字は 16bit で表わされる。よって使える文字数は論理的には 65536 文字。ちなみに UCS は Unicode ではない (後述)。
UTF-16 は基本エリア (BMP = Basic Multilingual Plane) は UCS-2 と完全な互換性があり、加えて Shift_JIS での漢字表現や EMS (Expanded Memory Specification) のような方法でプレーンを拡張し、UCS-2 が論理的に扱える文字数以上の文字を格納できる。BMP にある文字コード未割り当て領域 (プレーン拡張用に使われる) を "サロゲート" と呼び、この領域にあるコードを 2 つ (16bit×2) 使って表わされる文字 (或いは領域) を "サロゲートペア" と呼ぶ。
つまり、UTF-16 は
Shift_JIS 等の漢字領域を DBCS (Double Byte Character Set) / MBCS (Multi Byte Character Set) と言うが、UTF-16 のサロゲートペアははさしずめ "DWCS (Double Word CharacterSet) / MWCS (Multi Word Character Set)" と言ったトコロ。UCS-2 は DBCS ではなく、"SWCS (SingleWord Character Set)" が正解なのだろう。
勘違いしやすいが、Unicode は最新の規格で 21bit の範囲にある。UCS は Unicode と同列に扱われる文字集合の規格 (Universal Coded-CharacterSet)。UCS-2 は 2byte (固定 2byte = WORD)、UCS-4 は 4byte (固定 4byte = DWORD) の範囲にある...つまり、母集合としては UCS-4 は Unicode よりも大きい。UTF は "Unicode / UCS で表わされる文字の文字コードを変形して扱い易くするための文字符号化方式 (文字エンコーディング) の規格 (Unicode / UCS Transformation Format)" であり、文字集合の規格ではない。すべての Unicode / UCS をフラットに扱うには UTF-32 を使えばいいが、この際には、"1 文字 = DWORD" となってしまう。
・
Windows と UTF-16
では、UTF-16 を内部処理で使用している Windows ではすべての文字を表示できるかと言えば、そうとも限らない。サロゲートペアはデフォルト状態では Vista でしか表示できないからだ。2000 / XP でサロゲートペアを表示するためには対応するフォントとレジストリの変更が必要となる。
Windows 9x に於いては W 系の API はほぼ実装されておらず、Microsoft Layer for Unicode (MSLU) でも使わない限り W 系の API を呼び出すことはできない。例え MSLU を使ったとしても、W -> A 変換でロスしたり、内部 UCS-2 の制限を受けるため "完全 Unicode 対応" は限りなく不可能に近い。
・
Windows と UTF-8
有名な UTF-8 は、Shift_JIS をさらに拡張したようなもので、ASCII 部分は 1 バイトで表現でき、それ以外の文字は最大 6 バイト (最新の定義では 4 バイトが上限らしい) で表現する。これこそまさに MBCS と言える。
これも勘違いしやすいが、"UTF-8 にサロゲートペアは存在しないが、それ以上にややこしい構造になっている" と言うこと。それと、Windows に於いては UTF-16 を内部処理で利用している関係で "間接的にサロゲートペアの影響を受けてしまう" という事。Windows で UTF-8 の話をしている時にサロゲートペアの事を持ち出されても、脊髄反射で 「UTF-8 には関係ねーよ、バーカ」 とか罵ってはいけない。ちなみに、Delphi 2007 にも UTF-8 とサロゲートペアに関する問題が存在する (QC#58386)。
・
Delphi と Unicode
昨日の続きで、ここからが本題。
String (短い文字列=ShortString / 長い文字列=AnsiString)
Pascal の String 型はいわゆる"短い文字列"である。String 型を文字の配列としてアクセスする場合、添え字は 1 からとなる。Copy(S,1,1) と S[1] は同じ内容を得られる (正確には前者は "長さ 1 の String" で後者は Char / AnsiChar 型)。
では、S[0] にアクセスするとどうなるのか?実は文字列の長さが得られる。短い文字列では、Length(S) と Byte(S[0]) は同じ処理を指す。このため、Pascal 文字列 (ShortString) の文字列長の最大は 255 に制限される。明示的に短い文字列を使いたい場合には
|
のように添え字を伴って指定する事になる。
Delphi での String 型は特に何も指定しなければ AnsiString と考えればいい。文字列長の最大は Integer の正の最大数である 2GB となる。String 型はヌル終端でないので、実際にはどのような文字コードを入れても構わないのだが、サポートする文字列処理関数や VCL の関係上、ASCII (ANSI) または、Shift_JIS のように ASCII を符号化して各国の文字を扱えるようにした方式に限定される。
WideString
Unicode を扱う文字列型...のハズなのだけれども、実際には内部処理で UTF-16 を使用する Windows であっても、BMP しか扱えないと思われる。つまり、"Win9x = UCS-2"、"2000 / XP / Vista = UTF-16 の BMP" となる。ヘルプには
|
とあるのだが、"BSTR が USC-2 の範囲しか扱えない" のか、"互換性とは UCS-2 / UTF-16 の BMP の事を言っている" のかがはっきりしないが、ヘルプに
|
と明示してある以上、どんな Unicode / UTF / UCS 関連の関数であろうが、内部処理に WideString を利用しているのであればサロゲートが無視される可能性が高い (WideStringToUCS4String() 関数とかはそういった意味では眉唾物)。
・
Delphi の使い分け?
総合的に考えるに、
この辺をユーザにちゃんと説明した上であれば "Delphi 7 の再販はアリ" だと思っている...需要がないとは言い切れないのだから。加えて言えば Delphi 2007 の長期的なサポートも一考の価値はあると思う。
・
ちょっと擁護
CodeGear がヘタレなのではない。ASCII 圏の人間の作ったものは、どうしても非 ASCII 圏の事は後回しになる (或いは ASCII 圏の利便を図ろうとする)。
例えば UTF-8。これは 1 バイトの範囲にある文字は ASCII と完全互換だ。ASCII の範囲にある文字だけならば、ASCII だろうが Shift_JIS だろうが、EUC だろうが UTF-8 だろうが同じ処理で済む。「俺らの文字は 1 バイト (或いは 7bit) で済むんだよ、何で Unicode (UCS-2 / UTF-16) で 2 バイトも使わなきゃならんのだ?」 という理屈が見え隠れする。 UTF-8 はサイズの縮小という意味では非 ASCII 圏の人間にも有効ではあるが、他の文字コードセットへの変換時に面倒を伴う...「しわ寄せは全部こっちかよ?」 と言いたくなるのが人情ってもんだ。
MS だって例外ではない。
・
コードページとロケール。
さて、文字コードに関わるもう一つの話をしなくてはならない。コードページとロケールについてだ。
コードページってのは断りがない限り、"Unicode 対応でないアプリケーションに用いる ANSI 文字列の文字符号化方式(文字エンコーディング)" の事で、文字集合を指すのではない。日本語な ANSI 文字列は Shift_JIS だけれども、Windows の日本語 ANSI 文字列は厳密には "Shift_JIS を拡張した CP932" が正しい。プログラミングするなら GetACP() 或いは GetOEMCP() という API で取得できる。
ロケールというのはお住まいの地域の事。国 / 地域番号とでも言えばいいか。日本のロケール ID は 0x0409 プログラミングするなら GetUserDefaultLCID() という API で取得できる。実はロケールには複数あるのだが (システム / ユーザ / スレッド...)、話がまたややこしくなるので一般に言う所の "現在のロケール" という前提にしておく。
もう、お分かりかとは思うけど、ロケールとコードページは "関係はあるけど別物"。同じ国の中に異なる言語が存在する事だってあるのだから、ロケールからコードページは特定できない事になる。ややこしいのは OEM コードページという奴。これは Microsoft が管理していないコードページで、日本の CP932 だって元々は OEM コードページだった。MS-DOS の頃、PC / AT と PC-98 で "同じ Shift_JIS なのに違う文字 (機種依存)" だったのは、OEM コードページだったため。Microsoft が管理していないコードページは、同じコードでもベンダによって表示される文字が違う事がある。それと、日本の場合 GetOEMCP() では CP932 が返らないかといえばそうではなく、ちゃんと CP932 が返ってくる。
さて、そろそろ Delphi にまつわる話をしよう。"[Delphi-ML:90290] Delphi 2007 の TLabel の文字化け" でフォントの Charset の話をしているけれど、中村さんも僕もロケールには言及していない。先に書いたように、この話でロケールとコードページには因果関係はないからだ。それに、DEFAULT_CHARSET が正しく動作しないのはある意味仕方がないのだ...別に日本語の事だけを考えている訳じゃない。
最近の Delphi でオブジェクトインスペクタに列挙される Charset は OEM コードページ となっているので (<- これは勘違いであり嘘。実際のトコロは後述) は、例えば韓国なんかだと HANGEUL_CHARSET (CP949) と JOHAB_CHARSET (CP1361) という 2 つのコードページが使える事になる。
特別な処理が無い場合にはコンポーネント等の Font の初期値は "Delphi のデフォルトフォント" を参考にしている (多分)。では、Delphi のデフォルトフォントはどうやって求められているのか?
普通の考え方なら、
そして重要なのは、日本に於いては僕の示した "普通の考え方" でいいのだろうが、"一つの国で複数のコードページを持つ場合" にはそうとばかりも言えない、という事だ。現状では、「リポジトリを用いて回避しろ」 としか言えない...もちろんこれは日本国内に限った話ではない。
なお、この話題は "[delphi.japanese:TFont.Charset の DEFAULT_CHARSET の扱いについて]" として NG に問題提起してあるので、「実際のトコロどうすべきなのか?」というアイデアをお持ちの方には是非議論に加わって頂きたいと思っている。
・
コードページとフォントの Charset の関係。
ちょっと訂正。
コードページ | CP | OEM | xBCS | Language | TFont.Charset | Value | Charcter Set | Char Encoding | Note |
CP437 | ○ | SBCS | 英語 | |
|
||||
CP708 | ○ | SBCS | アラビア語 | ||||||
CP709 | ○ | SBCS | アラビア語 | ||||||
CP710 | ○ | SBCS | アラビア語 | ||||||
CP720 | ○ | SBCS | アラビア語 | ||||||
CP864 | ○ | SBCS | アラビア語 | |
|||||
CP1256 | ○ | |
SBCS | アラビア語 | ARABIC_CHARSET | 178 | |||
CP737 | ○ | SBCS | ギリシャ語 | ||||||
CP869 | ○ | SBCS | 現代ギリシャ語 | ||||||
CP1253 | ○ | SBCS | ギリシャ語 | GREEK_CHARSET | 161 | ||||
CP775 | ○ | SBCS | バルト語族 | ||||||
CP1257 | ○ | SBCS | バルト語族 | BALTIC_CHARSET | 186 | ||||
CP850 | ○ | SBCS | ラテン I | ||||||
CP852 | ○ | SBCS | ラテン II | ||||||
CP858 | SBCS | ラテン I | |||||||
CP1252 | ○ | SBCS | ラテン I | ANSI_CHARSET | 0 | ||||
CP855 | ○ | SBCS | キリル文字 (ロシア) |
||||||
CP866 | ○ | SBCS | ロシア語 | ||||||
CP1251 | ○ | SBCS | キリル文字 (ロシア) |
RUSSIAN_CHARSET | 204 | ||||
CP857 | ○ | SBCS | トルコ語 | ||||||
CP1254 | ○ | SBCS | トルコ語 | TURKISH_CHARSET | 162 | ||||
CP860 | ○ | SBCS | ポルトガル語 | ||||||
CP861 | ○ | SBCS | アイスランド語 | ||||||
CP862 | ○ | SBCS | ヘブライ語 | ||||||
CP1255 | ○ | SBCS | ヘブライ語 | HEBREW_CHARSET | 177 | ||||
CP863 | ○ | SBCS | カナダ系フランス語 | ||||||
CP865 | ○ | SBCS | 北欧語族 | ||||||
CP874 | ○ | ○ | SBCS | タイ語 | THAI_CHARSET | 222 | |||
CP932 | ○ | ○ | MBCS | 日本語 | SHIFTJIS_CHARSET |
128 | JIS X 208 | Shift_JIS | シフト JIS コード |
CP936 | ○ | ○ | MBCS | 中国語-簡体字 (中国 / シンガポール) |
GB2312_CHARSET | 134 | GB 2312-80 | GBK | |
CP950 | ○ | ○ | MBCS | 中国語-繁体字 (台湾 / 香港) |
CHINESEBIG5_CHARSET | 136 | Big5 | Big5 | |
CP949 | ○ | ○ | MBCS | 韓国語 | HANGEUL_CHARSET | 129 | KS X 1001 | UHC (Unified Hangul Code) |
|
CP1361 | ○ | MBCS | 韓国語 | JOHAB_CHARSET | 130 | KS X 1001 | Johab | ||
CP1200 | ○ | - | Unicode(BMP) | Unicode | UCS-2 | ||||
CP1250 | ○ | SBCS | 東欧 | EASTEUROPE_CHARSET | 238 | ||||
CP1258 | SBCS | ベトナム語 | VIETNAMESE_CHARSET | 163 | |||||
- | デフォルト CP? | DEFAULT_CHARSET | 1 | ||||||
- | Mac 用 | MAC_CHARSET | 77 | ||||||
- | OEM-CP 用 | OEM_CHARSET | 255 | ||||||
SBCS | シンボルフォント用 | SYMBOL_CHARSET | 2 |
うは、TFont.Charset はGetACP()/GetOEMCP()だけじゃ処理できないじゃん。
|
それじゃ、こんな感じになるのかな?これで、ベトナムも(殆ど)OKだね...gặp sau nhè。
・
ちなみに。
Tiburón とかの ó のように声調記号のある文字の入力には "UniKey" を使っています。以前、ベトナムへ出張した際には重宝しました。以下、実際の使い方です。
記号 | 表記 | タイピング (TELTEX) |
|
A のサーカムフレックス記号 | Â | â | aa |
A のブレーヴェ記号 | Ă | ă | aw |
D のストローク記号 | Đ | đ | dd |
E のサーカムフレックス記号 | Ê | ê |
ee |
O のサーカムフレックス記号 | Ô | ô | oo |
O のホーン記号 | Ơ | ơ | ow |
U のホーン記号 | Ư | ư | uw |
Thanh sắc の声調記号 |
Á | á | s |
Thanh huyền の声調記号 | À | à | f |
Thanh hỏi の声調記号 | Ả | ả | r |
Thanh ngã の声調記号 | Ã | ã | x |
Thanh nặng の声調記号 | Ạ | ạ | j |
記号取り消し | z |
ベトナム語の入力方式にはイロイロありますが、ここでは TELTEX 方式を紹介しています。"ặ" なんて文字もある訳で、これは "awj" または "ajw" とタイプします。「Tiburón のóだけのために UniKey をインストールするのは大袈裟すぎる」 って方は "Online Keyboard for Vietnamese" で適当にキーを押してコピペして下さい...まぁ、このページからコピペするってのもアリなんですが (^^;A
なお、正しくベトナム語と日本語を混在できるフォントは
...ですが、実際にやってみると "MS ゴシック" 等でも表示できるように見えます。しかし (詳しい理由は述べませんが) 一部の文字だけがボールドになります。日本語とベトナム語を混在させる場合にはできるだけ "Arial" や "Tahoma" を使うようにして下さい。または、ベトナム語の箇所だけフォントを変更するようにして下さい (Word や Excel の場合)。
・
パンが無ければお菓子を(以下略)
雑談にコメントできなきゃ、掲示板を(以下略)。専用スレッドを用意してみましたので、昨今の雑談にツッコミを入れたい方はどうぞ (メアドは必須ではありません)。目印としてフサを置いておきました。掲示板の注意書きにもありますが、REMOTE_HOST が見えますので自演したい場合には充分注意を払ってからやって下さいね。
荒れない程度にマターリやれれば、よろしいかと...。
・
"デベロッパーキャンプ、ご参加ありがとうございました。" を検証する。
私は先のデブキャンに参加する事が叶いませんでしたが、こうして資料の提示があるのは喜ばしい事です...地方に居ながらにして、重要な情報が得られるのですから。
[String は UnicodeString にマップ]
[文字のインデックス化と通常の文字列処理に変更はない]
・
彼からの Mail
溜まってますねー。
こうさ、カウパーが乾燥して癒着した下着と尿道が剥がされる瞬間の切ない痛みを感じる時、いつも庵寿と厨子王のその後に想いを馳せる。 |
織姫と彦星でもいいのではないでしょうか?
今便所なんだけどさ、座った瞬間の屁音が「ピキュン」っていうか「フィキュッ」っていうか、なんかその辺の萌えキャラの呻き声みたいだったんで、俺もだいぶ丸くなったもんだなっていう感慨を覚えた。 |
エロゲのやり過ぎだ...もう、お互いいい歳なんだからさ。
カーマ来てんだけどさ、昨夜 TV 通販で 6 千ナンボで売ってたのと全く同じ大理石加工のフライパンが 1980 で置いてあったのでウンコ漏洩した。 |
通販の奴は、「今ならもう 2 個」とか言ってなかったか?
なんか三ヶ月ぐらい点けっぱにしといたらパソ死んだ。とりあえずセーフモードで立ち上がる途中に電源ブツッてなってリセットかかるんでもう絶望的だと思う。 死ぬ前にデバイスマネージャ見た時は SCSI 死んでたっぽいんだけど、それが判ったところで今更。 級長ちんげ生えすぎだっつーの。 |
脈絡のない最後の一行に悪意しか感じない私は何かがおかしいのでしょうか、それとも単なる被害妄想でしょうか?
今レジ立ってんだけどさ、肛奥でニホンオオカミ飼ってるかのような唸り声がずっと聞こえてくるのに店員俺しかいねえ状況だし、今夜セブンイレブン全店舗営業停止のニュースを楽しみにしてていいと思う。 |
オマイの苗字は"日本の苗字 7000 傑"でも最低ランクなのだから、自重せよ。
結局三国志 10 の PK 付き 14000 円を買おうか買うまいか買おうか買うまいか買おうか買うまいかで閉店間際のエイデン柴田店で 40 分近く懊悩しまくった揚句の果てに買ったつもりになって帰って来て麻婆飯作って食った後にさーパパ三国志 10 最初っからパラメータ最強にしまくった新武将 128 人ぐらい作成しまくるぞーって思ってパソ部屋行ったら実際買ってない現実と向き合った時の寂寥感といったらなかった。心底自分にガッカリだ。 |
"日清のラーメン屋さん" みたいだな。「行ったつもりで我が家で...」 ま、こっちは腹は膨れるのだがな。
日中ヒマだったんで一人で安宅家の人々ごっこしてみたんだけど、あまりにも人としてどうかと思ったのでこのネタ封印する事にした。 |
何の事か解らなかったのでググったら、すげぇストーリーだな、オイ!
新しくうちに来た冷蔵庫、なんか勝手に氷作るわだだっ広いわで、野菜何買ってこようとか考えてたら便意に襲われた。 |
夜中にガラガラッって音がするので (多分)、"かなり巨大なゴキブリが台所で這いずり回ってる" のだと妄想すると、夜も眠れなくなると思う。
よく級長が職場の会議でケツアナルって言うけどさ、ケツアナルって何か古代インカの太陽神って感じしねえ? |
"ケツァルコワトル" の事かー!って、ネタ元を説明しないと意味不明なネタって、ネタとしての存在意義を疑われても仕方がないと思う。
3800 万のマンション買う気になって検討してたら超ウンコしたくなったもんで、亜音速でベビーカー押して最寄りのバロー便所に駆け込んだ。 |
そういや、お子様が生まれたのだったな...おめでとう。願わくば、この子が親父或いは叔父 (1) や叔父 (2) のようなヲタに育ちませんように。
今日のトリビア コンビニに男性客が支払いに来るゲームチェックは 大半が出会い系関係である。 |
人生イロイロ...男もイロイロ...さ。
ファミ通の表紙見たら SCE 池尻大作氏ってのが出てたんで、いつから世界のソニーはナンミョウの企業舎弟に成り下がったのかと早合点して愕然としたのだ!!!!!!!!!!!!!!!!!!!!!!!!!!!!@@;;;;;;;;;; |
"渡辺信一郎" と "ワタナベシンイチ" と "ナベシン" と "スパイク" と "ダンス☆マン" と "ダソヌ☆マソ" みたいなものか。ぶっちゃ毛、一見さんにはよくわからないけどね。
BACK | 古いのを読む | 新しいのを読む |