1バイト、2バイト、3バイト文字の入り乱れたEUC-JP文字列を1文字ずつ出力する(PostScript)。

文字列を出力して行末に達したときは、改行して次の行の先頭から表示しなければなりません。
行末に達したかどうかは currentpoint で現在の位置を求め、 stringwidth で印刷しようとする文字列の幅を求めれば良いのですが、長い文章全体の幅を求めても意味がありません。文字列を1文字と残りの文字列に分けて、 その1文字の幅から改行すべきかどうか判定するようにします。
PostScriptでは1バイトで文字列から一部文字列を取得できますが、EUC-JP の文字列は1バイト、2バイト、3バイト文字が入り乱れています。
1バイト、2バイト、3バイト文字と長さを考慮しながら、先頭の1文字と残りの文字列に分割する手続きを作成します。

%!PS-Adobe-3.0

/mm { 2.834645669 mul } def
newpath 

/Space 3 mm def
/Left 20 mm def

/Ryumin-Light-EUC-H findfont 20 scalefont setfont

/vPosition  297 mm 20 mm sub def  % A4 297mm
/hPosition Left Space add def

/newline { /vPosition vPosition 25 sub def
            hPosition vPosition moveto } def 

hPosition vPosition moveto 

(Hello,world!) 0 get ==      %=> 72
(あ) 0 get ==                %=> 164
(あ) 1 get ==                %=> 162

5 string ==                     % (\000\000\000\000\000)

/str 5 string def
str 0 16#2a put                 %=> '*'
str 1 16#30 put                 %=> '0'
str 2 164 put
str 3 162 put

str show      %=> "*0あ" が表示される。

% 半角カナは 8ea1 〜 8edf
/s 5 string def
s 0 16#8e put
s 1 16#dc put                 %=> 'ワ'
s 2 16#8e put
s 3 16#dd put                 %=> 'ン'

newline  s show      %=> "ワン" が表示される。
% newline  (。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテト) show
% newline  (ナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚) show

% 先頭から指定長の文字列を取得して返す。
/Head { 0 exch getinterval} def


% 指定位置より後ろ文字列を返す。
% 参考:ローカル変数に値を渡す方法
% http://www.cs.kyoto-wu.ac.jp/~konami/documents/ps/psmemo.html#subsec6:5
/ldict 1 dict def
/Tail {
    ldict begin
    /start exch def
    /str   exch def
    /len str length start sub def
    str start len getinterval
    end
} def

(abcdefghijk) 2 Head == % (ab)
(abcdefghijk) 2 Tail == % (cdefghijk)

位置を指定して文字列を分割できるようになりましたので、先頭が1バイト文字のときは1バイトと残り、2バイト文字のときは2バイトと残り、3バイト文字のときは3バイトと残りに分割するようにします。

% 数字から文字列へ
1.2345 20 string cvs ==                    %=> (1.2345)

(abcdefghijk) 0 get 16#7e le ==
(あabcdefghijk) 0 get 16#7e le ==

/isASCII   { 16#7e le } def

% 半角カナは 8ea1 〜 8edf 
/isHANKAKU { 16#8e eq } def   % 1byte 文字

% 拡張漢字 3byte :8FA1A1  〜 8FE9F8(FEFE)
/isKAKUCHO { 16#8F eq } def   % 3byte 文字

% A1A1 〜 E9F8(FEFE)
/isKANJI { dup 16#a1 ge exch 16#e9 le and} def

(abcdefghijk) 0 get isASCII ==  % => true
(アイウエオカキクケコサ) 0 get isASCII ==  % => false
(あabcdefghi) 0 get isASCII ==  % => false

(アイウエオカキクケコサ) 0 get isHANKAKU == % => true
(abcdefghijk) 0 get isHANKAKU ==
(あabcdefghi) 0 get isHANKAKU ==

(あいう) 0 get isKANJI ==        % => true

% 1バイト、2バイト、3バイト文字を考慮しながら、先頭の1文字と残りの文字列を分けて
% スタックに積みます。
% 1バイト以上の文字列でないと str 0 get のときスタックアンダーフローになります。
/sdict 1 dict def
/Split {
    sdict begin
    /str   exch def
    str 0 get isASCII { str 1 Tail  str 1 Head}                       % 1byte 文字
                      { str 0 get isKAKUCHO { str 3 Tail  str 3 Head} % 3byte 文字
                                            { str 2 Tail  str 2 Head} ifelse } ifelse
    end
} def

(aあイウ漢いうえおcdefghijk) Split
newline  show   % => a
Split
newline  show   % => あ
Split
newline  show   % => イ
Split
newline  show   % => ウ
Split
newline  show   % => 漢
newline  show   % => いうえおcdefghijk

clear
(あ) Split
pstack          % (\244\242) ()
clear

showpage