サロゲートペア文字にも異体字セレクタ対象の文字があることに、「C++Builderで異体字セレクタを使う」の投稿後に気付いた。
1.表示は簡単
基本は変わらない。対象文字のコードポイントの上位・下位バイトが分かっていれば、以下の数行のコードで表示できる。
なおTEditのフォントは、Windows8.1以降に標準バンドルされている游明朝を使っている。(オープンソースの花園明朝Aを使えば、より多くの異体字が表示できる)
1 2 3 4 5 6 7 8 9 10 11 |
void __fastcall TForm1::Button1Click(TObject *Sender) { wchar_t wc[5]; wc[0] = 0xD84D; // 上位バイト wc[1] = 0xDE3A; // 下位バイト wc[2] = 0xDB40; wc[3] = 0xDD00; wc[4] = L'\0'; Edit1->Text = wc; } |
表示結果
標準字形と異体字を並べてみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
void __fastcall TForm1::Button1Click(TObject *Sender) { wchar_t wc[5]; wc[0] = 0xD84D; // 上位バイト wc[1] = 0xDE3A; // 下位バイト // 標準字形をセット wc[2] = L'\0'; String Str = wc; // 異体字をセット wc[2] = 0xDB40; wc[4] = L'\0'; for( int i = 0; i < 2; ++i ) { wc[3] = 0xDD01 + i; Str += wc; } Edit1->Text = Str; } |
表示結果
2.両対応の汎用メソッド
実際にはコードポイントをいちいち探したり求めるのは面倒くさいので、実際の文字と異体字番号(ゼロから指定)から異体字を求める汎用メソッドを作ってみる。サロゲートかどうかも気にしなくてよい。
(以下のサンプルは、Stringが複数の文字からなる場合は、先頭文字の異体字を返す)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#include <System.Character.hpp> // IsSurrogate: #include <algorithm> // std::min: static const unsigned int MAX_IVS_COUNT = 240; String __fastcall TForm1::StringToIvsString( const String& OrgStr, unsigned int ivs_num )const { ivs_num = std::min( ivs_num, MAX_IVS_COUNT - 1 ); wchar_t wc[5] = {}; wc[0] = OrgStr[1]; int begin_ivs = 1; if( System::Character::IsSurrogate( OrgStr, 1 ) ) { wc[1] = OrgStr[2]; begin_ivs = 2; } // wc[begin_ivs] = 0xDB40; wc[begin_ivs+1] = 0xDD00 + ivs_num; String RetStr = wc; return RetStr; } |
テストコード。
LabeledEditからIVS番号を取得して、文字を変換する。
2つのTEditのフォントは游明朝に設定している。
1 2 3 4 5 6 7 8 9 |
void __fastcall TForm1::BtnToIvsClick(TObject *Sender) { if( EditOrgStr->Text.IsEmpty() ) return; String Str = StringToIvsString( EditOrgStr->Text, LabeledEditIvsNum->Text.ToInt() ); EditIvs->Text = Str; } |
実行結果。
3.TRichEditの挙動が非サロゲートと異なる(?)
サロゲートペアの異体字をTRichEditに表示した場合、非サロゲートペアの場合と異なり、余分な空白が表示されないようだ。
異体字と標準字形を並べて表示してみると…。(左がTMemo、右がTRichEdit)
この挙動は謎。
なお、異体字の後ろにカーソルを置いた状態で、BackSpaceキーを押下すると〝先祖返り〟する挙動は、非サロゲート文字と変わらない。
C++Builder10.2.3とWindows10で確認。