文字列が枠内におさまるように自動改行しながら印刷する(PostScript)。

PostScriptで表を作るとき、長い文字列でも枠からはみ出さないように自動改行しながら印刷します。

%!PS-Adobe-3.0
% EUC-JP で記述すること。
2.834645669 2.834645669 scale % これでポイントだった単位がミリになります。
newpath 

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

/vPosition   297 20 sub def  % A4 297mm
/Space 3 def
/CellW 100 def
/ADJW CellW Space 2 mul sub def
0.3 setlinewidth
/Left 20 def
/newLineHight 12 def

/hPosition Left Space add def

hPosition vPosition moveto
CellW       0 rlineto
0        newLineHight 8 mul neg rlineto
CellW neg   0 rlineto
closepath stroke


/newline { /vPosition vPosition newLineHight sub def
            hPosition Space add vPosition moveto } def 


% 先頭から指定長の文字列を取得して返す。
/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

/isASCII   { 16#7e le } def                    % 1byte 文字
/isHANKAKU { 16#8e eq } def                    % 2byte:半角カナは 8ea1 〜 8edf 
/isKAKUCHO { 16#8F eq } def                    % 拡張漢字 3byte :8FA1A1  〜 8FE9F8(FEFE)
/isKANJI { dup 16#a1 ge exch 16#e9 le and} def % 2byte漢字: A1A1 〜 E9F8(FEFE)

% 1バイト、2バイト、3バイトの1文字と残りの文字列に分ける。
/sdict 1 dict def                       % Stack String -> 1文字String 残り文字列
/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

% 残りの文字列が 0 より長いときは foldString を再帰する
/ifFoldString { dup length 0 gt { foldString } if } def

%  指定位置で折り返しながら文字列を表示。
/foldString {
     Split
     dup stringwidth pop     % 1文字を複製し、幅を求める
     currentpoint pop        % 現在の座標取得。Y座標は捨てる
     add                     % 現在位置 + 文字列の幅
     ADJW hPosition add      % 終点
     le { show  ifFoldString }  % 終点より座標が少ないときは1文字表示。残り文字があれば再帰。
                                % 改行して1文字表示。残り文字があれば再帰。
        { newline show ifFoldString }ifelse                 %
  } def

hPosition Space add vPosition moveto newline
(本日は晴天なり本日は晴天なり。我輩は猫である。名前はまだない。Hello,world! 枠内に入るよう横幅を調整しています。) foldString

showpage