%!PS
% shamlessy derived from https://robrich.org/archive/2006/10/30/postscriptissoelegant.aspx
/debug_flag true def
/block_element_count 4 def %number of items in a text block
/block_index 0 def %current block to use
/block_count 0 def %number of blocks
/block_max 10 def %maximum number of blocks
/block_storage block_max block_element_count mul array def
/newline { % - newline -
%add block compatible newline
currentpoint exch pop line_height sub
bottom_margin lt {
%move to next box
(move to next box) ==
block_index 1 add block_count ge {
(move to next page ) ==
showpage
} if
block_index 1 add block_count mod set_current_block
} {
%move one line down
(move one line down) ==
left_margin currentpoint exch pop line_height sub moveto
} ifelse
} def
/too_far { % (string) too_far -> bool
%Is the word too long for the space on the line?
dup
stringwidth pop
currentpoint pop
add right_margin
gt
} bind def
/show_word { % (string) show_word ->
%Show a word, line wrap if can't fit
too_far { newline } if show
} def
/show_text { %(string) showtext ->
%show text line wrap if needed
% in a loop, break by spaces, and print each word.
% If there isn't a space left, be done.
{
( ) search
exch
show_word
not
{
exit
} if
show
}
loop
} def
/set_current_block { %block_index set_current_block ->
%set margin state for the givin block index
/block_index exch def
/top_margin block_storage block_index block_element_count mul 0 add get def
/right_margin block_storage block_index block_element_count mul 1 add get def
/bottom_margin block_storage block_index block_element_count mul 2 add get def
/left_margin block_storage block_index block_element_count mul 3 add get def
left_margin top_margin line_height sub moveto
debug_flag {
currentpoint
left_margin top_margin moveto
right_margin top_margin lineto
right_margin bottom_margin lineto
left_margin bottom_margin lineto
closepath
stroke
moveto
} if
} def
/add_text_block { %left top width height text_block ->
%add new text block
4 2 roll % width height left top
%top
block_storage exch block_count block_element_count mul 0 add exch put
%left
block_storage exch block_count block_element_count mul 3 add exch put
%bottom
block_storage exch block_count block_element_count mul 2 add exch
block_storage block_count block_element_count mul 0 add get exch sub put
%right
block_storage exch block_count block_element_count mul 1 add exch
block_storage block_count block_element_count mul 3 add get exch add put
/block_count block_count 1 add def
debug_flag {
(====block_storage) =
block_storage ==
(====block_count) =
block_count =
(====E) =
} if
} def
/r_sep { % (r_text) r_sep -
% finish with a line to right justified r_text
% use setdash to get dotted lines
% existing text............r_text
dup
stringwidth pop
right_margin exch sub % x point of end of line
currentpoint exch pop % y point of end of line
lineto currentpoint stroke moveto
show
} def
/use_font { %font size -> %set font and line_height
/line_height exch def
findfont line_height scalefont setfont
} def
/inch {
72 mul
} def
/Times 28 use_font
0.5 inch
11 inch 1 inch sub
3 inch
3 inch
add_text_block
4.5 inch
11 inch 1 inch sub
3 inch
3 inch
add_text_block
%0.5 inch
%11 inch 5 inch sub
%3 inch
%3 inch
%add_text_block
0 set_current_block
(On Windows, I ran it though Ghostscript on huge documents with no difference. On Unix though, it dogged the Ghostscript engine to death. (My awk script ran like a dream though.) ) show_text
/Times 10 use_font
(A google board post led me to the most elegant auto-paging and auto-line-wrap function. The auto-paging is easy: when you're moving to the next line, if you'll go off the page, do the show page and new page routines first. The line wrap a bit more complex though. It splits by spaces, compares the length of the first word it got back against the right margin minus the current point, and decides if it needs to line wrap before printing this word. Then it displays the space. The elegant part? Argument 2 of the split function's return value is "the rest". Called in a loop, it cycles through all the words on a page, line-breaking as needed.) show_text
%5.5 inch
%11 inch 1 inch sub
%2 inch
%9 inch
%text_block
(Ok, most people don't code in PostScript. Granted, like SQL, it's one of those languages that's usually coded by a program written in another language. But it's so incredibly elegant!) show_text
newline
(Fun with process descriptors) show_text (20) r_sep
(Other Interesting things) show_text (43) r_sep
(Wow so much sep) show_text (52) r_sep
showpage