The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
%require "common.ps"
%require "rect.ps"
%require "ptr.ps"
%require "box.ps"
%require "mws.ps"
%require "sv-8.ps"

/he {                              % <x> <y> <keystring> <next_ptr> he -
   10 dict begin
     /cont exch def /str exch def /y exch def  /x exch def
     /len str length def
     /x2 x 70 add def
     /cw 8 def           % hek char width
     /x3 x2 40 add len 1 add cw mul add def

     1 LW
     x y 3 box

     /Helvetica 11 SF
     x 5 add y 12 sub M

     [(next)(hek)(val)] {
        gsave
        currentpoint 30 mws pop
        grestore
        0 -15 RM
     } forall

     % PTR to next
     cont { % ifelse
         x 42.5 add   y 7.5 sub
         x 57   add   y 7.5 sub
         x 57   add   y 55  sub
         x 25   add   y 55  sub
         x 25   add   y 70  sub
         ptrn
     } {
         x 42.5 add y 7.5 sub ptrn
     } ifelse
     
     % HEK arrow
     gsave 1 setgray x 55 add y 24 sub x2 y 21 sub rect F grestore
     x 42.5 add y 22.5 sub x2 ptr1

     % HEK
     0.8 setlinewidth
     gsave 0.8 setgray x3 cw sub y 27 sub x3 y 15 sub rect fill grestore
     x2 y 27 sub x3 y 15 sub rect S              % box
     gsave yellow x2 40 add y 27 sub x3 cw sub y 15 sub rect F grestore % key yellow
     x3 y 27 sub x3 20 add y 15 sub rect S       % flags
     % gsave yellow x3 20 add y 27 sub x3 y 15 sub rect F grestore % flags yellow
 
     x2 20 add dup y 27 sub M y 15 sub L S       % sep between HASH/LEN
     x2 40 add dup y 27 sub M y 15 sub L S       % sep after LEN

     % sep between characters
     gsave 0.3 LW
     x2 40 add cw x3 cw sub {
         dup y 27 sub M
         y 15 sub L S
     } for
     grestore

     /Helvetica 8 SF
     (hash) x2 2 add y 25 sub 16 mws pop
     x2 30 add y 25 sub M (len) cshow
     x3 cw add 2 add y 25 sub M (flag) cshow
     /Courier 7 SF
     x2 40 add cw 2 div add y 24 sub M
     str {
       gsave 1 string dup 3 2 roll 0 exch put cshow grestore
       cw 0 RM
     } forall
     (\\0) currentpoint cw 1 sub mwcs

     % anotate boxes
     /Courier 10 SF
     x 50 add y 2 add M (he) rshow
     x3 y 13 sub M (hek) rshow

     % VAL arrow and corresponding SV
     gsave 1 setgray x 55 add y 39 sub x2 y 36 sub rect F grestore
     1 LW
     x 42.5 add y 37.5 sub x2 ptr1
     x2 y 33 sub sv2

   end
} def

/hek { 		% <x> <y> <keystring> hek -
   10 dict begin
     /str exch def /y exch def  /x exch def
     /len str length def
     /cw 8 def           % hek char width
     /x2 x 40 add len 1 add cw mul add def
     /y y 15 add def

     0.8 setlinewidth
     gsave 0.8 setgray x2 cw sub y 27 sub x2 y 15 sub rect fill grestore
     x y 27 sub x2 y 15 sub rect stroke         % box
     x 20 add dup y 27 sub M y 15 sub L stroke  % sep between HASH/LEN
     x 40 add dup y 27 sub M y 15 sub L stroke  % sep between HASH/LEN

     % sep between characters
     gsave 0.3 setlinewidth
     x 40 add cw x2 cw sub {
         dup y 27 sub M
         y 15 sub L stroke
     } for
     grestore

     /Helvetica 8 SF
     (hash) x 2 add y 25 sub 16 mws pop
     x 30 add y 25 sub M (len) cshow
     /Courier 6 SF
     x 40 add cw 2 div add y 24 sub M
     str {
       gsave 1 string dup 3 2 roll 0 exch put cshow grestore
       cw 0 rmoveto
     } forall
     (\\0) cshow

     % anotate boxes
     /Courier 8 SF
     x2 y 13 sub M (hek) rshow

   end
} def