[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

MF hackery (arrow kit) + CM design questions




Last night, I only wanted to investigate why the triple arrows in the
MS2 arrow kit were turning out bolder than the single and double ones,
but I eventually ended up applying lots of minor corrections and
improvements throughout al of the MF sources for the arrow kit,
resulting in one big patch attached below:

Changes include:

* triple arrowheads redesigned to match single and double arrowheads,
  using |rule_thickness| instead of |bar| or |1.5bar|.

* all characters: added or updated |penlabels| to get points numbered
  in the GFtoDVI proof sheets.

* all characters: added |adjust_fit(0,0)| where it was missing to
  get width characters boxes fixed properly.

* many characters: adjusted lft/rt positioning of control points.
  In general, the tips of arrowheads are positioned with lft/rt 
  while overshooting ends for extensible arrows are centered on
  the middle of the control points, i.e. without using lft/rt.

* dashed arrows and arrow extension pieces: improved the code using 
  for-loops instead of tedious repetions of |drawdot|.
  
* changed the width of arrow extension pieces to 12u# (equivalent
  to 2/3 of 1em) instead of 14u#, and use a factor of 3/2 instead 
  of 4/3 for the wide extension pieces, so that they end up being 
  exactly 18u# wide (equivalent to 1em) instead of 18.66u#.
  
Remaining problems:

* The construction of zero-width characters is different from
  that of Knuth's mapstochar.  Instead of directly specifying
  a width of 0pt#, he first used a non-zero width, followed 
  by |adjust_fit(0,0)| and a call to |zero_width|.  Is there
  any difference other than correctly setting the width of the
  proof-sheet box?  The problem is that calling |adjust_fit(0,0)|
  after specifying a width of 0pt# gives a division-by-zero error.

* The gaped squiggly arrows produce some stray pixes within the 
  are that should be erased.  Anyone knows how to fix this???

* There are still a few remaining inconsistencies as to when 
  points are positioned at hround(w-u) or hround(w-u-eps), etc.

* I haven't yet tested if the dot separation of dashed arrowheads
  and arrow extension pieces fits smoothly.  With 8 dots per 12u#
  the dot separation would be 1.5u# and the first dot would have 
  to be positioned at 0.5dot_sep (or 0.75u#) from the edges of 
  the character box.  I hope this will be satisfied in all cases.

* I haven't yet checked if all the arrows (apparently assembled
  from various sources) follow the design principles of Knuth's
  latest sources or if some of them are still based on old CM.

* It is unclear to me why there is an |italcorr| specification
  for some of the arrow extension pieces.  I presume this would
  be totally unecessary in an unslanted symbol font anyway.

So long, Ulrik.

P.S. Another unrelated MF problem: It appears that the vector 
accent from cmmi has a slanted arrowhead, while the reversevector 
and doublevector form ymc are upright.  Would you agree that all 
three  of them should be the same style (preferably upright)?

P.P.S.  Another one: The CM square brackets from punct.mf have 
a width of 5u# (and relatively little side-bearings), while the
floor/ceiling bracktes from symbol.mf have a width of 8u# (with 
wider side-bearings and rounded corners at the end of strokes).
Now the big square brackets have a width of 6u, 6.5u, 7u, 7.5u,
while the big floor/ceilings have a width of 7u, 7.5u, 8u, 8.5u,
and both of the share the same set of extensible modules.

Would it seem reasonable that all of them should have consistent
widths or is there a good design reason why floors/ceilings are
a little wider?  I suppose that even if we consider this a bug, 
we will have to keep the old widths for metrics compatibility
in the CM implementation, although it might also be interesting 
to provide an alternative optimized version as well.  Opions?



diff -u ORIG/ymedel.mf ./ymedel.mf
--- ORIG/ymedel.mf	Thu Oct  2 20:42:07 1997
+++ ./ymedel.mf	Wed Oct 29 23:00:25 1997
@@ -16,7 +16,7 @@
 x4=x3; y4=y1; z5=.5[z1,z4]; z6=.5[z2,z3];
 draw z5--z6;
 draw z4--z1--z2--z3;  % stem and bar
-labels(1,2,3); endchar;
+labels(1,2,3,4,5,6); endchar;
 
 cmchar "Left multiset bracket";
 beginchar(slot_multisetbracketleft,9u#,body_height#,paren_depth#);
diff -u ORIG/ymearr.mf ./ymearr.mf
--- ORIG/ymearr.mf	Thu Oct  2 21:02:54 1997
+++ ./ymearr.mf	Thu Oct 30 04:37:47 1997
@@ -1,6 +1,10 @@
+% experimental changes:
+%
+% arrow_ext_width#:=12u#;	(was: 14u#)
+% 3/2arrow_ext_width#:=18u#;	(was: 4/3x, 18.66u#)
 
-arrow_ratio:=14/9;
-arrow_ext_width#:=14u#;
+arrow_ratio:=12/9;
+arrow_ext_width#:=12u#;
 arrow_head_width#:=9u#;
 arrow_overshoot:=u-eps;
 
@@ -25,24 +29,25 @@
   ...z5{z6-z4}...z6{up}...z7{z8-z6}...cycle;  % circle and interior
 enddef;
 
-% 8 control glyphs 
+% 8 control glyphs
 
-cmchar "Single left end"; 
+cmchar "Single left arrow end"; 
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_NONE,arrow_head_width#,single_height); 
 adjust_fit(0,0); pickup rule.nib;
-y0=y1=math_axis; x1=hround(w+arrow_overshoot); lft x0=hround u;
-draw z0--z1; endchar;
+lft x1=hround u; x2=hround(w+arrow_overshoot);
+y1=y2=math_axis;
+draw z1--z2;
+penlabels(1,2); endchar;
 
 cmchar "Single arrow extension";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_singleext,arrow_ext_width#,single_height); 
-pickup rule.nib;
-lft x1=hround(0-arrow_overshoot); 
-x2=w-x1; 
+adjust_fit(0,0); pickup rule.nib;
+x1=hround(0-arrow_overshoot); x2=w-x1; 
 y1=y2=math_axis;
 draw z1--z2;  % bar
-labels(1,2); endchar;
+penlabels(1,2); endchar;
 
 cmchar "Single arrow negation";
 compute_spread(.45x_height#,.55x_height#);
@@ -57,55 +62,51 @@
 cmchar "Single arrow negated extension";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_NEGEXT,arrow_ext_width#,single_height); 
-pickup rule.nib;
-lft x1=hround 0 - arrow_overshoot; x2=w-x1; y1=y2=math_axis;
+adjust_fit(0,0); pickup rule.nib;
+x1=hround(0-arrow_overshoot); x2=w-x1;
+y1=y2=math_axis;
 draw z1--z2;  % bar
 y3-y1=.24asc_height+eps;
 char_center(100); top y101=top y3; x101=x100+2u;
 char_negate(100,101,102);
-labels(1,2); endchar;
-
-cmchar "Single gap";
-compute_spread(.45x_height#,.55x_height#);
-beginchar(slot_GAP,arrow_ext_width#/3,single_height); 
-endchar;
+penlabels(1,2); endchar;
 
 cmchar "Single arrow gaped extension";
 compute_spread(.45x_height#,.55x_height#);
-beginchar(slot_GAPEXT,4/3arrow_ext_width#,single_height); 
-pickup rule.nib;
-lft x1=hround(0-arrow_overshoot); 
+beginchar(slot_GAPEXT,3/2arrow_ext_width#,single_height); 
+adjust_fit(0,0); pickup rule.nib;
+x1=hround(0-arrow_overshoot); x4=w-x1;
 x2=hround (3/8w); 
 x3=hround (5/8w);
-x4=w-x1;
 y1=y2=y3=y4=math_axis;
 draw z1--z2;  % bar
 draw z3--z4;
-labels(1,2,3,4); endchar; 
+penlabels(1,2,3,4); endchar; 
 
 cmchar "Squiggly arrow extension";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_SQUIG,arrow_ext_width#,single_height); 
-adjust_fit(0,0); 
+adjust_fit(0,0); pickup rule.nib;
 y2=y4; y1=y3=y5; y3-y4=.24asc_height+eps;
 .5[y3,y4]=math_axis;
 x2-x1=x3-x2=x4-x3=x5-x4;
 x1=0; x5=w;
 pickup pencircle scaled rule_thickness; 
 draw z1{right}..z2{right}..z3{right}..z4{right}..{right}z5; 
-endchar;
+penlabels(1,2,3,4,5); endchar;
 
-cmchar "Single arrow dashed extension";
+cmchar "Single dashed arrow extension";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_DASH,arrow_ext_width#,single_height); 
-pickup rule.nib;
+italcorr h#*slant-.5u#;
+adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8;
-x0=0;
-y0=y1=y2=y3=y4=y5=y6=y7=y8=math_axis;
-2(x1-x0)=x2-x1=x3-x2=x4-x3=x5-x4=x6-x5=x7-x6=x8-x7=dot_sep;
-drawdot z1; drawdot z2; drawdot z3; drawdot z4;
-drawdot z5; drawdot z6; drawdot z7; drawdot z8;
-labels(0,1,2,3,4,5,6,7,8); endchar;
+x0=0; y0=math_axis;
+2(x1-x0)=dot_sep; y1=y0; drawdot z1;
+for j=2 thru 8:
+  x[j]-x[j-1]=dot_sep; y[j]=y0; drawdot z[j];
+endfor
+penlabels(0,1,2,3,4,5,6,7,8); endchar;
 
 % 24 left heads
 
@@ -115,7 +116,8 @@
 adjust_fit(0,0); pickup crisp.nib;
 pos1(rule_thickness,90); pos2(rule_thickness,90);
 pos3(rule_thickness,0); pos4(rule_thickness,0);
-y0=y1=y2=math_axis; x1=hround(w); lft x0=hround u;
+y0=y1=y2=math_axis;
+lft x0=hround u; x1=hround(w+arrow_overshoot); 
 y3-y0=y0-y4=if monospace:.24 else:.36 fi asc_height+eps;
 x3=x4=x0+if monospace:3u else:4u fi+eps;
 pos5(rule_thickness,angle(z4-z0)); z5l=z0;
@@ -132,10 +134,11 @@
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Head,arrow_head_width#,double_height);
 adjust_fit(0,0); pickup rule.nib;
-lft x7=hround u-eps; x8=x7; x1=x2=w+arrow_overshoot;
+lft x7=hround u-eps; x8=x7; x1=x2=hround(w+arrow_overshoot);
 y1=y7; y2=y8; y1-y2=spread; .5[y1,y2]=math_axis;
 draw z1--z7; draw z2--z8;  % bars
-pickup crisp.nib; lft x0=hround u-eps; y0=good.y math_axis;
+pickup crisp.nib;
+lft x0=hround u-eps; y0=good.y math_axis;
 pos3(rule_thickness,0); pos4(rule_thickness,0);
 y3-y1=y2-y4=.24asc_height+eps; x3=x4=x0+6u+eps;
 pos5(rule_thickness,angle(z4-z0)); z5l=z0;
@@ -152,24 +155,26 @@
 cmchar "Triple left arrow head"; 
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_HEAD,arrow_head_width#,triple_height); 
-adjust_fit(0,0); pickup rule.nib; penpos1(rule_thickness,90); 
-penpos2(rule_thickness,90); penpos3(1.5bar,0); penpos4(1.5bar,0); 
+adjust_fit(0,0); pickup crisp.nib;
+pos1(rule_thickness,90); pos2(rule_thickness,90);
+pos3(rule_thickness,0); pos4(rule_thickness,0); 
 y0=y1=y2=math_axis; x1=hround(w+arrow_overshoot); 
-lft x0=hround u; x0'=x0''=x0; x1'=x1''=x1; 
-y1'=y1+spread;y1''=y1-spread; y0'=y1'; y0''=y1''; draw 
-z0'--z1'; draw z0''--z1''; % draw bars  
+lft x0=hround u-eps; x0'=x0''=x0; x1'=x1''=x1; 
+y1'-y1=y1-y1''=spread; y0'=y1'; y0''=y1'';
+pickup rule.nib;  
+draw z0'--z1'; draw z0''--z1''; % draw bars  
 pickup crisp.nib;  
 y3-y0'=y0''-y4=.24asc_height+eps; x3=x4=x0+6u+eps; 
-pos5(bar,angle(z4-z0)); z5l=z0; pos6(bar,angle(z3-z0)); 
-z6l=z0; z9=.381966[.5[z3,z4],z0]; erase filldraw 
-z0..{z3-z9}z3--(0,y3) 
- --(0,y4)--z4{z9-z4}..z0& cycle; numeric t; path p; 
-p=z4r{z9-z4}..z6r; t=xpart(p 
-intersectiontimes((0,y2l)--(w,y2l))); x2=xpart point t of p; 
+pos5(rule_thickness,angle(z4-z0)); z5l=z0;
+pos6(rule_thickness,angle(z3-z0)); z6l=z0;
+z9=.381966[.5[z3,z4],z0];
+erase filldraw z0..{z3-z9}z3--(0,y3) 
+ --(0,y4)--z4{z9-z4}..z0& cycle;
+numeric t; path p; p=z4r{z9-z4}..z6r;
+t=xpart(p intersectiontimes((0,y2l)--(w,y2l))); x2=xpart point t of p; 
 pickup rule.nib; draw z2--z1; pickup crisp.nib;  
 filldraw z0..{z4-z9}z4l--subpath (0,t) of\\(z4r{z9-z4}..z6r)
-%--z2l---z1l..z1r---z2r
---subpath (t,0) of\\(z3r{z9-z3}..z5r) 
+ --subpath (t,0) of\\(z3r{z9-z3}..z5r) 
  --z3l{z9-z3}..z0 & cycle;  % arrowhead and stem 
 penlabels(0,1,2,3,4,5,6,9,0',0'',1',1''); endchar; 
 
@@ -179,7 +184,7 @@
 penpos1(.25rule_thickness,90); penpos2(.25rule_thickness,90); penpos3(bar,0); 
 penpos4(bar,0);
 y0=y1=y2=math_axis; x0=hround 1.5u-eps;
-rt x1=w-(hround 0-arrow_overshoot);
+x1=(hround w+arrow_overshoot);
 y3-y0=y0-y4=.24asc_height+eps; x3=x4=x0+3u+eps;
 penpos5(bar,angle(z4-z0)); z5l=z0; penpos6(bar,angle(z3-z0)); z6l=z0;
 z9=.381966[.5[z3,z4],z0];
@@ -196,17 +201,13 @@
 adjust_fit(0,0); pickup crisp.nib;  
 pos1(rule_thickness,90); pos2(rule_thickness,90); 
 pos3(bar,0); pos4(bar,0); y0=y1=y2=math_axis; 
-x1=hround(w+arrow_overshoot); % x1+.5rule_thickness=hround(w-u); 
-lft x0=hround u; 
+x1=hround(w+arrow_overshoot); lft x0=hround u; 
 y3-y0=y0-y4=.24asc_height+eps; x3=x4=x0+3u+eps; 
 pos5(bar,angle(z4-z0)); z5l=z0; pos6(bar,angle(z3-z0)); 
 z6l=z0; z9=.381966[.5[z3,z4],z0];  
-numeric t; path p;  
-p=z4r{z9-z4}..z6r;  
-t=xpart(p intersectiontimes((0,y2l)--(w,y2l)));  
-x2=xpart point t of p;  
-path p; p=z0..{z4-z9}z4l--subpath (0,t) 
-of\\(z4r{z9-z4}..z6r) 
+numeric t; path p;  p=z4r{z9-z4}..z6r;
+t=xpart(p intersectiontimes((0,y2l)--(w,y2l))); x2=xpart point t of p;
+path p; p=z0..{z4-z9}z4l--subpath (0,t) of\\(z4r{z9-z4}..z6r) 
  --z2l--z2r--subpath (t,0) of\\(z3r{z9-z3}..z5r) 
  --z3l{z9-z3}..z0 & cycle; % second arrowhead 
 filldraw z0..{z4-z9}z4l--subpath (0,t) of\\(z4r{z9-z4}..z6r) 
@@ -223,7 +224,7 @@
 y1=y2=math_axis; y1-y3=y4-y1=.24asc_height+eps;
 draw z3--z4;  % stem
 draw z1--z2;  % bar stub
-labels(1,2,3,4); endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Double left mapsto arrow head";
 compute_spread(.45x_height#,.55x_height#);
@@ -235,7 +236,7 @@
 draw z3--z4;  % stem
 draw z1--z2;  % bar stub
 draw z5--z6;  % bar stub
-labels(1,2,3,4,5,6); endchar;
+penlabels(1,2,3,4,5,6); endchar;
 
 cmchar "Triple left mapsto arrow head";
 compute_spread(.45x_height#,.55x_height#);
@@ -248,7 +249,7 @@
 draw z1--z2;  % bar stub
 draw z5--z6;  % bar stub
 draw z7--z8;  % bar stub
-labels(1,2,3,4,5,6,7,8); endchar;
+penlabels(1,2,3,4,5,6,7,8); endchar;
 
 cmchar "Left hook up";
 compute_spread(.45x_height#,.55x_height#);
@@ -258,7 +259,7 @@
 y1-y3=spread; y2=.5[y1,y3]; y3=math_axis=y4;
 x4=hround(w+arrow_overshoot);
 draw z1{left}...z2{down}...z3{right}---z4;  % hook
-labels(1,2,3); endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Left hook down";
 compute_spread(.45x_height#,.55x_height#);
@@ -268,7 +269,7 @@
 y3-y1=spread; y2=.5[y1,y3]; y3=math_axis=y4;
 x4=hround(w+arrow_overshoot);
 draw z1{left}...z2{up}...z3{right}---z4;  % hook
-labels(1,2,3); endchar;
+penlabels(1,2,3,4); endchar;
 
 % 146: Left harpoon up
 % 147: Left harpoon down
@@ -313,7 +314,8 @@
 adjust_fit(0,0); pickup crisp.nib;
 pos1(rule_thickness,90); pos2(rule_thickness,90);
 pos3(rule_thickness,0); pos4(rule_thickness,0);
-y0=y1=y2=math_axis; x1=hround (0); rt x0=hround(w-u);
+y0=y1=y2=math_axis; 
+rt x0=hround(w-u); x1=hround(0-arrow_overshoot); 
 y3-y0=y0-y4=if monospace:.24 else:.36 fi asc_height+eps;
 x3=x4=x0-if monospace:3u else:4u fi-eps;
 pos5(rule_thickness,angle(z4-z0)); z5l=z0;
@@ -330,10 +332,11 @@
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Headright,arrow_head_width#,double_height);
 adjust_fit(0,0); pickup rule.nib;
-lft x1=hround 0 - arrow_overshoot; x2=x1; x7=x8=w-hround u-eps;
+x1=x2=hround(0-arrow_overshoot); rt x7=w-hround u-eps; x8=x7;
 y1=y7; y2=y8; y1-y2=spread; .5[y1,y2]=math_axis;
 draw z1--z7; draw z2--z8;  % bars
-pickup crisp.nib; rt x0=hround(w-u)+eps; y0=good.y math_axis;
+pickup crisp.nib;
+rt x0=hround(w-u)+eps; y0=good.y math_axis;
 pos3(rule_thickness,0); pos4(rule_thickness,0);
 y3-y1=y2-y4=.24asc_height+eps; x3=x4=x0-6u-eps;
 pos5(rule_thickness,angle(z4-z0)); z5l=z0;
@@ -350,24 +353,26 @@
 cmchar "Triple right arrow head"; 
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_HEADright,arrow_head_width#,triple_height); 
-adjust_fit(0,0); pickup rule.nib; penpos1(rule_thickness,90); 
-penpos2(rule_thickness,90); penpos3(1.5bar,0); penpos4(1.5bar,0); 
+adjust_fit(0,0); pickup crisp.nib;
+pos1(rule_thickness,90); pos2(rule_thickness,90);
+pos3(rule_thickness,0); pos4(rule_thickness,0); 
 y0=y1=y2=math_axis; x1=hround(0-arrow_overshoot);  
-rt x0=hround (w-u); x0'=x0''=x0; x1'=x1''=x1; 
-y1'=y1+spread;y1''=y1-spread; y0'=y1'; y0''=y1''; 
+rt x0=hround(w-u)+eps; x0'=x0''=x0; x1'=x1''=x1; 
+y1'-y1=y1-y1''=spread; y0'=y1'; y0''=y1''; 
+pickup rule.nib;  
 draw z0'--z1'; draw z0''--z1''; % draw bars  
 pickup crisp.nib;  
 y3-y0'=y0''-y4=.24asc_height+eps; x3=x4=x0-6u-eps; 
-penpos5(bar,angle(z0-z4)); z5r=z0; penpos6(bar,angle(z0-z3)); 
-z6r=z0; z9=.381966[.5[z3,z4],z0]; erase filldraw 
-z0..{z3-z9}z3--(w,y3)--(w,y4)--z4{z9-z4}..z0& cycle; 
-numeric t; path p; 
-p=z4l{z9-z4}..z6l; t=xpart(p intersectiontimes((0,y2l)--(w,y2l))); 
-x2=xpart point t of p; 
+pos5(rule_thickness,angle(z0-z4)); z5r=z0;
+pos6(rule_thickness,angle(z0-z3)); z6r=z0;
+z9=.381966[.5[z3,z4],z0];
+erase filldraw z0..{z3-z9}z3--(w,y3)
+ --(w,y4)--z4{z9-z4}..z0& cycle; 
+ numeric t; path p; p=z4l{z9-z4}..z6l;
+ t=xpart(p intersectiontimes((0,y2l)--(w,y2l))); x2=xpart point t of p; 
 pickup rule.nib; draw z2--z1; pickup crisp.nib;  
 filldraw z0..{z4-z9}z4r--subpath (0,t) of\\(z4l{z9-z4}..z6l) 
-% --z2l---z1l..z1r---z2r
---subpath (t,0) of\\(z3l{z9-z3}..z5l) 
+ --subpath (t,0) of\\(z3l{z9-z3}..z5l) 
  --z3r{z9-z3}..z0 & cycle;  % arrowhead and stem 
 penlabels(0,1,2,3,4,5,6,9,0',0'',1',1''); endchar; 
 
@@ -377,8 +382,8 @@
 penpos1(.25rule_thickness,90); penpos2(.25rule_thickness,90); penpos3(bar,0); 
 penpos4(bar,0);
 y0=y1=y2=math_axis; 
-x1=hround 0 - arrow_overshoot;
-rt x0=w-(hround 1.5u-eps);
+x1=hround(0-arrow_overshoot);
+x0=w-(hround 1.5u-eps);
 y3-y0=y0-y4=.24asc_height+eps; x3=x4=x0-3u-eps;
 penpos5(bar,angle(z4-z0)); z5l=z0; penpos6(bar,angle(z3-z0)); z6l=z0;
 z9=.381966[.5[z3,z4],z0];
@@ -392,16 +397,18 @@
 cmchar "Right double arrow head"; 
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_doubleheadright,arrow_head_width#,single_height); 
-adjust_fit(0,0); 
-pickup crisp.nib;  pos1(rule_thickness,90); pos2(rule_thickness,90); 
-pos3(bar,0); pos4(bar,0);  y0=y1=y2=math_axis; x1=hround(0-arrow_overshoot); 
-rt x0=hround(w-u); y3-y0=y0-y4=.24asc_height+eps; x3=x4=x0-3u-eps; 
+adjust_fit(0,0); pickup crisp.nib;
+pos1(rule_thickness,90); pos2(rule_thickness,90); 
+pos3(bar,0); pos4(bar,0);  y0=y1=y2=math_axis;
+x1=hround(0-arrow_overshoot); rt x0=hround(w-u);
+y3-y0=y0-y4=.24asc_height+eps; x3=x4=x0-3u-eps; 
 pos5(bar,angle(z4-z0)); z5l=z0; pos6(bar,angle(z3-z0)); z6l=z0; 
-z9=.381966[.5[z3,z4],z0]; numeric t; path p; p=z4l{z9-z4}..z6r;  t=xpart(p 
-intersectiontimes((0,y2l)--(w,y2l)));  x2=xpart point t of p;  path p; 
-p=z0..{z4-z9}z4r--subpath (0,t) of\\(z4l{z9-z4}..z6r) 
+z9=.381966[.5[z3,z4],z0];
+numeric t; path p; p=z4l{z9-z4}..z6r;
+t=xpart(p intersectiontimes((0,y2l)--(w,y2l)));  x2=xpart point t of p;
+path p; p=z0..{z4-z9}z4r--subpath (0,t) of\\(z4l{z9-z4}..z6r) 
  --z2l--z2r--subpath (t,0) of\\(z3l{z9-z3}..z5r) 
- --z3r{z9-z3}..z0 & cycle; 
+ --z3r{z9-z3}..z0 & cycle; % second arrowhead  
 filldraw z0..{z4-z9}z4r--subpath (0,t) of\\(z4l{z9-z4}..z6r) 
  --z2l---z1l..z1r---z2r--subpath (t,0) of\\(z3l{z9-z3}..z5r) 
  --z3r{z9-z3}..z0 & cycle;  % arrowhead and stem 
@@ -412,37 +419,36 @@
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_mapsfromright,arrow_head_width#,single_height);
 adjust_fit(0,0); pickup rule.nib;
-lft x1=hround(w-u); x2=hround(-arrow_overshoot); x3=x4=x1;
+rt x1=hround(w-u); x2=hround(-arrow_overshoot); x3=x4=x1;
 y1=y2=math_axis; y1-y3=y4-y1=.24asc_height+eps;
 draw z3--z4;  % stem
 draw z1--z2;  % bar stub
-labels(1,2,3,4); endchar;
-
+penlabels(1,2,3,4); endchar;
 
-cmchar "Double right mapsto ";
+cmchar "Double right mapsto";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Mapsfromright,arrow_head_width#,double_height);
 adjust_fit(0,0); pickup rule.nib;
-lft x1=hround(w-u); x6=x2=hround(-arrow_overshoot); x5=x3=x4=x1;
+rt x1=hround(w-u); x6=x2=hround(-arrow_overshoot); x5=x3=x4=x1;
 y1=y2; y5=y6; .5[y1,y5]=math_axis; y5-y1=spread; 
 y1-y3=y4-y5=.24asc_height+eps;
 draw z3--z4;  % stem
 draw z1--z2;  % bar stub
 draw z5--z6;  % bar stub
-labels(1,2,3,4,5,6); endchar;
+penlabels(1,2,3,4,5,6); endchar;
 
 cmchar "Triple right mapsto";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_MAPSfromright,arrow_head_width#,triple_height);
 adjust_fit(0,0); pickup rule.nib;
-lft x1=hround(w-u); x6=x8=x2=hround(-arrow_overshoot); x5=x7=x3=x4=x1;
+rt x1=hround(w-u); x6=x8=x2=hround(-arrow_overshoot); x5=x7=x3=x4=x1;
 y1=y2=math_axis; y5=y6; y7=y8; y5-y2=y1-y7=spread;
 y3-y5=y7-y4=.24asc_height+eps;
 draw z3--z4;  % stem
 draw z1--z2;  % bar stub
 draw z5--z6;  % bar stub
 draw z7--z8;  % bar stub
-labels(1,2,3,4,5,6,7,8); endchar;
+penlabels(1,2,3,4,5,6,7,8); endchar;
 
 % 168: Right hook up
 % 169: Right hook down
@@ -483,7 +489,7 @@
 
 % 4 special left heads
 
-cmchar "Left squiggly arrow head";
+cmchar "Squiggly left arrow head";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_squighead,arrow_head_width#,single_height);
 adjust_fit(0,0); pickup crisp.nib;
@@ -500,12 +506,10 @@
 filldraw z0..{z4-z9}z4l--subpath (0,t) of\\(z4r{z9-z4}..z6r)
  --z2l---z1l..z1r---z2r--subpath (t,0) of\\(z3r{z9-z3}..z5r)
  --z3l{z9-z3}..z0 & cycle;  % arrowhead and stem
-
 x10=w; y10=math_axis+.12asc_height+eps;
-pickup pencircle scaled rule_thickness; 
+pickup rule.nib;
 draw z1{right}..z10{right}; 
-
-penlabels(0,1,2,3,4,5,6,9); endchar;
+penlabels(0,1,2,3,4,5,6,9,10); endchar;
 
 cmchar "Single left dashed arrow head";
 compute_spread(.45x_height#,.55x_height#);
@@ -526,16 +530,16 @@
  --z3l{z9-z3}..z0 & cycle;  % arrowhead and stem
 pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-y13=y12=y11=y10=y9; x10=hround(w-.5dot_sep);
-x11-x12=x12-x13=x10-x11=dot_sep;
+y13=y12=y11=y10=y0; x10=hround(w-.5dot_sep);
+x12-x13=x11-x12=x10-x11=dot_sep;
 drawdot z10; drawdot z11; drawdot z12; drawdot z13;
-penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14); endchar;
+penlabels(0,1,2,3,4,5,6,9,10,11,12,13); endchar;
 
 cmchar "Double left dashed arrow head";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Dashhead,arrow_head_width#,double_height);
 adjust_fit(0,0); pickup rule.nib;
-lft x7=hround u-eps; x8=x7; x1=x2=w+arrow_overshoot;
+lft x7=hround u-eps; x8=x7; x1=x2=hround(w+arrow_overshoot);
 y1=y7; y2=y8; y1-y2=spread; .5[y1,y2]=math_axis;
 
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
@@ -546,7 +550,8 @@
 drawdot z20; drawdot z21; drawdot z22;
 drawdot z30; drawdot z31; drawdot z32;
 
-pickup crisp.nib; lft x0=hround u-eps; y0=good.y math_axis;
+pickup crisp.nib;
+lft x0=hround u-eps; y0=good.y math_axis;
 pos3(rule_thickness,0); pos4(rule_thickness,0);
 y3-y1=y2-y4=.24asc_height+eps; x3=x4=x0+6u+eps;
 pos5(rule_thickness,angle(z4-z0)); z5l=z0;
@@ -558,18 +563,20 @@
 t=xpart(p intersectiontimes((0,y0)--(w,y0)));
 filldraw z0..{z4-z9}z4l--subpath (0,t) of\\(z4r{z9-z4}..z6r)
  --subpath (t,0) of\\(z3r{z9-z3}..z5r)--z3l{z9-z3}..z0 & cycle;  % arrowhead
-penlabels(0,1,2,3,4,5,6,7,8,9); endchar;
+penlabels(0,1,2,3,4,5,6,7,8,9,20,21,22,30,31,32); endchar;
 
 cmchar "Triple left dashed arrow head"; 
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_DASHhead,arrow_head_width#,triple_height); 
+adjust_fit(0,0); pickup rule.nib;
+pos1(rule_thickness,90); pos2(rule_thickness,90);
+pos3(rule_thickness,0); pos4(rule_thickness,0); 
+y0=y1=y2=math_axis; x1=x2+eps;
+lft x0=hround u-eps; x0'=x0''=x0; x1'=x1''=x1;
+y1'=y1+spread; y1''=y1-spread; y0'=y1'; y0''=y1'';
+
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-adjust_fit(0,0); pickup rule.nib; penpos1(rule_thickness,90); 
-penpos2(rule_thickness,90); penpos3(1.5bar,0); penpos4(1.5bar,0); 
-y0=y1=y2=math_axis;
-lft x0=hround u; x0'=x0''=x0; 
-y1'=y1+spread;y1''=y1-spread; y0'=y1'; y0''=y1''; 
-x53=x53'=x53''=hround (w-.5dot_sep);
+x53=x53'=x53''=hround(w-.5dot_sep);
 x51-x50=x52-x51=x53-x52=dot_sep;
 x50=x50'=x50''; x51=x51'=x51''; x52=x52'=x52''; 
 y50=y51=y52=y53=math_axis;
@@ -578,15 +585,16 @@
 drawdot z50; drawdot z51; drawdot z52; drawdot z53;
 drawdot z50'; drawdot z51'; drawdot z52'; drawdot z53';
 drawdot z50''; drawdot z51''; drawdot z52''; drawdot z53'';
-x1l:=x1r:=x1:=x2+eps;
+
 pickup crisp.nib;  
 y3-y0'=y0''-y4=.24asc_height+eps; x3=x4=x0+6u+eps; 
-pos5(bar,angle(z4-z0)); z5l=z0; pos6(bar,angle(z3-z0)); 
-z6l=z0; z9=.381966[.5[z3,z4],z0]; erase filldraw 
-z0..{z3-z9}z3--(0,y3) 
- --(0,y4)--z4{z9-z4}..z0& cycle; numeric t; path p; 
-p=z4r{z9-z4}..z6r; t=xpart(p 
-intersectiontimes((0,y2l)--(w,y2l))); x2=xpart point t of p; 
+pos5(rule_thickness,angle(z4-z0)); z5l=z0;
+pos6(rule_thickness,angle(z3-z0)); z6l=z0;
+z9=.381966[.5[z3,z4],z0];
+erase filldraw z0..{z3-z9}z3--(0,y3) 
+ --(0,y4)--z4{z9-z4}..z0& cycle;
+numeric t; path p; p=z4r{z9-z4}..z6r;
+t=xpart(p intersectiontimes((0,y2l)--(w,y2l))); x2=xpart point t of p; 
 filldraw z0..{z4-z9}z4l--subpath (0,t) of\\(z4r{z9-z4}..z6r) 
  --z2l---z1l..z1r---z2r--subpath (t,0) of\\(z3r{z9-z3}..z5r) 
  --z3l{z9-z3}..z0 & cycle;  % arrowhead and stem 
@@ -611,12 +619,10 @@
 filldraw z0..{z4-z9}z4r--subpath (0,t) of\\(z4l{z9-z4}..z6r)
  --z2l---z1l..z1r---z2r--subpath (t,0) of\\(z3l{z9-z3}..z5r)
  --z3r{z9-z3}..z0 & cycle;  % arrowhead and stem
-
 x10=0; y10=math_axis+.12asc_height+eps;
-pickup pencircle scaled rule_thickness; 
+pickup rule.nib;
 draw z10{right}..z1{right}; 
-
-penlabels(0,1,2,3,4,5,6,9); endchar;
+penlabels(0,1,2,3,4,5,6,9,10); endchar;
 
 cmchar "Single right dashed arrow head";
 compute_spread(.45x_height#,.55x_height#);
@@ -637,16 +643,16 @@
  --z3r{z9-z3}..z0 & cycle;  % arrowhead and stem
 pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-y13=y12=y11=y10=y9; x10=hround(.5dot_sep);
-x12-x11=x13-x12=x11-x10=dot_sep;
+y13=y12=y11=y10=y0; x10=hround(.5dot_sep);
+x13-x12=x12-x11=x11-x10=dot_sep;
 drawdot z10; drawdot z11; drawdot z12; drawdot z13;
-penlabels(0,1,2,3,4,5,6,9,10,11,12); endchar;
+penlabels(0,1,2,3,4,5,6,9,10,11,12,13); endchar;
 
 cmchar "Double right dashed arrow head";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Dashright,arrow_head_width#,double_height);
 adjust_fit(0,0); pickup rule.nib;
-lft x1=hround 0 - arrow_overshoot; x2=x1; x7=x8=w-hround u-eps;
+x1=x2=hround(0-arrow_overshoot); rt x7=w-hround u-eps; x8=x7;
 y1=y7; y2=y8; y1-y2=spread; .5[y1,y2]=math_axis;
 
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
@@ -657,7 +663,8 @@
 drawdot z20; drawdot z21; drawdot z22;
 drawdot z30; drawdot z31; drawdot z32;
 
-pickup crisp.nib; rt x0=hround(w-u)+eps; y0=good.y math_axis;
+pickup crisp.nib;
+rt x0=hround(w-u)+eps; y0=good.y math_axis;
 pos3(rule_thickness,0); pos4(rule_thickness,0);
 y3-y1=y2-y4=.24asc_height+eps; x3=x4=x0-6u-eps;
 pos5(rule_thickness,angle(z4-z0)); z5l=z0;
@@ -669,17 +676,19 @@
 t=xpart(p intersectiontimes((0,y0)--(w,y0)));
 filldraw z0..{z4-z9}z4r--subpath (0,t) of\\(z4l{z9-z4}..z6r)
  --subpath (t,0) of\\(z3l{z9-z3}..z5r)--z3r{z9-z3}..z0 & cycle;  % arrowhead
-penlabels(0,1,2,3,4,5,6,7,8,9); endchar;
+penlabels(0,1,2,3,4,5,6,7,8,9,20,21,22,30,31,32); endchar;
 
 cmchar "Triple right dashed arrow head"; 
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_DASHright,arrow_head_width#,triple_height); 
+adjust_fit(0,0); pickup rule.nib;
+pos1(rule_thickness,90); pos2(rule_thickness,90);
+pos3(rule_thickness,0); pos4(rule_thickness,0); 
+y0=y1=y2=math_axis; x1=x2-eps;
+rt x0=hround(w-u)+eps; x0'=x0''=x0; x1'=x1''=x1;
+y1'=y1+spread; y1''=y1-spread; y0'=y1'; y0''=y1'';
+
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-adjust_fit(0,0); pickup rule.nib; penpos1(rule_thickness,90); 
-penpos2(rule_thickness,90); penpos3(1.5bar,0); penpos4(1.5bar,0); 
-y0=y1=y2=math_axis; x1=hround(0-arrow_overshoot);  
-rt x0=hround (w-u); x0'=x0''=x0; x1'=x1''=x1; 
-y1'=y1+spread;y1''=y1-spread; y0'=y1'; y0''=y1''; 
 x50=x50'=x50''=hround .5dot_sep;
 x51-x50=x52-x51=x53-x52=dot_sep;
 x51=x51'=x51'';x 52=x52'=x52''; x53=x53'=x53'';
@@ -689,15 +698,16 @@
 drawdot z50; drawdot z51; drawdot z52; drawdot z53;
 drawdot z50'; drawdot z51'; drawdot z52'; drawdot z53';
 drawdot z50''; drawdot z51''; drawdot z52''; drawdot z53'';
-x1l:=x1r:=x2-eps;
+
 pickup crisp.nib;  
 y3-y0'=y0''-y4=.24asc_height+eps; x3=x4=x0-6u-eps; 
-penpos5(bar,angle(z0-z4)); z5r=z0; penpos6(bar,angle(z0-z3)); 
-z6r=z0; z9=.381966[.5[z3,z4],z0]; erase filldraw 
-z0..{z3-z9}z3--(w,y3)--(w,y4)--z4{z9-z4}..z0& cycle; 
-numeric t; path p; 
-p=z4l{z9-z4}..z6l; t=xpart(p intersectiontimes((0,y2l)--(w,y2l))); 
-x2=xpart point t of p; 
+penpos5(bar,angle(z0-z4)); z5r=z0;
+penpos6(bar,angle(z0-z3)); z6r=z0;
+z9=.381966[.5[z3,z4],z0];
+erase filldraw z0..{z3-z9}z3--(w,y3)
+ --(w,y4)--z4{z9-z4}..z0& cycle; 
+numeric t; path p; p=z4l{z9-z4}..z6l;
+t=xpart(p intersectiontimes((0,y2l)--(w,y2l))); x2=xpart point t of p; 
 filldraw z0..{z4-z9}z4r--subpath (0,t) of\\(z4l{z9-z4}..z6l) 
  --z2l---z1l..z1r---z2r--subpath (t,0) of\\(z3l{z9-z3}..z5l) 
  --z3r{z9-z3}..z0 & cycle;  % arrowhead and stem 
@@ -709,11 +719,10 @@
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_Headnone,arrow_head_width#,double_height); 
 adjust_fit(0,0); pickup rule.nib;
+lft x1=hround u; x1=x2; x7=x8=hround(w+arrow_overshoot); 
 y1=y7; y2=y8; y1-y2=spread; .5[y1,y2]=math_axis;
-x7=hround(w+arrow_overshoot); lft x1=hround u;
-x7=x8; x1=x2;	
 draw z1--z7; draw z2--z8;  % bars
-endchar;
+penlabels(1,2,7,8); endchar;
 
 cmchar "Wide double left arrow end"; 
 compute_spread(.45x_height#,.55x_height#); 
@@ -722,9 +731,9 @@
 y1=y2=math_axis+.24asc_height+eps;
 y3=y4=math_axis-.24asc_height-eps;
 x2=hround(w+arrow_overshoot); lft x1=hround u;
-x2=x4; x1=x3;	
+x1=x3; x2=x4;	
 draw z1--z2; draw z3--z4;  % bars
-endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Triple left arrow end"; 
 compute_spread(.45x_height#,.55x_height#); 
@@ -734,7 +743,7 @@
 x7=hround(w+arrow_overshoot); lft x1=hround u;
 x7=x8=x9; x1=x2=x3;	
 draw z1--z7; draw z2--z8; draw z3--z9; % bars
-endchar;
+penlabels(1,2,3,7,8,9); endchar;
 
 cmchar "Left squiggly arrow end";
 compute_spread(.45x_height#,.55x_height#);
@@ -751,52 +760,48 @@
  draw z1{left}..{left}z2;
  acc_w:=acc_w+squig_u;
 endfor
-endchar;
+penlabels(1,2,3); endchar;
 
 cmchar "Single left dashed arrow end";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_dashnone,arrow_head_width#,single_height);
 adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-y15=y14=y13=y12=y11=y10=math_axis; x10=hround(w-.5dot_sep);
-x14-x15=x13-x14=x11-x12=x12-x13=x10-x11=dot_sep;
-drawdot z10; drawdot z11; drawdot z12; drawdot z13; drawdot z14; 
-penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14); endchar;
+x10=hround(w-.5dot_sep); y10=math_axis; drawdot z10;
+for j=11 thru 14:
+  x[j-1]-x[j]=dot_sep; y[j]=y[j-1]; drawdot z[j];
+endfor
+penlabels(range 10 thru 14); endchar;
 
 cmchar "Double left dashed arrow end";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Dashnone,arrow_head_width#,double_height);
 adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-y15=y14=y13=y12=y11=y10; y25=y24=y23=y22=y21=y20; 
-y15-y25=spread; .5[y15,y25]=math_axis;
-x15=x25; x14=x24; x13=x23; x12=x22; x11=x21; x10=x20;
-x10=hround(w-.5dot_sep); x14-x15=x13-x14=x11-x12=x12-x13=x10-x11=dot_sep;
-drawdot z10; drawdot z11; drawdot z12; drawdot z13; drawdot z14; 
-drawdot z20; drawdot z21; drawdot z22; drawdot z23; drawdot z24; 
-penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14,20,21,22,23,24); endchar;
+x10=x20=hround(w-.5dot_sep);
+y10-y20=spread; .5[y10,y20]=math_axis;
+drawdot z10; drawdot z20;
+for j=11 thru 14:
+  x[j-1]-x[j]=dot_sep; y[j]=y[j-1]; drawdot z[j];
+  x[j]=x[j+10]; y[j+10]=y[j+10-1]; drawdot z[j+10];
+endfor
+penlabels(range 10 thru 14,range 20 thru 24); endchar;
 
 cmchar "Triple left dashed arrow end"; 
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_DASHnone,arrow_head_width#,triple_height); 
 adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-y15=y14=y13=y12=y11=y10; 
-y25=y24=y23=y22=y21=y20; 
-y35=y34=y33=y32=y31=y30; 
-y15-y25=y25-y35=spread; .5[y15,y35]=math_axis;
-x15=x25=x35; 
-x14=x24=x34; 
-x13=x23=x33; 
-x12=x22=x32; 
-x11=x21=x31; 
-x10=x20=x30;
-x10=hround(w-.5dot_sep); 
-x14-x15=x13-x14=x11-x12=x12-x13=x10-x11=dot_sep;
-drawdot z10; drawdot z11; drawdot z12; drawdot z13; drawdot z14; 
-drawdot z20; drawdot z21; drawdot z22; drawdot z23; drawdot z24; 
-drawdot z30; drawdot z31; drawdot z32; drawdot z33; drawdot z34; 
-endchar;
+x10=x20=x30=hround(w-.5dot_sep);
+y10-y20=y20-y30=spread; .5[y10,y30]=math_axis;
+drawdot z10; drawdot z20; drawdot z30;
+for j=11 thru 14:
+  x[j-1]-x[j]=dot_sep; y[j]=y[j-1]; drawdot z[j];
+  x[j]=x[j+10]=x[j+20];
+  y[j+10]=y[j+10-1]; drawdot z[j+10];
+  y[j+20]=y[j+20-1]; drawdot z[j+20];
+endfor
+penlabels(range 10 thru 14,range 20 thru 24,range 30 thru 34); endchar;
 
 % 8 simple right arrow ends
 
@@ -804,18 +809,19 @@
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_headrightnone,arrow_head_width#,single_height);
 adjust_fit(0,0); pickup rule.nib;
-y0=y1=math_axis; x1=hround (0-arrow_overshoot); rt x0=hround(w-u);
-draw z0--z1; endchar;
+rt x1=hround(w-u); x2=hround(0-arrow_overshoot);
+y1=y2=math_axis;
+draw z1--z2;
+penlabels(1,2); endchar;
 
 cmchar "Double right arrow end";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Headrightnone,arrow_head_width#,double_height);
 adjust_fit(0,0); pickup rule.nib;
+rt x7=hround(w-u); x7=x8; x1=x2=hround(0-arrow_overshoot); 
 y1=y7; y2=y8; y1-y2=spread; .5[y1,y2]=math_axis;
-lft x1=hround(0-arrow_overshoot); rt x7=hround(w-u); 
-x7=x8; x1=x2;	
 draw z1--z7; draw z2--z8;  % bars
-endchar;
+penlabels(1,2,7,8); endchar;
 
 cmchar "Wide double right arrow end";
 compute_spread(.45x_height#,.55x_height#);
@@ -823,20 +829,20 @@
 adjust_fit(0,0); pickup rule.nib;
 y1=y2=math_axis+.24asc_height+eps;
 y3=y4=math_axis-.24asc_height-eps;
-lft x1=hround(0-arrow_overshoot); rt x2=hround(w-u); 
-x3=x1; x4=x2;	
+x1=hround(0-arrow_overshoot); rt x2=hround(w-u); 
+x1=x3; x2=x4; 
 draw z1--z2; draw z3--z4;  % bars
-endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Triple right arrow end";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_HEADrightnone,arrow_head_width#,triple_height);
 adjust_fit(0,0); pickup rule.nib;
 y1=y7; y2=y8; y3=y9; y1-y2=y2-y3=spread; y2=math_axis;
-lft x1=hround(0-arrow_overshoot); rt x7=hround(w-u); 
+x1=hround(0-arrow_overshoot); rt x7=hround(w-u); 
 x7=x8=x9; x1=x2=x3;	
 draw z1--z7; draw z2--z8; draw z3--z9; % bars
-endchar;
+penlabels(1,2,3,7,8,9); endchar;
 
 cmchar "Right squiggly arrow end";
 compute_spread(.45x_height#,.55x_height#);
@@ -853,53 +859,48 @@
  draw z1{right}..{right}z2;
  acc_w:=acc_w+squig_u;
 endfor
-endchar;
+penlabels(1,2,3); endchar;
 
 cmchar "Single right dashed arrow end";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_dashrightnone,arrow_head_width#,single_height);
 adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-y15=y14=y13=y12=y11=y10=math_axis; x10=hround(.5dot_sep);
-x15-x14=x14-x13=x12-x11=x13-x12=x11-x10=dot_sep;
-drawdot z10; drawdot z11; drawdot z12; drawdot z13; drawdot z14; 
-penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14); endchar;
+x10=hround(.5dot_sep); y10=math_axis; drawdot z10;
+for j=11 thru 14:
+  x[j]-x[j-1]=dot_sep; y[j]=y[j-1]; drawdot z[j];
+endfor
+penlabels(range 10 thru 14); endchar;
 
 cmchar "Double right dashed arrow end";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Dashrightnone,arrow_head_width#,double_height);
 adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-y15=y14=y13=y12=y11=y10;
-y25=y24=y23=y22=y21=y20;
-y15-y25=spread; .5[y15,y25]=math_axis; 
-x15=x25; x14=x24; x13=x23; x12=x22; x11=x21; x10=x20;
-x10=hround(.5dot_sep); x15-x14=x14-x13=x12-x11=x13-x12=x11-x10=dot_sep;
-drawdot z10; drawdot z11; drawdot z12; drawdot z13; drawdot z14; 
-drawdot z20; drawdot z21; drawdot z22; drawdot z23; drawdot z24; 
-penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14,20,21,22,23,24); endchar;
+x10=x20=hround(.5dot_sep);
+y10-y20=spread; .5[y10,y20]=math_axis;
+drawdot z10; drawdot z20;
+for j=11 thru 14:
+  x[j]-x[j-1]=dot_sep; y[j]=y[j-1]; drawdot z[j];
+  x[j]=x[j+10]; y[j+10]=y[j+10-1]; drawdot z[j+10];
+endfor
+penlabels(range 10 thru 14,range 20 thru 24); endchar;
 
 cmchar "Triple right dashed arrow end"; 
 compute_spread(.45x_height#,.55x_height#); 
 beginchar(slot_DASHrightnone,arrow_head_width#,triple_height); 
 adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8*arrow_ratio;
-y15=y14=y13=y12=y11=y10; 
-y25=y24=y23=y22=y21=y20; 
-y35=y34=y33=y32=y31=y30; 
-y15-y25=y25-y35=spread; .5[y15,y35]=math_axis;
-x15=x25=x35; 
-x14=x24=x34; 
-x13=x23=x33; 
-x12=x22=x32; 
-x11=x21=x31; 
-x10=x20=x30;
-x10=hround .5dot_sep; 
-x14-x15=x13-x14=x11-x12=x12-x13=x10-x11=-dot_sep;
-drawdot z10; drawdot z11; drawdot z12; drawdot z13; drawdot z14; 
-drawdot z20; drawdot z21; drawdot z22; drawdot z23; drawdot z24; 
-drawdot z30; drawdot z31; drawdot z32; drawdot z33; drawdot z34; 
-endchar;
+x10=x20=x30=hround(.5dot_sep);
+y10-y20=y20-y30=spread; .5[y10,y30]=math_axis;
+drawdot z10; drawdot z20; drawdot z30;
+for j=11 thru 14:
+  x[j]-x[j-1]=dot_sep; y[j]=y[j-1]; drawdot z[j];
+  x[j]=x[j+10]=x[j+20];
+  y[j+10]=y[j+10-1]; drawdot z[j+10];
+  y[j+20]=y[j+20-1]; drawdot z[j+20];
+endfor
+penlabels(range 10 thru 14,range  20 thru 24,range  30 thru 34); endchar;
 
 % 5 arrow extension pieces
 
@@ -914,7 +915,7 @@
 y1=y2; y3=y4; y1-y3=spread; .5[y1,y3]=math_axis;
 draw z1--z2;  % upper bar
 draw z3--z4;  % lower bar
-labels(1,2,3,4); endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Wide double arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -928,7 +929,7 @@
 y3=y4=math_axis-.24asc_height-eps;
 draw z1--z2;  % upper bar
 draw z3--z4;  % lower bar
-labels(1,2,3,4); endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Triple arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -940,7 +941,7 @@
 draw z1--z2;  % upper bar
 draw z3--z4;  % lower bar
 draw z5--z6;  % middle bar
-labels(1,2,3,4,5,6); endchar;
+penlabels(1,2,3,4,5,6); endchar;
 
 cmchar "Squiggly left gaped arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -953,7 +954,7 @@
 pickup pencircle scaled rule_thickness; 
 draw z1{right}..z2{right}..z3{right}..z4{right}..{right}z5; 
 unfill (5/6w,-d)--(7/6w,-d)--(7/6w,h)--(5/6w,h)--cycle;
-endchar;
+penlabels(1,2,3,4,5); endchar;
 
 cmchar "Squiggly right gaped arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -966,7 +967,7 @@
 pickup pencircle scaled rule_thickness; 
 draw z1{right}..z2{right}..z3{right}..z4{right}..{right}z5; 
 unfill (1/6w,-d)--(-1/6w,-d)--(-1/6w,h)--(1/6w,h)--cycle;
-endchar;
+penlabels(1,2,3,4,5); endchar;
 
 cmchar "Double dashed arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -974,17 +975,14 @@
 italcorr h#*slant-.5u#;
 adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8;
-y0=y1=y2=y3=y4=y5=y6=y7=y8; 
-y10=y11=y12=y13=y14=y15=y16=y17=y18;
-y0-y10=spread; .5[y0,y10]=math_axis;
-x0=0; x10=x0; x11=x1; x12=x2; x13=x3; x14=x4; x15=x5; x16=x6;
-x17=x7; x18=x8;
-2(x1-x0)=x2-x1=x3-x2=x4-x3=x5-x4=x6-x5=x7-x6=x8-x7=dot_sep;
-drawdot z1; drawdot z2; drawdot z3; drawdot z4;
-drawdot z5; drawdot z6; drawdot z7; drawdot z8;
-drawdot z11; drawdot z12; drawdot z13; drawdot z14;
-drawdot z15; drawdot z16; drawdot z17; drawdot z18;
-labels(1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18); endchar;
+x0=x10=0; y0-y10=spread; .5[y0,y10]=math_axis;
+2(x1-x0)=dot_sep; x1=x11; y1=y0; y11=y10;
+drawdot z1; drawdot z11;
+for j=2 thru 8:
+  x[j]-x[j-1]=dot_sep; y[j]=y[j-1]; drawdot z[j];
+  x[j]=x[j+10]; y[j+10]=y[j+10-1]; drawdot z[j+10];
+endfor
+penlabels(range 1 thru 8,range 11 thru 18); endchar;
 
 cmchar "Triple dash arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -992,20 +990,16 @@
 italcorr h#*slant-.5u#;
 adjust_fit(0,0); pickup rule.nib;
 numeric dot_sep; dot_sep:=w/8;
-y0=y1=y2=y3=y4=y5=y6=y7=y8; 
-y10=y11=y12=y13=y14=y15=y16=y17=y18;
-y20=y21=y22=y23=y24=y25=y26=y27=y28;
-y10-y20=y0-y10=spread; .5[y0,y20]=math_axis;
-x0=0; x10=x0; x21=x11=x1; x22=x12=x2; x23=x13=x3; 
-x24=x14=x4; x25=x15=x5; x26=x16=x6; x27=x17=x7; x28=x18=x8;
-2(x1-x0)=x2-x1=x3-x2=x4-x3=x5-x4=x6-x5=x7-x6=x8-x7=dot_sep;
-drawdot z1; drawdot z2; drawdot z3; drawdot z4;
-drawdot z5; drawdot z6; drawdot z7; drawdot z8;
-drawdot z11; drawdot z12; drawdot z13; drawdot z14;
-drawdot z15; drawdot z16; drawdot z17; drawdot z18;
-drawdot z21; drawdot z22; drawdot z23; drawdot z24;
-drawdot z25; drawdot z26; drawdot z27; drawdot z28;
-labels(1,2,3,4,5,6); endchar;
+x0=x10=x20=0; y0-y10=y10-y20=spread; .5[y0,y20]=math_axis;
+2(x1-x0)=dot_sep; x1=x11=x21; y1=y0; y11=y10; y21=y20;
+drawdot z1; drawdot z11; drawdot z21;
+for j=2 thru 8:
+  x[j]-x[j-1]=dot_sep; y[j]=y[j-1]; drawdot z[j];
+  x[j]=x[j+10]=x[j+20];
+  y[j+10]=y[j+10-1]; drawdot z[j+10];
+  y[j+20]=y[j+20-1]; drawdot z[j+20];
+endfor
+penlabels(range 1 thru 8,range 11 thru 18,range 21 thru 28); endchar;
 
 % 7 arrow negation pieces
 
@@ -1091,7 +1085,7 @@
 y5-y1=.24asc_height+eps;
 char_center(100); top y101=top y5; x101=x100+2u;
 char_negate(100,101,102);
-labels(1,2,3,4); endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Wider double negated arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -1105,7 +1099,7 @@
 y5-y1=.24asc_height+eps;
 char_center(100); top y101=top y5; x101=x100+2u;
 char_negate(100,101,102);
-labels(1,2,3,4); endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Triple negated arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -1119,7 +1113,7 @@
 y7-y1=.24asc_height+eps;
 char_center(100); top y101=top y7; x101=x100+2u;
 char_negate(100,101,102);
-labels(1,2,3,4,5,6); endchar;
+penlabels(1,2,3,4,5,6); endchar;
 
 cmchar "Squiggly negated arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -1131,10 +1125,10 @@
 x1=0; x5=w;
 pickup pencircle scaled rule_thickness; 
 draw z1{right}..{right}z2..{right}z3..{right}z4..{right}z5; 
-y3:=math_axis+.24asc_height+eps;
-char_center(100); top y101=top y3; x101=x100+2u;
+y6:=math_axis+.24asc_height+eps;
+char_center(100); top y101=top y6; x101=x100+2u;
 char_negate(100,101,102);
-endchar;
+penlabels(1,2,3,4,5); endchar;
 
 cmchar "Single dashed negated arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -1149,7 +1143,7 @@
 y10-y1=.24asc_height+eps;
 char_center(100); top y101=top y10; x101=x100+2u;
 char_negate(100,101,102);
-labels(0,1,2,3,4,5,6,7,8,100); endchar;
+penlabels(range 1 thru 8); endchar;
 
 cmchar "Double dashed negated arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -1170,7 +1164,7 @@
 y9-y1=.24asc_height+eps;
 char_center(100); top y101=top y9; x101=x100+2u;
 char_negate(100,101,102);
-labels(1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18); endchar;
+penlabels(range 1 thru 8,range 11 thru 18); endchar;
 
 cmchar "Triple dashed negated arrow extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -1194,50 +1188,63 @@
 y77-y1=.24asc_height+eps;
 char_center(100); top y101=top y77; x101=x100+2u;
 char_negate(100,101,102);
-labels(1,2,3,4,5,6); endchar;
+penlabels(range 1 thru 8,range 11 thru 18,range 21 thru 28); endchar;
+
+% 8 arrow gaps
 
-% 7 arrow gaps
+cmchar "Single gap";
+compute_spread(.45x_height#,.55x_height#);
+beginchar(slot_GAP,arrow_ext_width#/3,single_height);
+adjust_fit(0,0);
+endchar;
 
 cmchar "Double gap";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_doublegap,arrow_ext_width#/3,double_height); 
+adjust_fit(0,0);
 endchar;
 
 cmchar "Wide double gap";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_widedoublegap,arrow_ext_width#/3,wide_double_height); 
+adjust_fit(0,0);
 endchar;
 
 cmchar "Triple gap";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_triplegap,arrow_ext_width#/3,triple_height); 
+adjust_fit(0,0);
 endchar;
 
 cmchar "Squiggly gap";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_squiggap,arrow_ext_width#/3,single_height); 
+adjust_fit(0,0);
 endchar;
 
 cmchar "Single dashed gap";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_dashgap,arrow_ext_width#/3,single_height); 
+adjust_fit(0,0);
 endchar;
 
 cmchar "Double dashed gap";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_Dashgap,arrow_ext_width#/3,double_height); 
+adjust_fit(0,0);
 endchar;
 
 cmchar "Triple dashed gap";
 compute_spread(.45x_height#,.55x_height#);
 beginchar(slot_DASHgap,arrow_ext_width#/3,triple_height); 
+adjust_fit(0,0);
 endchar;
 
 % 7 gap extensions
 
 cmchar "Double gap extension";
 compute_spread(.45x_height#,.55x_height#);
-beginchar(slot_doublegapext,4/3arrow_ext_width#,double_height); 
+beginchar(slot_doublegapext,3/2arrow_ext_width#,double_height); 
 italcorr h#*slant-.5u#;
 adjust_fit(0,0); pickup rule.nib;
 lft x1=hround(0-arrow_overshoot);   % hround u-eps; 
@@ -1248,11 +1255,11 @@
 y1=y2=y5=y7; y3=y4=y6=y8; y1-y3=spread; .5[y1,y3]=math_axis;
 draw z1--z5; draw z7--z2;  % upper bar
 draw z3--z6; draw z8--z4;  % lower bar
-labels(1,2,3,4); endchar;
+penlabels(1,2,3,4,5,6,7,8); endchar;
 
 cmchar "Wide double gap extension";
 compute_spread(.45x_height#,.55x_height#);
-beginchar(slot_widedoublegapext,4/3arrow_ext_width#,wide_double_height); 
+beginchar(slot_widedoublegapext,3/2arrow_ext_width#,wide_double_height); 
 italcorr h#*slant-.5u#;
 adjust_fit(0,0); pickup rule.nib;
 lft x1=hround (0 - arrow_overshoot);
@@ -1264,11 +1271,11 @@
 y6=y8=y3=y4=math_axis-.24asc_height-eps;
 draw z1--z5; draw z7--z2;  % upper bar
 draw z3--z6; draw z8--z4;  % lower bar
-labels(1,2,3,4); endchar;
+penlabels(1,2,3,4,5,6,7,8); endchar;
 
 cmchar "Triple gap extension";
 compute_spread(.45x_height#,.55x_height#);
-beginchar(slot_triplegapext,4/3arrow_ext_width#,triple_height); 
+beginchar(slot_triplegapext,3/2arrow_ext_width#,triple_height); 
 italcorr h#*slant-.5u#;
 adjust_fit(0,0); pickup rule.nib;
 lft x1=hround 0 - arrow_overshoot; x5=x3=x1; x6=x2=x4=w-x1; 
@@ -1278,7 +1285,7 @@
 draw z1--z7; draw z10--z2;  % upper bar
 draw z3--z8; draw z11--z4;  % lower bar
 draw z5--z9; draw z12--z6;  % middle bar
-labels(1,2,3,4,5,6); endchar;
+penlabels(1,2,3,4,5,6,7,8,9,10,11,12); endchar;
 
 cmchar "Squiggly gap extension";
 compute_spread(.45x_height#,.55x_height#);
@@ -1290,60 +1297,65 @@
 pickup pencircle scaled rule_thickness; 
 draw z1{right}..z2{right}..z3{right}..z4{right}..z5{right}; 
 unfill (1/3w,-d)--(2/3w,-d)--(2/3w,h)--(1/3w,h)--cycle;
-endchar;
+penlabels(1,2,3,4,5); endchar;
 
 cmchar "Single dash gap extension";
 compute_spread(.45x_height#,.55x_height#);
-beginchar(slot_dashgapext,4/3arrow_ext_width#,single_height); 
-pickup rule.nib;
-numeric dot_sep; dot_sep:=3/32w;
-y0=y1=y2=y3=y4=y5=y6=y7=y8=math_axis;
-x0=0;
-2(x1-x0)=x2-x1=x3-x2=dot_sep;
-w-x6=x1; w-x7=x2; w-x8=x3;
-drawdot z1; drawdot z2; drawdot z3;
-drawdot z6; drawdot z7; drawdot z8;
-labels(0,1,2,3,4,5,6,7,8); endchar;
+beginchar(slot_dashgapext,3/2arrow_ext_width#,single_height); 
+adjust_fit(0,0); pickup rule.nib;
+numeric dot_sep; dot_sep:=w/12;
+x0=0; y0=math_axis;
+2(x1-x0)=dot_sep; x1'=w-x1; y1'=y1=y0;
+drawdot z1; drawdot z1';
+for j=2 thru 4:
+  w-x[j]'=x[j]=x[j-1]+dot_sep; y[j]'=y[j]=y0;
+  drawdot z[j]; drawdot z[j]';
+endfor
+penlabels(1,2,3,4,1',2',3',4'); endchar;
 
 cmchar "Double dash gap extension";
 compute_spread(.45x_height#,.55x_height#);
-beginchar(slot_Dashgapext,4/3arrow_ext_width#,double_height); 
+beginchar(slot_Dashgapext,3/2arrow_ext_width#,double_height); 
 italcorr h#*slant-.5u#;
 adjust_fit(0,0); pickup rule.nib;
-numeric dot_sep; dot_sep:=w/8;
-y0=y1=y2=y3=y4=y5=y6=y7=y8; 
-y10=y11=y12=y13=y14=y15=y16=y17=y18;
-y0-y10=spread; .5[y0,y10]=math_axis;
-x11=x1; x12=x2; x13=x3; x16=x6; x17=x7; x18=x8;
-x0=0; 2(x1-x0)=x2-x1=x3-x2=dot_sep;
-w-x6=x1; w-x7=x2; w-x8=x3;
-drawdot z1; drawdot z2; drawdot z3; 
-drawdot z6; drawdot z7; drawdot z8;
-drawdot z11; drawdot z12; drawdot z13; 
-drawdot z16; drawdot z17; drawdot z18;
-labels(1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18); endchar;
+numeric dot_sep; dot_sep:=w/12;
+x0=0; y0-y10=spread; .5[y0,y10]=math_axis;
+2(x1-x0)=dot_sep; x1=x11; x1'=x11'=w-x1;
+y1'=y1=y0; y11'=y11=y10;
+drawdot z1; drawdot z1';
+drawdot z11; drawdot z11';
+for j=2 thru 4:
+  w-x[j]'=x[j]=x[j-1]+dot_sep; y[j]'=y[j]=y0;
+  x[j]=x[j+10]; x[j]'=x[j+10]';
+  y[j+10]'=y[j+10]=y[j+10-1];
+  drawdot z[j]; drawdot z[j]';
+  drawdot z[j+10]; drawdot z[j+10]';
+endfor
+penlabels(1,2,3,4,11,12,13,14,1',2',3',4',11',12',13',14'); endchar;
 
 cmchar "Triple dash gap extension";
 compute_spread(.45x_height#,.55x_height#);
-beginchar(slot_DASHgapext,4/3arrow_ext_width#,triple_height); 
+beginchar(slot_DASHgapext,3/2arrow_ext_width#,triple_height); 
 italcorr h#*slant-.5u#;
 adjust_fit(0,0); pickup rule.nib;
-numeric dot_sep; dot_sep:=w/8;
-y0=y1=y2=y3=y4=y5=y6=y7=y8; 
-y10=y11=y12=y13=y14=y15=y16=y17=y18;
-y20=y21=y22=y23=y24=y25=y26=y27=y28;
-y10-y20=y0-y10=spread; .5[y0,y20]=math_axis;
-x21=x11=x1; x22=x12=x2; x23=x13=x3; 
-x26=x16=x6; x27=x17=x7; x28=x18=x8;
-x0=0; 2(x1-x0)=x2-x1=x3-x2=dot_sep;
-w-x6=x1; w-x7=x2; w-x8=x3;
-drawdot z1; drawdot z2; drawdot z3; 
-drawdot z6; drawdot z7; drawdot z8;
-drawdot z11; drawdot z12; drawdot z13; 
-drawdot z16; drawdot z17; drawdot z18;
-drawdot z21; drawdot z22; drawdot z23; 
-drawdot z26; drawdot z27; drawdot z28;
-labels(1,2,3,4,5,6); endchar;
+numeric dot_sep; dot_sep:=w/12;
+x0=0; y0-y10=y10-y20=spread; .5[y0,y20]=math_axis;
+2(x1-x0)=dot_sep; x1=x11=x21; x1'=x11'=x21'=w-x1;
+y1'=y1=y0; y11'=y11=y10; y21'=y21=y20;
+drawdot z1; drawdot z1';
+drawdot z11; drawdot z11';
+drawdot z21; drawdot z21';
+for j=2 thru 4:
+  w-x[j]'=x[j]=x[j-1]+dot_sep; y[j]'=y[j]=y0;
+  x[j]=x[j+10]=x[j+20]; x[j]'=x[j+10]'=x[j+20]';
+  y[j+10]'=y[j+10]=y[j+10-1];
+  y[j+20]'=y[j+20]=y[j+20-1];
+  drawdot z[j]; drawdot z[j]';
+  drawdot z[j+10]; drawdot z[j+10]';
+  drawdot z[j+20]; drawdot z[j+20]';
+endfor
+penlabels(1,2,3,4,11,12,13,14,21,22,23,24,
+  1',2',3',4',11',12',13',14',21',22',23',24'); endchar;
 
 cmchar "Left harpoon up"; 
 compute_spread(.45x_height#,.55x_height#); 
@@ -1489,7 +1501,7 @@
  --z3l{z9-z3}..z0 & cycle;  % arrowhead and stem 
 path p;
 p:=ldarr shifted (0,y2-y4+eps); filldraw p; % top arrow 
-p:= ldarr shifted (0,y2-y3-eps); filldraw p; % bottom arrow 
+p:=ldarr shifted (0,y2-y3-eps); filldraw p; % bottom arrow 
 endchar; 
 
 cmchar "Left arrows up"; 
@@ -1503,7 +1515,7 @@
 y5:=y6:=math_axis-.24asc_height-eps;
 x5=hround(w+arrow_overshoot); lft x6=hround u; 
 draw z5---z6;
-endchar;
+endchar; 
 
 cmchar "Left arrows down"; 
 compute_spread(.45x_height#,.55x_height#); 
@@ -1516,7 +1528,7 @@
 y5:=y6:=math_axis+.24asc_height+eps;
 x5=hround(w+arrow_overshoot); lft x6=hround u; 
 draw z5---z6;
-endchar;
+endchar; 
 
 cmchar "Right arrows"; 
 compute_spread(.45x_height#,.55x_height#); 
@@ -1581,7 +1593,7 @@
 y11=y12=math_axis;
 pickup rule.nib;
 draw z11---z12;
-penlabels(0,1,2,3,4,5,6,9); endchar; 
+endchar; 
  
 cmchar "Left feathers";
 beginchar(slot_feathers,arrow_head_width#,wide_double_height); 
@@ -1592,7 +1604,7 @@
 y11=y12=math_axis;
 pickup rule.nib;
 draw z11---z12;
-endchar;
+endchar; 
 
 cmchar "Right feather"; 
 beginchar(slot_featherright,arrow_head_width#,wide_double_height); 
@@ -1603,7 +1615,7 @@
 y11=y12=math_axis;
 pickup rule.nib;
 draw z11---z12;
-penlabels(0,1,2,3,4,5,6,9); endchar; 
+endchar; 
 
 cmchar "Right feathers"; 
 beginchar(slot_feathersright,arrow_head_width#,single_height); 
@@ -1614,7 +1626,7 @@
 y11=y12=math_axis;
 pickup rule.nib;
 draw z11---z12;
-penlabels(0,1,2,3,4,5,6,9); endchar; 
+endchar; 
  
 cmchar "Right hook up";
 compute_spread(.45x_height#,.55x_height#);
@@ -1624,7 +1636,7 @@
 y1-y3=spread; y2=.5[y1,y3]; y3=math_axis=y4;
 x4=hround(-arrow_overshoot);
 draw z1{right}...z2{down}...z3{left}---z4;  % hook
-labels(1,2,3); endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Right hook down";
 compute_spread(.45x_height#,.55x_height#);
@@ -1634,7 +1646,7 @@
 y3-y1=spread; y2=.5[y1,y3]; y3=math_axis=y4;
 x4=hround(-arrow_overshoot);
 draw z1{right}...z2{up}...z3{left}---z4;  % hook
-labels(1,2,3); endchar;
+penlabels(1,2,3,4); endchar;
 
 cmchar "Right curly up";  
 beginchar(slot_curlyupright,arrow_head_width#,.8asc_height#,0#); 
@@ -1658,30 +1670,33 @@
 q=z15--z10{right}..tension0.8..{up}z11..tension0.8..{left}z12 
 ..tension0.8..{down}z13--z14; 
 draw q; 
-penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14); endchar; 
+penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14,15); endchar; 
  
 cmchar "Right curly down";  
 beginchar(slot_curlydownright,arrow_head_width#,.8asc_height#,0#); 
 adjust_fit(0,0); 
 pickup pencircle scaled rule_thickness; 
 q:=q reflectedabout ((0,math_axis),(w,math_axis)); 
-draw q; endchar; 
+draw q;
+penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14,15); endchar; 
  
 cmchar "Left curly down";  
 beginchar(slot_curlydown,arrow_head_width#,.8asc_height#,0#); 
 adjust_fit(0,0); 
 pickup pencircle scaled rule_thickness; 
 q:=q reflectedabout ((w/2+eps,-d),(w/2+eps,h)); 
-draw q; endchar; 
+draw q;
+penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14,15); endchar; 
  
 cmchar "Left curly up";  
 beginchar(slot_curlyup,arrow_head_width#,.8asc_height#,0#); 
 adjust_fit(0,0); 
 pickup pencircle scaled rule_thickness; 
 q:=q reflectedabout ((0,math_axis),(w,math_axis)); 
-draw q; endchar; 
+draw q; 
+penlabels(0,1,2,3,4,5,6,9,10,11,12,13,14,15); endchar; 
 
-bye.
+endinput