ASCII は英語(English language)にのみ適しています。 ただし、 ほとんどの西洋言語(western languages)は、それぞれの少数の特殊文字をエンコードするには 1 バイトで十分であるため、 Forth の枠組みにある程度適合します(ただし、常に同じエンコードを使用できるとは限りません。 ただし、 latin-1 が最も広く使用されています)。 他の言語の場合は、 異なる文字セットを使用する必要があり、その一部は可変幅です。 この問題に対処するために、 文字はスタック上ではユニコード・コードポイント(Unicode codepoints)として表され、 メモリー内では UTF-8 バイト文字列として表されることがよくあります。 ユニコード・コードポイントは、 多くの場合、 1 つのアプリケーション・ レベル(one application-level character)の文字を表しますが、 ユニコードは、基本文字(base letter)と結合発音記号(combining diacritical mark)など、 複数のコード・ポイントで構成される分解文字(combining diacritical mark)もサポートします。
ユニコード・コードポイントはメモリー内の複数バイトを消費する可能性があるため、 ここで我々の用語をすり合わせしておきましょう: char はメモリー内の生のバイト、 またはスタック上の 0 ~ 255 の範囲の値です。 xchar (extended char) は 1 つのコードポイントを表します。 これはメモリー内の 1 バイト以上で表され、 スタック上にはより大きな値が存在する可能性があります。 ASCII 文字は char や xchar と同一です。 つまり、0 ~ 127 の範囲の値、 かつ、 メモリー内のその値を含む 1 バイトです。
UTF-8 エンコードを使用する場合、 他のすべてのコードポイントは 1 文字あたり 1 バイト以上必要になります。 ほとんどの場合、 このような文字はメモリー内の文字列として扱うだけでよく、 以下のワード群を使用する必要はありませんが、 個々のコードポイントを処理したい場合は、 以下のワード群が役に立ちます。 現時点では、 分解文字(decomposed characters)を扱うためのワードはありません。
xchar ワード群はいくつかのデータ型を追加します:
xc-size
( xc – u ) xchar “x-c-size”
xchar xc のメモリー・サイズを char で計算します。
x-size
( xc-addr u1 – u2 ) xchar “x-size”
xc-addr に格納されている最初の xchar のメモリー・サイズを char で計算します。
xc@
( xc-addr – xc ) xchar-ext “xc-fetch”
xc-addr1 から xchar xc を取得します。
xc@+
( xc-addr1 – xc-addr2 xc ) xchar “x-c-fetch-plus”
xc-addr1 から xchar xc を取得します。 xc-addr2 は、 xc の後ろの最初のメモリー位置を指します。
xc@+?
( xc-addr1 u1 – xc-addr2 u2 xc ) gforth-experimental “x-c-fetch-plus-query”
文字列 xc-addr1 u1 の最初の xchar xc を取得します。 xc-addr2 u2 は xc の後ろの残りの文字列です。
xc!+?
( xc xc-addr1 u1 – xc-addr2 u2 f ) xchar “x-c-store-plus-query”
xchar xc を、 アドレス xc-addr1 で始まり u1 文字分の大きさであるバッファーに格納します。
xc-addr2 は xc の後の最初のメモリー位置を指し、 u2 はバッファの残りのサイズです。 xchar
xc がバッファーに収まった場合、 f は true、 それ以外の場合は f は false で
xc-addr2 u2 は xc-addr1 u1 と等しくなります。 XC!+?
はバッファー・オーバーフローに対して安全であるため、 XC!+
よりも推奨されます。
xc!+
( xc xc-addr1 – xc-addr2 ) xchar “x-c-store”
xchar xc を xc-addr1 に保存します。 xc-addr2 は、 バッファ内の次の未使用アドレスです。 これは最大 4 バイトを書き込むため、 アドレスをバッファの末尾と照合するだけの場合は、 有用なデータの上書きを避けるために、 バッファの末尾の後に少なくとも 3 バイトの余裕(パディング)が必要であることに注意してください。
xchar+
( xc-addr1 – xc-addr2 ) xchar “x-char-plus”
xc-addr1 に格納されている xchar のサイズをこのアドレスに加算し、 xc-addr2 を与えます(訳注: つまり、 次の xchar 文字の位置を返す)
xchar-
( xc-addr1 – xc-addr2 ) xchar-ext “x-char-minus”
xc-addr1 から xchar が見つかるまで逆方向に進み、 この xchar のサイズを xc-addr2 に加算すると xc-addr1 になります。
+x/string
( xc-addr1 u1 – xc-addr2 u2 ) xchar-ext “plus-x-slash-string”
アドレス xc-addr1 サイズ u1 文字で定義されたバッファーで xchar 1つ分だけ進めたアドレスを xc-addr2 に返します。 u2 は xchar 分だけ u1 より減ります(残り文字列長さです)。 u2 が 0 になったら末尾まで到達しています。 注意: 0 になってもそこで止まりません更に進んでしまうので注意(長さが負数になる)
x\string-
( xc-addr u1 – xc-addr u2 ) xchar-ext “x-backslash-string-minus”
バッファの最後から開始して、 アドレス xc-addr とサイズ u1 (char単位) で定義されたバッファー内で 1 xchar ずつ後方に進みます。 xc-addr は変わらず、 u2 は xchar 分ずつ短くなります。 注意: 0 になっても止まりません。そのまま長さが負数になっていきます。
-trailing-garbage
( xc-addr u1 – xc-addr u2 ) xchar-ext “minus-trailing-garbage”
xc-addr u1 というバッファー内の最後の XCHAR を調べます — エンコードが正しく、 完全な文字を表す場合 u2 は u1 と等しいです。 それ以外の場合は u2 は、 最後の(文字化けした) xchar を除いた文字列を表します。
x-width
( xc-addr u – n ) xchar-ext “x-width”
アドレス xc-addr 長さ u (char単位)の文字列に対して、同じ幅の等幅 ASCII 文字での文字数を n に得ます。 等幅フォントを想定しています。 つまり文字の幅はいずれも ASCII 文字の幅の整数倍であると仮定します(訳注: 含まれる xchar ごとにその表示幅を調べたのを積算して返します buf $@ type abcあdef ok buf $@len . 9 ok buf $@ x-width . 8 ok)
xkey
( – xc ) xchar “x-key”
端末から xchar を 1 つ読み取ります。 これにより、xchar の読み取りが完了するまでのすべての入力イベントが破棄されます(訳注: ヒストリ操作は効いたので…全ての入力イベント…?)。
xc-width
( xc – n ) xchar-ext “x-c-width”
xc の幅は、通常の固定幅グリフ(fixed-width glyph)の幅の n 倍です。
xhold
( xc – ) xchar-ext “x-hold”
<<#
と #>
の間で使用されます。 表示数値出力文字列(pictured numeric output
string)の前に xc を追加します。 代替手段としては holds
を使用することができます。
xc,
( xchar – ) xchar “x-c-comma”