]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/beam.cc
*** empty log message ***
[lilypond.git] / lily / beam.cc
index 4c5f743030bb52eccd90edf094bb3f2a262a2f8c..61e27d7ce31ed01a044c31bb5fbf2d0d76a08e14 100644 (file)
@@ -3,15 +3,13 @@
   
   source file of the GNU LilyPond music typesetter
   
   
   source file of the GNU LilyPond music typesetter
   
-  (c)  1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (c) 1997--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
   Jan Nieuwenhuizen <janneke@gnu.org>
 */
 
 /*
 TODO:
 
   Jan Nieuwenhuizen <janneke@gnu.org>
 */
 
 /*
 TODO:
 
-  * Use Number_pair i.s.o Interval to represent (yl, yr).
-  
   - Determine auto knees based on positions if it's set by the user.
 
   - the code is littered with * and / staff_space calls for
   - Determine auto knees based on positions if it's set by the user.
 
   - the code is littered with * and / staff_space calls for
@@ -21,7 +19,6 @@ TODO:
   
 Notes:
 
   
 Notes:
 
-
  - Stems run to the Y-center of the beam.
   
  - beam_translation is the offset between Y centers of the beam.
  - Stems run to the Y-center of the beam.
   
  - beam_translation is the offset between Y centers of the beam.
@@ -29,16 +26,17 @@ Notes:
 */
 
 
 */
 
 
+
 #include <math.h> // tanh.
 
 #include <math.h> // tanh.
 
-#include "molecule.hh" 
+#include "beam.hh"
+#include "interval-set.hh"
 #include "directional-element-interface.hh"
 #include "beaming.hh"
 #include "directional-element-interface.hh"
 #include "beaming.hh"
-#include "beam.hh"
 #include "misc.hh"
 #include "least-squares.hh"
 #include "stem.hh"
 #include "misc.hh"
 #include "least-squares.hh"
 #include "stem.hh"
-#include "paper-def.hh"
+#include "output-def.hh"
 #include "lookup.hh"
 #include "group-interface.hh"
 #include "staff-symbol-referencer.hh"
 #include "lookup.hh"
 #include "group-interface.hh"
 #include "staff-symbol-referencer.hh"
@@ -47,10 +45,6 @@ Notes:
 #include "warn.hh"
 
 
 #include "warn.hh"
 
 
-
-bool debug_beam_quanting_flag;
-
-
 #if DEBUG_QUANTING
 #include "text-item.hh"  // debug output.
 #include "font-interface.hh"  // debug output.
 #if DEBUG_QUANTING
 #include "text-item.hh"  // debug output.
 #include "font-interface.hh"  // debug output.
@@ -65,7 +59,7 @@ Beam::add_stem (Grob *me, Grob *s)
   s->add_dependency (me);
 
   assert (!Stem::get_beam (s));
   s->add_dependency (me);
 
   assert (!Stem::get_beam (s));
-  s->set_grob_property ("beam", me->self_scm ());
+  s->set_property ("beam", me->self_scm ());
 
   add_bound_item (dynamic_cast<Spanner*> (me), dynamic_cast<Item*> (s));
 }
 
   add_bound_item (dynamic_cast<Spanner*> (me), dynamic_cast<Item*> (s));
 }
@@ -74,7 +68,7 @@ Beam::add_stem (Grob *me, Grob *s)
 Real
 Beam::get_thickness (Grob * me)
 {
 Real
 Beam::get_thickness (Grob * me)
 {
-  return robust_scm2double (me->get_grob_property ("thickness"), 0)
+  return robust_scm2double (me->get_property ("thickness"), 0)
     * Staff_symbol_referencer::staff_space (me);
 }
 
     * Staff_symbol_referencer::staff_space (me);
 }
 
@@ -82,9 +76,17 @@ Beam::get_thickness (Grob * me)
 Real
 Beam::get_beam_translation (Grob *me)
 {
 Real
 Beam::get_beam_translation (Grob *me)
 {
-  SCM func = me->get_grob_property ("space-function");
-  SCM s = gh_call2 (func, me->self_scm (), scm_int2num (get_beam_count (me)));
-  return gh_scm2double (s);
+  SCM func = me->get_property ("space-function");
+
+  if (ly_c_procedure_p (func))
+    {
+      SCM s = scm_call_2 (func, me->self_scm (), scm_int2num (get_beam_count (me)));
+      return scm_to_double (s);
+    }
+  else
+    {
+      return 0.81;
+    }
 }
 
 /* Maximum beam_count. */
 }
 
 /* Maximum beam_count. */
@@ -92,9 +94,9 @@ int
 Beam::get_beam_count (Grob *me) 
 {
   int m = 0;
 Beam::get_beam_count (Grob *me) 
 {
   int m = 0;
-  for (SCM s = me->get_grob_property ("stems"); gh_pair_p (s); s = ly_cdr (s))
+  for (SCM s = me->get_property ("stems"); scm_is_pair (s); s = scm_cdr (s))
     {
     {
-      Grob *stem = unsmob_grob (ly_car (s));
+      Grob *stem = unsmob_grob (scm_car (s));
       m = m >? (Stem::beam_multiplicity (stem).length () + 1);
     }
   return m;
       m = m >? (Stem::beam_multiplicity (stem).length () + 1);
     }
   return m;
@@ -114,11 +116,11 @@ Beam::space_function (SCM smob, SCM beam_count)
   Real line = Staff_symbol_referencer::line_thickness (me);
   Real thickness = get_thickness (me);
   
   Real line = Staff_symbol_referencer::line_thickness (me);
   Real thickness = get_thickness (me);
   
-  Real beam_translation = gh_scm2int (beam_count) < 4
+  Real beam_translation = scm_to_int (beam_count) < 4
     ? (2*staff_space + line - thickness) / 2.0
     : (3*staff_space + line - thickness) / 3.0;
   
     ? (2*staff_space + line - thickness) / 2.0
     : (3*staff_space + line - thickness) / 3.0;
   
-  return gh_double2scm (beam_translation);
+  return scm_make_real (beam_translation);
 }
 
 
 }
 
 
@@ -147,12 +149,12 @@ Beam::before_line_breaking (SCM smob)
     {
       me->warning (_ ("beam has less than two visible stems"));
 
     {
       me->warning (_ ("beam has less than two visible stems"));
 
-      SCM stems = me->get_grob_property ("stems");
+      SCM stems = me->get_property ("stems");
       if (scm_ilength (stems) == 1)
        {
       if (scm_ilength (stems) == 1)
        {
-         me->warning (_ ("Beam has less than two stems. Removing beam."));
+         me->warning (_ ("removing beam with less than two stems"));
 
 
-         unsmob_grob (gh_car (stems))->set_grob_property ("beam", SCM_EOL);
+         unsmob_grob (scm_car (stems))->set_property ("beam", SCM_EOL);
          me->suicide ();
 
          return SCM_UNSPECIFIED;
          me->suicide ();
 
          return SCM_UNSPECIFIED;
@@ -198,18 +200,18 @@ position_with_maximal_common_beams (SCM left_beaming, SCM right_beaming,
                                    Direction left_dir,
                                    Direction right_dir)
 {
                                    Direction left_dir,
                                    Direction right_dir)
 {
-  Slice lslice = int_list_to_slice (gh_cdr (left_beaming));
+  Slice lslice = int_list_to_slice (scm_cdr (left_beaming));
 
   int best_count = 0;
   int best_start = 0;
   for (int i = lslice[-left_dir];
        (i - lslice[left_dir])* left_dir <= 0 ; i+= left_dir) 
     {
 
   int best_count = 0;
   int best_start = 0;
   for (int i = lslice[-left_dir];
        (i - lslice[left_dir])* left_dir <= 0 ; i+= left_dir) 
     {
-      int count =0;
-      for ( SCM s = gh_car (right_beaming); gh_pair_p (s); s = gh_cdr (s))
+      int count = 0;
+      for ( SCM s = scm_car (right_beaming); scm_is_pair (s); s = scm_cdr (s))
        {
        {
-         int k = - right_dir * gh_scm2int (gh_car (s)) + i;
-         if (scm_memq (scm_int2num (k), left_beaming) != SCM_BOOL_F)
+         int k = - right_dir * scm_to_int (scm_car (s)) + i;
+         if (scm_c_memq (scm_int2num (k), left_beaming) != SCM_BOOL_F)
            count ++;
        }
 
            count ++;
        }
 
@@ -226,20 +228,20 @@ position_with_maximal_common_beams (SCM left_beaming, SCM right_beaming,
 void
 Beam::connect_beams (Grob *me)
 {
 void
 Beam::connect_beams (Grob *me)
 {
-  Link_array<Grob> stems=
+  Link_array<Grob> stems =
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
 
   Slice last_int;
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
 
   Slice last_int;
-  last_int.set_empty();
+  last_int.set_empty ();
   SCM last_beaming = SCM_EOL;
   Direction last_dir = CENTER;
   SCM last_beaming = SCM_EOL;
   Direction last_dir = CENTER;
-  for (int i = 0; i< stems.size(); i++)
+  for (int i = 0; i< stems.size (); i++)
     {
       Grob *this_stem = stems[i];
     {
       Grob *this_stem = stems[i];
-      SCM this_beaming = this_stem->get_grob_property ("beaming");
+      SCM this_beaming = this_stem->get_property ("beaming");
 
       Direction this_dir = get_grob_direction (this_stem);
 
       Direction this_dir = get_grob_direction (this_stem);
-      if (gh_pair_p (last_beaming) && gh_pair_p (this_beaming))
+      if (scm_is_pair (last_beaming) && scm_is_pair (this_beaming))
        {
          int start_point = position_with_maximal_common_beams
            (last_beaming, this_beaming,
        {
          int start_point = position_with_maximal_common_beams
            (last_beaming, this_beaming,
@@ -249,18 +251,18 @@ Beam::connect_beams (Grob *me)
          Slice new_slice ; 
          do
            {
          Slice new_slice ; 
          do
            {
-             if (d == RIGHT && i == stems.size()-1)
+             if (d == RIGHT && i == stems.size ()-1)
                continue;
              
                continue;
              
-             new_slice.set_empty();
+             new_slice.set_empty ();
              SCM s = index_get_cell (this_beaming, d);
              SCM s = index_get_cell (this_beaming, d);
-             for (; gh_pair_p (s); s = gh_cdr (s))
+             for (; scm_is_pair (s); s = scm_cdr (s))
                {
                  int new_beam_pos =
                {
                  int new_beam_pos =
-                   start_point - this_dir * gh_scm2int (gh_car (s));
+                   start_point - this_dir * scm_to_int (scm_car (s));
 
                  new_slice.add_point (new_beam_pos);
 
                  new_slice.add_point (new_beam_pos);
-                 gh_set_car_x (s, scm_int2num (new_beam_pos));
+                 scm_set_car_x (s, scm_int2num (new_beam_pos));
                }
 
 
                }
 
 
@@ -272,22 +274,22 @@ Beam::connect_beams (Grob *me)
        }
       else
        {
        }
       else
        {
-         gh_set_car_x ( this_beaming, SCM_EOL);
-         SCM s = gh_cdr (this_beaming);
-         for (; gh_pair_p (s); s = gh_cdr (s))
+         scm_set_car_x ( this_beaming, SCM_EOL);
+         SCM s = scm_cdr (this_beaming);
+         for (; scm_is_pair (s); s = scm_cdr (s))
            {
            {
-             int np = - this_dir * gh_scm2int (gh_car(s));
-             gh_set_car_x (s, scm_int2num (np));
+             int np = - this_dir * scm_to_int (scm_car (s));
+             scm_set_car_x (s, scm_int2num (np));
              last_int.add_point (np);
            }
        }
 
       if (i == stems.size () -1)
        {
              last_int.add_point (np);
            }
        }
 
       if (i == stems.size () -1)
        {
-         gh_set_cdr_x (this_beaming, SCM_EOL);
+         scm_set_cdr_x (this_beaming, SCM_EOL);
        }
 
        }
 
-      if (scm_ilength (gh_cdr (this_beaming)) > 0)
+      if (scm_ilength (scm_cdr (this_beaming)) > 0)
        {
          last_beaming = this_beaming;
          last_dir = this_dir;
        {
          last_beaming = this_beaming;
          last_dir = this_dir;
@@ -299,17 +301,20 @@ Beam::connect_beams (Grob *me)
 /*
   TODO: should not make beams per stem, but per Y-level.
  */
 /*
   TODO: should not make beams per stem, but per Y-level.
  */
-MAKE_SCHEME_CALLBACK (Beam, brew_molecule, 1);
+MAKE_SCHEME_CALLBACK (Beam, print, 1);
 SCM
 SCM
-Beam::brew_molecule (SCM grob)
+Beam::print (SCM grob)
 {
 {
-  Grob *me = unsmob_grob (grob);
+  Spanner *me = unsmob_spanner (grob);
   position_beam (me);
   
   position_beam (me);
   
-  Link_array<Grob> stems=
+  Link_array<Grob> stems =
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
   Grob* xcommon = common_refpoint_of_array (stems, me, X_AXIS);
 
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
   Grob* xcommon = common_refpoint_of_array (stems, me, X_AXIS);
 
+  xcommon = me->get_bound (LEFT)->common_refpoint (xcommon, X_AXIS);
+  xcommon = me->get_bound (RIGHT)->common_refpoint (xcommon, X_AXIS);
+
   Real x0, dx;
   if (visible_stem_count (me))
     {
   Real x0, dx;
   if (visible_stem_count (me))
     {
@@ -323,58 +328,58 @@ Beam::brew_molecule (SCM grob)
       dx = stems.top ()->relative_coordinate (xcommon, X_AXIS) - x0;
     }
 
       dx = stems.top ()->relative_coordinate (xcommon, X_AXIS) - x0;
     }
 
-  SCM posns = me->get_grob_property ("positions");
-  Interval pos;
+  SCM posns = me->get_property ("positions");
+  Drul_array<Real> pos;
   if (!is_number_pair (posns))
     {
       programming_error ("No beam posns");
       pos = Interval (0,0);
     }
   else
   if (!is_number_pair (posns))
     {
       programming_error ("No beam posns");
       pos = Interval (0,0);
     }
   else
-    pos= ly_scm2interval (posns);
-
+    pos = ly_scm2realdrul (posns);
 
 
-  pos *= Staff_symbol_referencer::staff_space (me); 
-  Real dy = pos.delta ();
-  Real dydx = (dy && dx) ? dy/dx : 0;
+  scale_drul (&pos,  Staff_symbol_referencer::staff_space (me));
+  
+  Real dy = pos[RIGHT] - pos[LEFT];
+  Real slope = (dy && dx) ? dy/dx : 0;
   
   Real thick = get_thickness (me);
   Real bdy = get_beam_translation (me);
 
   
   Real thick = get_thickness (me);
   Real bdy = get_beam_translation (me);
 
-  SCM last_beaming = SCM_EOL;;
+  SCM last_beaming = SCM_EOL;
   Real last_xposn = -1;
   Real last_stem_width = -1 ;
 
   Real last_xposn = -1;
   Real last_stem_width = -1 ;
 
-  Real gap_length =robust_scm2double ( me->get_grob_property ("gap"), 0.0);
+  Real gap_length = robust_scm2double (me->get_property ("gap"), 0.0);
   
   
-  Molecule the_beam;
-  Real lt = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
+  Stencil the_beam;
+  Real lt = me->get_layout ()->get_dimension (ly_symbol2scm ("linethickness"));
   
   
-  for (int i = 0; i<= stems.size(); i++)
+  for (int i = 0; i<= stems.size (); i++)
     {
     {
-      Grob * st = (i < stems.size()) ? stems[i] : 0;
+      Grob * st = (i < stems.size ()) ? stems[i] : 0;
       
       
-      SCM this_beaming = st ? st->get_grob_property ("beaming") : SCM_EOL;
+      SCM this_beaming = st ? st->get_property ("beaming") : SCM_EOL;
       Real xposn = st ? st->relative_coordinate (xcommon, X_AXIS) : 0.0;
       Real xposn = st ? st->relative_coordinate (xcommon, X_AXIS) : 0.0;
-      Real stem_width = st ? robust_scm2double (st->get_grob_property ("thickness"), 1.0) *lt : 0 ;
-      Direction stem_dir = st ? to_dir (st->get_grob_property ("direction")) : CENTER;
+      Real stem_width = st ? robust_scm2double (st->get_property ("thickness"), 1.0) *lt : 0 ;
+      Direction stem_dir = st ? to_dir (st->get_property ("direction")) : CENTER;
       /*
        We do the space left of ST, with lfliebertjes pointing to the
        right from the left stem, and rfliebertjes pointing left from
        right stem.
        */
       /*
        We do the space left of ST, with lfliebertjes pointing to the
        right from the left stem, and rfliebertjes pointing left from
        right stem.
        */
-      SCM left = (i>0) ? gh_cdr (last_beaming) : SCM_EOL;
-      SCM right = st ? gh_car (this_beaming) : SCM_EOL;
+      SCM left = (i > 0) ? scm_cdr (last_beaming) : SCM_EOL;
+      SCM right = st ? scm_car (this_beaming) : SCM_EOL;
 
       Array<int> full_beams;
       Array<int> lfliebertjes;
       Array<int> rfliebertjes;   
 
       for (SCM s = left;
 
       Array<int> full_beams;
       Array<int> lfliebertjes;
       Array<int> rfliebertjes;   
 
       for (SCM s = left;
-          gh_pair_p (s); s =gh_cdr (s))
+          scm_is_pair (s); s = scm_cdr (s))
        {
        {
-         int b = gh_scm2int (gh_car (s));
-         if (scm_memq (gh_car(s), right) != SCM_BOOL_F)
+         int b = scm_to_int (scm_car (s));
+         if (scm_c_memq (scm_car (s), right) != SCM_BOOL_F)
            {
              full_beams.push (b);
            }
            {
              full_beams.push (b);
            }
@@ -384,10 +389,10 @@ Beam::brew_molecule (SCM grob)
            }
        }
       for (SCM s = right;
            }
        }
       for (SCM s = right;
-          gh_pair_p (s); s =gh_cdr (s))
+          scm_is_pair (s); s = scm_cdr (s))
        {
        {
-         int b = gh_scm2int (gh_car (s));
-         if (scm_memq (gh_car(s), left) == SCM_BOOL_F)
+         int b = scm_to_int (scm_car (s));
+         if (scm_c_memq (scm_car (s), left) == SCM_BOOL_F)
            {
              rfliebertjes.push (b);
            }
            {
              rfliebertjes.push (b);
            }
@@ -397,9 +402,9 @@ Beam::brew_molecule (SCM grob)
        how much to stick out for beams across linebreaks
        */
       Real break_overshoot = 3.0;
        how much to stick out for beams across linebreaks
        */
       Real break_overshoot = 3.0;
-      Real w = (i > 0 && st) ? xposn - last_xposn : break_overshoot;
+      Real w = (i > 0 && st) ? (xposn - last_xposn) : break_overshoot;
 
 
-      Real stem_offset =0.0;
+      Real stem_offset = 0.0;
       if (i > 0)
        {
          w += last_stem_width / 2;
       if (i > 0)
        {
          w += last_stem_width / 2;
@@ -410,15 +415,15 @@ Beam::brew_molecule (SCM grob)
        w += stem_width/ 2 ;
       
 
        w += stem_width/ 2 ;
       
 
-      Real blot = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
-      Molecule whole = Lookup::beam (dydx, w, thick, blot);
-      Molecule gapped;
+      Real blot = me->get_layout ()->get_dimension (ly_symbol2scm ("blotdiameter"));
+      Stencil whole = Lookup::beam (slope, w, thick, blot);
+      Stencil gapped;
 
       int gap_count = 0;
 
       int gap_count = 0;
-      if (gh_number_p (me->get_grob_property ("gap-count")))
+      if (scm_is_number (me->get_property ("gap-count")))
        {
        {
-         gap_count = gh_scm2int (me->get_grob_property ("gap-count"));
-         gapped = Lookup::beam (dydx, w - 2 * gap_length, thick, blot);
+         gap_count = scm_to_int (me->get_property ("gap-count"));
+         gapped = Lookup::beam (slope, w - 2 * gap_length, thick, blot);
 
          full_beams.sort (default_compare);
          if (stem_dir == UP)
 
          full_beams.sort (default_compare);
          if (stem_dir == UP)
@@ -428,7 +433,7 @@ Beam::brew_molecule (SCM grob)
       int k = 0;
       for (int j = full_beams.size (); j--;)
        {
       int k = 0;
       for (int j = full_beams.size (); j--;)
        {
-         Molecule b (whole);
+         Stencil b (whole);
          
          if (k++ < gap_count)
            {
          
          if (k++ < gap_count)
            {
@@ -436,14 +441,12 @@ Beam::brew_molecule (SCM grob)
              b.translate_axis (gap_length, X_AXIS);
            }
          b.translate_axis (last_xposn -  x0 + stem_offset, X_AXIS);
              b.translate_axis (gap_length, X_AXIS);
            }
          b.translate_axis (last_xposn -  x0 + stem_offset, X_AXIS);
-         b.translate_axis (dydx * (last_xposn - x0) + bdy * full_beams[j], Y_AXIS);
+         b.translate_axis (slope * (last_xposn - x0) + bdy * full_beams[j], Y_AXIS);
 
 
-         the_beam.add_molecule (b);          
+         the_beam.add_stencil (b);           
        }
        }
-
-      
          
          
-      if (lfliebertjes.size() || rfliebertjes.size())
+      if (lfliebertjes.size () || rfliebertjes.size ())
        {
          Real nw_f;
 
        {
          Real nw_f;
 
@@ -451,32 +454,47 @@ Beam::brew_molecule (SCM grob)
            {
              int t = Stem::duration_log (st); 
 
            {
              int t = Stem::duration_log (st); 
 
-             SCM proc = me->get_grob_property ("flag-width-function");
-             SCM result = gh_call1 (proc, scm_int2num (t));
-             nw_f = gh_scm2double (result);
+             SCM proc = me->get_property ("flag-width-function");
+             SCM result = scm_call_1 (proc, scm_int2num (t));
+             nw_f = scm_to_double (result);
            }
          else
            }
          else
-           nw_f = break_overshoot;
+           nw_f = break_overshoot / 2;
              
          /* Half beam should be one note-width,
             but let's make sure two half-beams never touch */
              
          /* Half beam should be one note-width,
             but let's make sure two half-beams never touch */
-         Real w = (i>0 && st) ? (xposn - last_xposn) : break_overshoot;
-         w = w/2 <? nw_f;
+         Real lw = nw_f;
+         Real rw = nw_f;
+         if (i > 0)
+           rw = nw_f <? ( (xposn - last_xposn) / 2);
+         else
+           /*
+             TODO: 0.5 is a guess.
+           */
+           rw = xposn - me->get_bound (LEFT)->extent (xcommon, X_AXIS)[RIGHT]
+             - 0.5;
+         
+         if (st)
+           lw = nw_f <? ( (xposn - last_xposn) / 2);
+         else
+           lw = me->get_bound (RIGHT)->relative_coordinate (xcommon, X_AXIS)
+             - last_xposn;
 
 
-         Molecule half = Lookup::beam (dydx, w, thick, blot);
-         for (int j = lfliebertjes.size(); j--;)
+         Stencil rhalf = Lookup::beam (slope, rw, thick, blot);
+         Stencil lhalf = Lookup::beam (slope, lw, thick, blot);
+         for (int j = lfliebertjes.size (); j--;)
            {
            {
-             Molecule b (half);
+             Stencil b (lhalf);
              b.translate_axis (last_xposn -  x0, X_AXIS);
              b.translate_axis (last_xposn -  x0, X_AXIS);
-             b.translate_axis (dydx * (last_xposn-x0) + bdy * lfliebertjes[j], Y_AXIS);
-             the_beam.add_molecule (b);              
+             b.translate_axis (slope * (last_xposn-x0) + bdy * lfliebertjes[j], Y_AXIS);
+             the_beam.add_stencil (b);       
            }
            }
-         for (int j = rfliebertjes.size(); j--;)
+         for (int j = rfliebertjes.size (); j--;)
            {
            {
-             Molecule b (half);
-             b.translate_axis (xposn -  x0 - w , X_AXIS);
-             b.translate_axis (dydx * (xposn-x0 -w) + bdy * rfliebertjes[j], Y_AXIS);
-             the_beam.add_molecule (b);              
+             Stencil b (rhalf);
+             b.translate_axis (xposn -  x0 - rw , X_AXIS);
+             b.translate_axis (slope * (xposn-x0 -rw) + bdy * rfliebertjes[j], Y_AXIS);
+             the_beam.add_stencil (b);       
            }
        }
 
            }
        }
 
@@ -490,9 +508,9 @@ Beam::brew_molecule (SCM grob)
   the_beam.translate_axis (pos[LEFT], Y_AXIS);
 
 #if (DEBUG_QUANTING)
   the_beam.translate_axis (pos[LEFT], Y_AXIS);
 
 #if (DEBUG_QUANTING)
-  SCM quant_score = me->get_grob_property ("quant-score");
-  if (debug_beam_quanting_flag
-      && gh_string_p (quant_score))
+  SCM quant_score = me->get_property ("quant-score");
+  if (to_boolean (me->get_layout ()->lookup_variable (ly_symbol2scm ("debug-beam-quanting")))
+      && scm_is_string (quant_score))
     {
       
       /*
     {
       
       /*
@@ -501,17 +519,17 @@ Beam::brew_molecule (SCM grob)
        parameters.
       */
       String str;
        parameters.
       */
       String str;
-      SCM properties = Font_interface::font_alist_chain (me);
+      SCM properties = Font_interface::text_font_alist_chain (me);
 
 
-      Molecule tm = *unsmob_molecule (Text_item::interpret_markup
-       (me->get_paper ()->self_scm (), properties, quant_score));
-      the_beam.add_at_edge (Y_AXIS, UP, tm, 5.0, 0);
+      Direction stem_dir = stems.size() ? to_dir (stems[0]->get_property ("direction")) : UP;
+    
+      Stencil tm = *unsmob_stencil (Text_interface::interpret_markup
+        (me->get_layout ()->self_scm (), properties, quant_score));
+      the_beam.add_at_edge (Y_AXIS, stem_dir, tm, 1.0, 0);
     }
 #endif
     }
 #endif
-    
-  
   
   
-  return the_beam.smobbed_copy();
+  return the_beam.smobbed_copy ();
 }
   
 
 }
   
 
@@ -526,15 +544,15 @@ Beam::get_default_dir (Grob *me)
   count[UP]  = count[DOWN] = 0;
   Direction d = DOWN;
 
   count[UP]  = count[DOWN] = 0;
   Direction d = DOWN;
 
-  Link_array<Grob> stems=
+  Link_array<Grob> stems =
        Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
 
        Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
 
-  for (int i=0; i <stems.size (); i++)
+  for (int i = 0; i < stems.size (); i++)
     do {
       Grob *s = stems[i];
       Direction sd = get_grob_direction (s);
 
     do {
       Grob *s = stems[i];
       Direction sd = get_grob_direction (s);
 
-      int center_distance = int(- d * Stem::head_positions (s) [-d]) >? 0;
+      int center_distance = int (- d * Stem::head_positions (s) [-d]) >? 0;
       int current = sd ? (1 + d * sd)/2 : center_distance;
 
       if (current)
       int current = sd ? (1 + d * sd)/2 : center_distance;
 
       if (current)
@@ -544,18 +562,18 @@ Beam::get_default_dir (Grob *me)
        }
     } while (flip (&d) != DOWN);
   
        }
     } while (flip (&d) != DOWN);
   
-  SCM func = me->get_grob_property ("dir-function");
-  SCM s = gh_call2 (func,
-                   gh_cons (scm_int2num (count[UP]),
+  SCM func = me->get_property ("dir-function");
+  SCM s = scm_call_2 (func,
+                   scm_cons (scm_int2num (count[UP]),
                             scm_int2num (count[DOWN])),
                             scm_int2num (count[DOWN])),
-                   gh_cons (scm_int2num (total[UP]),
+                   scm_cons (scm_int2num (total[UP]),
                             scm_int2num (total[DOWN])));
 
                             scm_int2num (total[DOWN])));
 
-  if (gh_number_p (s) && gh_scm2int (s))
+  if (scm_is_number (s) && scm_to_int (s))
     return to_dir (s);
   
   /* If dir is not determined: get default */
     return to_dir (s);
   
   /* If dir is not determined: get default */
-  return to_dir (me->get_grob_property ("neutral-direction"));
+  return to_dir (me->get_property ("neutral-direction"));
 }
 
 
 }
 
 
@@ -566,77 +584,18 @@ void
 Beam::set_stem_directions (Grob *me, Direction d)
 {
   Link_array<Grob> stems
 Beam::set_stem_directions (Grob *me, Direction d)
 {
   Link_array<Grob> stems
-    =Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
+    = Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
   
   
-  for (int i=0; i <stems.size (); i++)
+  for (int i = 0; i <stems.size (); i++)
     {
       Grob *s = stems[i];
   
     {
       Grob *s = stems[i];
   
-      SCM forcedir = s->get_grob_property ("direction");
+      SCM forcedir = s->get_property ("direction");
       if (!to_dir (forcedir))
        set_grob_direction (s,  d);
     }
 }
 
       if (!to_dir (forcedir))
        set_grob_direction (s,  d);
     }
 }
 
-/*
-  A union of intervals in the real line.
-
-  Abysmal performance (quadratic) for large N, hopefully we don't have
-  that large N. In any case, this should probably be rewritten to use
-  a balanced tree.
- */
-struct Int_set
-{
-  Array<Interval> allowed_regions_;
-
-  Int_set()
-  {
-    set_full();
-  }
-
-  void set_full()
-  {
-    allowed_regions_.clear();
-    Interval s;
-    s.set_full ();
-    allowed_regions_.push (s);
-  }
-
-  void remove_interval (Interval rm)
-  {
-    for (int i = 0; i < allowed_regions_.size(); )
-      {
-       Interval s = rm;
-
-       s.intersect (allowed_regions_[i]);
-
-       if (!s.is_empty ())
-         {
-           Interval before = allowed_regions_[i];
-           Interval after = allowed_regions_[i];
-
-           before[RIGHT] = s[LEFT];
-           after[LEFT] = s[RIGHT];
-
-           if (!before.is_empty () && before.length () > 0.0)
-             {
-               allowed_regions_.insert (before, i);
-               i++;
-             }
-           allowed_regions_.del (i);
-           if (!after.is_empty () && after.length () > 0.0)
-             {
-               allowed_regions_.insert (after, i);
-               i++;
-             }
-         }
-       else
-         i++;
-      }
-  }
-};
-
-
 /*
   Only try horizontal beams for knees.  No reliable detection of
   anything else is possible here, since we don't know funky-beaming
 /*
   Only try horizontal beams for knees.  No reliable detection of
   anything else is possible here, since we don't know funky-beaming
@@ -646,94 +605,98 @@ struct Int_set
 void
 Beam::consider_auto_knees (Grob* me)
 {
 void
 Beam::consider_auto_knees (Grob* me)
 {
-  SCM scm = me->get_grob_property ("auto-knee-gap");
-  if (!gh_number_p (scm))
+  SCM scm = me->get_property ("auto-knee-gap");
+  if (!scm_is_number (scm))
     return ;
 
     return ;
 
-  Real threshold = gh_scm2double (scm);
-  
-  Int_set gaps;
+  Interval_set gaps;
 
   gaps.set_full ();
 
 
   gaps.set_full ();
 
-  Link_array<Grob> stems=
-    Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
-      
+  Link_array<Grob> stems =
+    Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
+  
   Grob *common = common_refpoint_of_array (stems, me,  Y_AXIS);
   Real staff_space = Staff_symbol_referencer::staff_space (me);
   
   Grob *common = common_refpoint_of_array (stems, me,  Y_AXIS);
   Real staff_space = Staff_symbol_referencer::staff_space (me);
   
-  Array<Interval> hps_array;  
-  for (int i=0; i < stems.size (); i++)
+  Array<Interval> head_positions_array;  
+  for (int i = 0; i < stems.size (); i++)
     {
       Grob* stem = stems[i];
     {
       Grob* stem = stems[i];
-      if (Stem::invisible_b (stem))
+      if (Stem::is_invisible (stem))
        continue;
 
        continue;
 
-      Interval hps = Stem::head_positions (stem);
-      if(!hps.is_empty ())
+      Interval head_positions = Stem::head_positions (stem);
+      if (!head_positions.is_empty ())
        {
        {
-         hps[LEFT] += -1;
-         hps[RIGHT] += 1; 
-         hps *= staff_space * 0.5 ;
+         head_positions[LEFT] += -1;
+         head_positions[RIGHT] += 1; 
+         head_positions *= staff_space * 0.5 ;
 
          /*
            We could subtract beam Y position, but this routine only
            sets stem directions, a constant shift does not have an
            influence.
 
          /*
            We could subtract beam Y position, but this routine only
            sets stem directions, a constant shift does not have an
            influence.
-           
           */
           */
-         hps += stem->relative_coordinate (common, Y_AXIS);
+         head_positions += stem->relative_coordinate (common, Y_AXIS);
 
 
-         if (to_dir (stem->get_grob_property ("direction")))
+         if (to_dir (stem->get_property ("direction")))
            {
            {
-             Direction stemdir = to_dir (stem->get_grob_property ("direction"));
-             hps[-stemdir] = - stemdir * infinity_f;
+             Direction stemdir = to_dir (stem->get_property ("direction"));
+             head_positions[-stemdir] = - stemdir * infinity_f;
            }
        }
            }
        }
-      hps_array.push (hps);
+      head_positions_array.push (head_positions);
 
 
-      gaps.remove_interval (hps);
+      gaps.remove_interval (head_positions);
     }
 
   Interval max_gap;
     }
 
   Interval max_gap;
-  Real max_gap_len =0.0;
+  Real max_gap_len = 0.0;
 
 
-  for (int i  = gaps.allowed_regions_.size() -1;  i >=  0 ; i--)
+  for (int i  = gaps.allowed_regions_.size () -1;  i >=  0 ; i--)
     {
       Interval gap = gaps.allowed_regions_[i];
 
       /*
        the outer gaps are not knees.
        */
     {
       Interval gap = gaps.allowed_regions_[i];
 
       /*
        the outer gaps are not knees.
        */
-      if (isinf (gap[LEFT]) || isinf(gap[RIGHT]))
+      if (isinf (gap[LEFT]) || isinf (gap[RIGHT]))
        continue;
       
       if (gap.length () >= max_gap_len)
        {
        continue;
       
       if (gap.length () >= max_gap_len)
        {
-         max_gap_len = gap.length();
+         max_gap_len = gap.length ();
          max_gap = gap;
        }
     }
 
          max_gap = gap;
        }
     }
 
+  Real beam_translation = get_beam_translation (me);
+  Real beam_thickness = Beam::get_thickness (me);
+  int beam_count = Beam::get_beam_count (me);  
+  Real height_of_beams = beam_thickness / 2
+    + (beam_count - 1) * beam_translation;
+  Real threshold = scm_to_double (scm) +  height_of_beams;
+  
   if (max_gap_len > threshold)
     {
       int j = 0;
   if (max_gap_len > threshold)
     {
       int j = 0;
-      for (int i = 0; i < stems.size(); i++)
+      for (int i = 0; i < stems.size (); i++)
        {
          Grob* stem = stems[i];
        {
          Grob* stem = stems[i];
-         if (Stem::invisible_b (stem))
+         if (Stem::is_invisible (stem))
            continue;
 
            continue;
 
-         Interval hps = hps_array[j++];
+         Interval head_positions = head_positions_array[j++];
 
 
 
 
-         Direction d =  (hps.center () < max_gap.center()) ?
+         Direction d =  (head_positions.center () < max_gap.center ()) ?
            UP : DOWN ;
          
            UP : DOWN ;
          
-         stem->set_grob_property ("direction", scm_int2num (d));
+         stem->set_property ("direction", scm_int2num (d));
          
          
-         hps.intersect (max_gap);
-         assert (hps.is_empty () || hps.length () < 1e-6 );
+         head_positions.intersect (max_gap);
+         assert (head_positions.is_empty () || head_positions.length () < 1e-6 );
        }
     }
 }
        }
     }
 }
@@ -756,7 +719,7 @@ Beam::set_stem_shorten (Grob *me)
   /*
     shortening looks silly for x staff beams
    */
   /*
     shortening looks silly for x staff beams
    */
-  if (knee_b(me))
+  if (is_knee (me))
     return ;
   
   Real forced_fraction = 1.0 * forced_stem_count (me)
     return ;
   
   Real forced_fraction = 1.0 * forced_stem_count (me)
@@ -764,7 +727,7 @@ Beam::set_stem_shorten (Grob *me)
 
   int beam_count = get_beam_count (me);
 
 
   int beam_count = get_beam_count (me);
 
-  SCM shorten_list = me->get_grob_property ("beamed-stem-shorten");
+  SCM shorten_list = me->get_property ("beamed-stem-shorten");
   if (shorten_list == SCM_EOL)
     return;
 
   if (shorten_list == SCM_EOL)
     return;
 
@@ -772,13 +735,13 @@ Beam::set_stem_shorten (Grob *me)
   
   SCM shorten_elt =
     robust_list_ref (beam_count -1, shorten_list);
   
   SCM shorten_elt =
     robust_list_ref (beam_count -1, shorten_list);
-  Real shorten_f = gh_scm2double (shorten_elt) * staff_space;
+  Real shorten_f = scm_to_double (shorten_elt) * staff_space;
 
   /* your similar cute comment here */
   shorten_f *= forced_fraction;
 
   if (shorten_f)
 
   /* your similar cute comment here */
   shorten_f *= forced_fraction;
 
   if (shorten_f)
-    me->set_grob_property ("shorten", gh_double2scm (shorten_f));
+    me->set_property ("shorten", scm_make_real (shorten_f));
 }
 
 /*  Call list of y-dy-callbacks, that handle setting of
 }
 
 /*  Call list of y-dy-callbacks, that handle setting of
@@ -798,27 +761,52 @@ Beam::after_line_breaking (SCM smob)
 void
 Beam::position_beam (Grob *me)
 {
 void
 Beam::position_beam (Grob *me)
 {
-  if (to_boolean (me->get_grob_property ("positioning-done")))
+  if (!me->is_live ())
+    return ;
+  if (to_boolean (me->get_property ("positioning-done")))
     return ;
 
     return ;
 
-  me->set_grob_property ("positioning-done", SCM_BOOL_T);
+  me->set_property ("positioning-done", SCM_BOOL_T);
 
   /* Copy to mutable list. */
 
   /* Copy to mutable list. */
-  SCM s = ly_deep_copy (me->get_grob_property ("positions"));
-  me->set_grob_property ("positions", s);
+  SCM s = ly_deep_copy (me->get_property ("positions"));
+  me->set_property ("positions", s);
 
 
-  if (ly_car (s) == SCM_BOOL_F)
+  if (scm_car (s) == SCM_BOOL_F)
     {
       // one wonders if such genericity is necessary  --hwn.
     {
       // one wonders if such genericity is necessary  --hwn.
-      SCM callbacks = me->get_grob_property ("position-callbacks");
-      for (SCM i = callbacks; gh_pair_p (i); i = ly_cdr (i))
-       gh_call1 (ly_car (i), me->self_scm ());
+      SCM callbacks = me->get_property ("position-callbacks");
+      for (SCM i = callbacks; scm_is_pair (i); i = scm_cdr (i))
+       scm_call_1 (scm_car (i), me->self_scm ());
     }
 
   set_stem_lengths (me);  
 }
 
 
     }
 
   set_stem_lengths (me);  
 }
 
 
+void
+set_minimum_dy (Grob *me, Real * dy)
+{
+  if (*dy)
+    {
+      /*
+       If dy is smaller than the smallest quant, we
+       get absurd direction-sign penalties. 
+      */
+         
+      Real ss = Staff_symbol_referencer::staff_space (me);
+      Real thickness = Beam::get_thickness (me) / ss ;
+      Real slt = Staff_symbol_referencer::line_thickness (me) / ss;
+      Real sit = (thickness - slt) / 2;
+      Real inter = 0.5;
+      Real hang = 1.0 - (thickness - slt) / 2;
+         
+      *dy = sign (*dy) * (fabs (*dy)
+                       >?
+                       (sit <? inter <? hang));
+    }
+}
+
 /*
   Compute  a first approximation to the beam slope.
  */
 /*
   Compute  a first approximation to the beam slope.
  */
@@ -833,13 +821,13 @@ Beam::least_squares (SCM smob)
   
   if (count < 1)
     {
   
   if (count < 1)
     {
-      me->set_grob_property ("positions", ly_interval2scm (pos));
+      me->set_property ("positions", ly_interval2scm (pos));
       return SCM_UNSPECIFIED;
     }
 
 
   Array<Real> x_posns ;
       return SCM_UNSPECIFIED;
     }
 
 
   Array<Real> x_posns ;
-  Link_array<Grob> stems=
+  Link_array<Grob> stems =
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
   Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS);
   Grob *commony = common_refpoint_of_array (stems, me, Y_AXIS);  
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
   Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS);
   Grob *commony = common_refpoint_of_array (stems, me, Y_AXIS);  
@@ -855,7 +843,7 @@ Beam::least_squares (SCM smob)
                  + lvs->relative_coordinate (commony, Y_AXIS) - my_y);
   
   Real x0 = first_visible_stem (me)->relative_coordinate (commonx, X_AXIS);
                  + lvs->relative_coordinate (commony, Y_AXIS) - my_y);
   
   Real x0 = first_visible_stem (me)->relative_coordinate (commonx, X_AXIS);
-  for (int i=0; i < stems.size (); i++)
+  for (int i = 0; i < stems.size (); i++)
     {
       Grob* s = stems[i];
 
     {
       Grob* s = stems[i];
 
@@ -865,8 +853,8 @@ Beam::least_squares (SCM smob)
   Real dx = last_visible_stem (me)->relative_coordinate (commonx, X_AXIS) - x0;
 
   
   Real dx = last_visible_stem (me)->relative_coordinate (commonx, X_AXIS) - x0;
 
   
-  Real y =0;  
-  Real dydx = 0;
+  Real y = 0;  
+  Real slope = 0;
   Real dy = 0;
   
   if (!ideal.delta ())
   Real dy = 0;
   
   if (!ideal.delta ())
@@ -895,18 +883,19 @@ Beam::least_squares (SCM smob)
 
       /*
        For broken beams this doesn't work well. In this case, the
 
       /*
        For broken beams this doesn't work well. In this case, the
-        slope esp. of the first part of a broken beam should predict
-        where the second part goes.
-       */
-
+       slope esp. of the first part of a broken beam should predict
+       where the second part goes.
+      */
+      me->set_property ("least-squares-dy",
+                       scm_make_real (pos[RIGHT] - pos[LEFT]));
     }
   else
     {
       Array<Offset> ideals;
     }
   else
     {
       Array<Offset> ideals;
-      for (int i=0; i < stems.size (); i++)
+      for (int i = 0; i < stems.size (); i++)
        {
          Grob* s = stems[i];
        {
          Grob* s = stems[i];
-         if (Stem::invisible_b (s))
+         if (Stem::is_invisible (s))
            continue;
          ideals.push (Offset (x_posns[i],
                               Stem::get_stem_info (s).ideal_y_
            continue;
          ideals.push (Offset (x_posns[i],
                               Stem::get_stem_info (s).ideal_y_
@@ -914,19 +903,21 @@ Beam::least_squares (SCM smob)
                               - my_y));
        }
       
                               - my_y));
        }
       
-      minimise_least_squares (&dydx, &y, ideals);
+      minimise_least_squares (&slope, &y, ideals);
 
 
-      dy = dydx * dx;
-      me->set_grob_property ("least-squares-dy", gh_double2scm (dy));
+      dy = slope * dx;
+
+      set_minimum_dy (me,&dy);
+      me->set_property ("least-squares-dy", scm_make_real (dy));
       pos = Interval (y, (y+dy));
     }
 
   /*
     "position" is relative to the staff.
    */
       pos = Interval (y, (y+dy));
     }
 
   /*
     "position" is relative to the staff.
    */
-  pos *= 1/ Staff_symbol_referencer::staff_space (me); 
+  scale_drul (&pos,  1/ Staff_symbol_referencer::staff_space (me)); 
   
   
-  me->set_grob_property ("positions", ly_interval2scm (pos));
+  me->set_property ("positions", ly_interval2scm (pos));
  
   return SCM_UNSPECIFIED;
 }
  
   return SCM_UNSPECIFIED;
 }
@@ -936,10 +927,10 @@ Beam::least_squares (SCM smob)
   We can't combine with previous function, since check concave and
   slope damping comes first.
 
   We can't combine with previous function, since check concave and
   slope damping comes first.
 
-TODO: we should use the concaveness to control the amount of damping
-applied.
+  TODO: we should use the concaveness to control the amount of damping
+  applied.
   
   
- */
+*/
 MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 1);
 SCM
 Beam::shift_region_to_valid (SCM grob)
 MAKE_SCHEME_CALLBACK (Beam, shift_region_to_valid, 1);
 SCM
 Beam::shift_region_to_valid (SCM grob)
@@ -949,7 +940,7 @@ Beam::shift_region_to_valid (SCM grob)
     Code dup.
    */
   Array<Real> x_posns ;
     Code dup.
    */
   Array<Real> x_posns ;
-  Link_array<Grob> stems=
+  Link_array<Grob> stems =
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
   Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS);
   Grob *commony = common_refpoint_of_array (stems, me, Y_AXIS);  
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
   Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS);
   Grob *commony = common_refpoint_of_array (stems, me, Y_AXIS);  
@@ -959,8 +950,8 @@ Beam::shift_region_to_valid (SCM grob)
   if (!fvs)
     return SCM_UNSPECIFIED;
     
   if (!fvs)
     return SCM_UNSPECIFIED;
     
-  Real x0 =fvs->relative_coordinate (commonx, X_AXIS);
-  for (int i=0; i < stems.size (); i++)
+  Real x0 = fvs->relative_coordinate (commonx, X_AXIS);
+  for (int i = 0; i < stems.size (); i++)
     {
       Grob* s = stems[i];
 
     {
       Grob* s = stems[i];
 
@@ -974,13 +965,13 @@ Beam::shift_region_to_valid (SCM grob)
   
   Real dx = lvs->relative_coordinate (commonx, X_AXIS) - x0;
 
   
   Real dx = lvs->relative_coordinate (commonx, X_AXIS) - x0;
 
-  Interval pos = ly_scm2interval ( me->get_grob_property ("positions"));
+  Drul_array<Real> pos = ly_scm2interval ( me->get_property ("positions"));
 
 
-  pos  *= Staff_symbol_referencer::staff_space (me);
+  scale_drul (&pos,  Staff_symbol_referencer::staff_space (me));
   
   
-  Real dy = pos.delta();
+  Real dy = pos[RIGHT] - pos[LEFT];
   Real y = pos[LEFT];
   Real y = pos[LEFT];
-  Real dydx =dy/dx;
+  Real slope = dy/dx;
 
   
   /*
 
   
   /*
@@ -989,17 +980,17 @@ Beam::shift_region_to_valid (SCM grob)
    */
   Interval feasible_left_point;
   feasible_left_point.set_full ();
    */
   Interval feasible_left_point;
   feasible_left_point.set_full ();
-  for (int i=0; i < stems.size (); i++)
+  for (int i = 0; i < stems.size (); i++)
     {
       Grob* s = stems[i];
     {
       Grob* s = stems[i];
-      if (Stem::invisible_b (s))
+      if (Stem::is_invisible (s))
        continue;
 
       Direction d = Stem::get_direction (s);
 
       Real left_y =
        Stem::get_stem_info (s).shortest_y_
        continue;
 
       Direction d = Stem::get_direction (s);
 
       Real left_y =
        Stem::get_stem_info (s).shortest_y_
-       - dydx * x_posns [i];
+       - slope * x_posns [i];
 
       /*
        left_y is now relative to the stem S. We want relative to
 
       /*
        left_y is now relative to the stem S. We want relative to
@@ -1017,9 +1008,7 @@ Beam::shift_region_to_valid (SCM grob)
     }
       
   if (feasible_left_point.is_empty ())
     }
       
   if (feasible_left_point.is_empty ())
-    {
-      warning (_("Not sure that we can find a nice beam slope (no viable initial configuration found)."));
-    }
+    warning (_ ("no viable initial configuration found: may not find good beam slope"));
   else if (!feasible_left_point.contains (y))
     {
       if (isinf (feasible_left_point[DOWN]))
   else if (!feasible_left_point.contains (y))
     {
       if (isinf (feasible_left_point[DOWN]))
@@ -1030,138 +1019,10 @@ Beam::shift_region_to_valid (SCM grob)
        y = feasible_left_point.center ();
     }
   
        y = feasible_left_point.center ();
     }
   
-  pos = Interval (y, (y+dy));
-  pos *= 1/ Staff_symbol_referencer::staff_space (me);
+  pos = Drul_array<Real> (y, (y+dy));
+  scale_drul (&pos, 1/ Staff_symbol_referencer::staff_space (me));
   
   
-  me->set_grob_property ("positions", ly_interval2scm (pos));
-  return SCM_UNSPECIFIED;
-}
-
-
-MAKE_SCHEME_CALLBACK (Beam, check_concave, 1);
-SCM
-Beam::check_concave (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-
-  Link_array<Grob> stems = 
-    Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
-
-  for (int i = 0; i < stems.size ();)
-    {
-      if (Stem::invisible_b (stems[i]))
-       stems.del (i);
-      else
-       i++;
-    }
-  
-  if (stems.size () < 3)
-    return SCM_UNSPECIFIED;
-
-
-  /* Concaveness #1: If distance of an inner notehead to line between
-     two outer noteheads is bigger than CONCAVENESS-GAP (2.0ss),
-     beam is concave (Heinz Stolba).
-
-     In the case of knees, the line connecting outer heads is often
-     not related to the beam slope (it may even go in the other
-     direction). Skip the check when the outer stems point in
-     different directions. --hwn
-     
-  */
-  bool concaveness1 = false;
-  SCM gap = me->get_grob_property ("concaveness-gap");
-  if (gh_number_p (gap)
-      && Stem::get_direction(stems.top ())
-         == Stem::get_direction(stems[0]))
-    {
-      Real r1 = gh_scm2double (gap);
-      Real dy = Stem::chord_start_y (stems.top ())
-       - Stem::chord_start_y (stems[0]);
-
-      
-      Real slope = dy / (stems.size () - 1);
-      
-      Real y0 = Stem::chord_start_y (stems[0]);
-      for (int i = 1; i < stems.size () - 1; i++)
-       {
-         Real c = (Stem::chord_start_y (stems[i]) - y0) - i * slope;
-         if (c > r1)
-           {
-             concaveness1 = true;
-             break;
-           }
-       }
-    }
-
-    
-  /* Concaveness #2: Sum distances of inner noteheads that fall
-     outside the interval of the two outer noteheads.
-
-     We only do this for beams where first and last stem have the same
-     direction. --hwn.
-
-
-     Note that "convex" stems compensate for "concave" stems.
-     (is that intentional?) --hwn.
-  */
-  
-  Real concaveness2 = 0;
-  SCM thresh = me->get_grob_property ("concaveness-threshold");
-  Real r2 = infinity_f;
-  if (!concaveness1 && gh_number_p (thresh)
-      && Stem::get_direction(stems.top ())
-         == Stem::get_direction(stems[0]))
-    {
-      r2 = gh_scm2double (thresh);
-
-      Direction dir = Stem::get_direction(stems.top ());
-      Real concave = 0;
-      Interval iv (Stem::chord_start_y (stems[0]),
-                  Stem::chord_start_y (stems.top ()));
-      
-      if (iv[MAX] < iv[MIN])
-       iv.swap ();
-      
-      for (int i = 1; i < stems.size () - 1; i++)
-       {
-         Real f = Stem::chord_start_y (stems[i]);
-         concave += ((f - iv[MAX] ) >? 0) +
-           ((f - iv[MIN] ) <? 0);
-       }
-      concave *= dir;
-      concaveness2 = concave / (stems.size () - 2);
-      
-      /*
-
-      ugh: this is the a kludge to get
-      input/regression/beam-concave.ly to behave as
-      baerenreiter.
-
-      */
-
-      /*
-       huh? we're dividing twice (which is not scalable) meaning that
-       the longer the beam, the more unlikely it will be
-       concave. Maybe you would even expect the other way around??
-
-       --hwn.
-       
-       */
-      concaveness2 /= (stems.size () - 2);
-    }
-  
-  /* TODO: some sort of damping iso -> plain horizontal */
-  if (concaveness1 || concaveness2 > r2)
-    {
-      Interval pos = ly_scm2interval (me->get_grob_property ("positions"));
-      Real r = pos.linear_combination (0);
-
-      r /= Staff_symbol_referencer::staff_space (me);
-      me->set_grob_property ("positions", ly_interval2scm (Interval (r, r)));
-      me->set_grob_property ("least-squares-dy", gh_double2scm (0));
-    }
-
+  me->set_property ("positions", ly_interval2scm (pos));
   return SCM_UNSPECIFIED;
 }
 
   return SCM_UNSPECIFIED;
 }
 
@@ -1177,15 +1038,15 @@ Beam::slope_damping (SCM smob)
   if (visible_stem_count (me) <= 1)
     return SCM_UNSPECIFIED;
 
   if (visible_stem_count (me) <= 1)
     return SCM_UNSPECIFIED;
 
-  SCM s = me->get_grob_property ("damping"); 
-  int damping = gh_scm2int (s);
+  SCM s = me->get_property ("damping"); 
+  Real damping = scm_to_double (s);
 
   if (damping)
     {
 
   if (damping)
     {
-      Interval pos = ly_scm2interval (me->get_grob_property ("positions"));
-      pos *= Staff_symbol_referencer::staff_space (me);
+      Drul_array<Real> pos = ly_scm2interval (me->get_property ("positions"));
+      scale_drul (&pos,  Staff_symbol_referencer::staff_space (me));
       
       
-      Real dy = pos.delta ();
+      Real dy = pos[RIGHT] - pos[LEFT];
 
       Grob *fvs  = first_visible_stem (me);
       Grob *lvs  = last_visible_stem (me);
 
       Grob *fvs  = first_visible_stem (me);
       Grob *lvs  = last_visible_stem (me);
@@ -1195,16 +1056,23 @@ Beam::slope_damping (SCM smob)
 
       Real dx = last_visible_stem (me)->relative_coordinate (commonx, X_AXIS)
        - first_visible_stem (me)->relative_coordinate (commonx, X_AXIS);
 
       Real dx = last_visible_stem (me)->relative_coordinate (commonx, X_AXIS)
        - first_visible_stem (me)->relative_coordinate (commonx, X_AXIS);
-      Real dydx = dy && dx ? dy/dx : 0;
-      dydx = 0.6 * tanh (dydx) / damping;
 
 
-      Real damped_dy = dydx * dx;
+      Real slope = dy && dx ? dy/dx : 0;
+
+      Real concaveness = robust_scm2double (me->get_property ("concaveness"), 0.0);
+      
+      slope = 0.6 * tanh (slope) / (damping + concaveness);
+
+      Real damped_dy = slope * dx;
+
+      set_minimum_dy (me, &damped_dy);
+      
       pos[LEFT] += (dy - damped_dy) / 2;
       pos[RIGHT] -= (dy - damped_dy) / 2;
 
       pos[LEFT] += (dy - damped_dy) / 2;
       pos[RIGHT] -= (dy - damped_dy) / 2;
 
-      pos *= 1/ Staff_symbol_referencer::staff_space (me);
+      scale_drul (&pos, 1/Staff_symbol_referencer::staff_space (me));
       
       
-      me->set_grob_property ("positions", ly_interval2scm (pos));
+      me->set_property ("positions", ly_interval2scm (pos));
     }
   return SCM_UNSPECIFIED;
 }
     }
   return SCM_UNSPECIFIED;
 }
@@ -1214,15 +1082,15 @@ Beam::slope_damping (SCM smob)
   and (cdr BEAMING)
  */
 Slice
   and (cdr BEAMING)
  */
 Slice
-where_are_the_whole_beams(SCM beaming)
+where_are_the_whole_beams (SCM beaming)
 {
   Slice l; 
   
 {
   Slice l; 
   
-  for( SCM s = gh_car (beaming); gh_pair_p (s) ; s = gh_cdr (s))
+  for ( SCM s = scm_car (beaming); scm_is_pair (s) ; s = scm_cdr (s))
     {
     {
-      if (scm_memq (gh_car (s), gh_cdr (beaming)) != SCM_BOOL_F)
+      if (scm_c_memq (scm_car (s), scm_cdr (beaming)) != SCM_BOOL_F)
        
        
-       l.add_point (gh_scm2int (gh_car (s)));
+       l.add_point (scm_to_int (scm_car (s)));
     }
 
   return l;
     }
 
   return l;
@@ -1233,13 +1101,13 @@ where_are_the_whole_beams(SCM beaming)
 Real
 Beam::calc_stem_y (Grob *me, Grob* s, Grob ** common,
                   Real xl, Real xr,
 Real
 Beam::calc_stem_y (Grob *me, Grob* s, Grob ** common,
                   Real xl, Real xr,
-                  Interval pos, bool french) 
+                  Drul_array<Real> pos, bool french) 
 {
   Real beam_translation = get_beam_translation (me);
 
     
   Real r = s->relative_coordinate (common[X_AXIS], X_AXIS) - xl;
 {
   Real beam_translation = get_beam_translation (me);
 
     
   Real r = s->relative_coordinate (common[X_AXIS], X_AXIS) - xl;
-  Real dy = pos.delta ();
+  Real dy = pos[RIGHT] - pos[LEFT];
   Real dx = xr - xl;
   Real stem_y_beam0 = (dy && dx
                       ? r / dx
   Real dx = xr - xl;
   Real stem_y_beam0 = (dy && dx
                       ? r / dx
@@ -1247,7 +1115,7 @@ Beam::calc_stem_y (Grob *me, Grob* s, Grob ** common,
                       : 0) + pos[LEFT];
   
   Direction my_dir = get_grob_direction (s);
                       : 0) + pos[LEFT];
   
   Direction my_dir = get_grob_direction (s);
-  SCM beaming = s->get_grob_property ("beaming");
+  SCM beaming = s->get_property ("beaming");
  
   Real stem_y = stem_y_beam0;
   if (french)
  
   Real stem_y = stem_y_beam0;
   if (french)
@@ -1258,9 +1126,9 @@ Beam::calc_stem_y (Grob *me, Grob* s, Grob ** common,
     }
   else
     {
     }
   else
     {
-      Slice bm = Stem::beam_multiplicity(s);
+      Slice bm = Stem::beam_multiplicity (s);
       if (!bm.is_empty ())
       if (!bm.is_empty ())
-       stem_y +=bm[my_dir] * beam_translation;
+       stem_y += bm[my_dir] * beam_translation;
     }
   
   Real id = me->relative_coordinate (common[Y_AXIS], Y_AXIS)
     }
   
   Real id = me->relative_coordinate (common[Y_AXIS], Y_AXIS)
@@ -1276,7 +1144,7 @@ Beam::calc_stem_y (Grob *me, Grob* s, Grob ** common,
 void
 Beam::set_stem_lengths (Grob *me)
 {
 void
 Beam::set_stem_lengths (Grob *me)
 {
-  Link_array<Grob> stems=
+  Link_array<Grob> stems =
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
 
   if (!stems.size ())
     Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
 
   if (!stems.size ())
@@ -1284,19 +1152,19 @@ Beam::set_stem_lengths (Grob *me)
   
   Grob *common[2];
   for (int a = 2; a--;)
   
   Grob *common[2];
   for (int a = 2; a--;)
-    common[a] = common_refpoint_of_array (stems, me, Axis(a));
+    common[a] = common_refpoint_of_array (stems, me, Axis (a));
   
   
-  Interval pos = ly_scm2interval (me->get_grob_property ("positions"));
+  Drul_array<Real> pos = ly_scm2realdrul (me->get_property ("positions"));
   Real staff_space = Staff_symbol_referencer::staff_space (me);
   Real staff_space = Staff_symbol_referencer::staff_space (me);
-  pos  *= staff_space;
+  scale_drul (&pos,  staff_space);
 
   bool gap = false;
 
   bool gap = false;
-  Real thick =0.0;
-  if (gh_number_p (me->get_grob_property ("gap-count"))
-      &&gh_scm2int (me->get_grob_property ("gap-count")))
+  Real thick = 0.0;
+  if (scm_is_number (me->get_property ("gap-count"))
+      &&scm_to_int (me->get_property ("gap-count")))
     {
       gap = true;
     {
       gap = true;
-      thick = get_thickness(me);
+      thick = get_thickness (me);
     }
       
   // ugh -> use commonx
     }
       
   // ugh -> use commonx
@@ -1306,13 +1174,13 @@ Beam::set_stem_lengths (Grob *me)
   Real xl = fvs ? fvs->relative_coordinate (common[X_AXIS], X_AXIS) : 0.0;
   Real xr = lvs ? lvs->relative_coordinate (common[X_AXIS], X_AXIS) : 0.0;
   
   Real xl = fvs ? fvs->relative_coordinate (common[X_AXIS], X_AXIS) : 0.0;
   Real xr = lvs ? lvs->relative_coordinate (common[X_AXIS], X_AXIS) : 0.0;
   
-  for (int i=0; i < stems.size (); i++)
+  for (int i = 0; i < stems.size (); i++)
     {
       Grob* s = stems[i];
     {
       Grob* s = stems[i];
-      if (Stem::invisible_b (s))
+      if (Stem::is_invisible (s))
        continue;
 
        continue;
 
-      bool french = to_boolean (s->get_grob_property ("french-beaming"));
+      bool french = to_boolean (s->get_property ("french-beaming"));
       Real stem_y = calc_stem_y (me, s, common,
                                 xl, xr,
                                 pos, french && s != lvs && s!= fvs);
       Real stem_y = calc_stem_y (me, s, common,
                                 xl, xr,
                                 pos, french && s != lvs && s!= fvs);
@@ -1331,11 +1199,11 @@ Beam::set_stem_lengths (Grob *me)
 void
 Beam::set_beaming (Grob *me, Beaming_info_list *beaming)
 {
 void
 Beam::set_beaming (Grob *me, Beaming_info_list *beaming)
 {
-  Link_array<Grob> stems=
+  Link_array<Grob> stems =
     Pointer_group_interface__extract_grobs (me, (Grob *)0, "stems");
   
   Direction d = LEFT;
     Pointer_group_interface__extract_grobs (me, (Grob *)0, "stems");
   
   Direction d = LEFT;
-  for (int i=0; i  < stems.size (); i++)
+  for (int i = 0; i  < stems.size (); i++)
     {
       /*
        Don't overwrite user settings.
     {
       /*
        Don't overwrite user settings.
@@ -1344,20 +1212,20 @@ Beam::set_beaming (Grob *me, Beaming_info_list *beaming)
       do
        {
          /* Don't set beaming for outside of outer stems */      
       do
        {
          /* Don't set beaming for outside of outer stems */      
-         if ((d == LEFT && i == 0)
-             ||(d == RIGHT && i == stems.size () -1))
+         if ( (d == LEFT && i == 0)
+             || (d == RIGHT && i == stems.size () -1))
            continue;
 
          Grob *st =  stems[i];
            continue;
 
          Grob *st =  stems[i];
-         SCM beaming_prop = st->get_grob_property ("beaming");
+         SCM beaming_prop = st->get_property ("beaming");
          if (beaming_prop == SCM_EOL ||
              index_get_cell (beaming_prop, d) == SCM_EOL)
            {
              int b = beaming->infos_.elem (i).beams_i_drul_[d];
              if (i>0
          if (beaming_prop == SCM_EOL ||
              index_get_cell (beaming_prop, d) == SCM_EOL)
            {
              int b = beaming->infos_.elem (i).beams_i_drul_[d];
              if (i>0
-                 && i < stems.size() -1
-                 && Stem::invisible_b (st))
-               b = b <? beaming->infos_.elem(i).beams_i_drul_[-d];
+                 && i < stems.size () -1
+                 && Stem::is_invisible (st))
+               b = b <? beaming->infos_.elem (i).beams_i_drul_[-d];
              
              Stem::set_beaming (st, b, d);
            }
              
              Stem::set_beaming (st, b, d);
            }
@@ -1372,11 +1240,11 @@ Beam::forced_stem_count (Grob *me)
   Link_array<Grob>stems = 
     Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
   int f = 0;
   Link_array<Grob>stems = 
     Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
   int f = 0;
-  for (int i=0; i < stems.size (); i++)
+  for (int i = 0; i < stems.size (); i++)
     {
       Grob *s = stems[i];
 
     {
       Grob *s = stems[i];
 
-      if (Stem::invisible_b (s))
+      if (Stem::is_invisible (s))
        continue;
 
       /* I can imagine counting those boundaries as a half forced stem,
        continue;
 
       /* I can imagine counting those boundaries as a half forced stem,
@@ -1399,7 +1267,7 @@ Beam::visible_stem_count (Grob *me)
   int c = 0;
   for (int i = stems.size (); i--;)
     {
   int c = 0;
   for (int i = stems.size (); i--;)
     {
-      if (!Stem::invisible_b (stems[i]))
+      if (!Stem::is_invisible (stems[i]))
         c++;
     }
   return c;
         c++;
     }
   return c;
@@ -1413,7 +1281,7 @@ Beam::first_visible_stem (Grob *me)
   
   for (int i = 0; i < stems.size (); i++)
     {
   
   for (int i = 0; i < stems.size (); i++)
     {
-      if (!Stem::invisible_b (stems[i]))
+      if (!Stem::is_invisible (stems[i]))
         return stems[i];
     }
   return 0;
         return stems[i];
     }
   return 0;
@@ -1426,7 +1294,7 @@ Beam::last_visible_stem (Grob *me)
     Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
   for (int i = stems.size (); i--;)
     {
     Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems");
   for (int i = stems.size (); i--;)
     {
-      if (!Stem::invisible_b (stems[i]))
+      if (!Stem::is_invisible (stems[i]))
         return stems[i];
     }
   return 0;
         return stems[i];
     }
   return 0;
@@ -1448,46 +1316,51 @@ SCM
 Beam::rest_collision_callback (SCM element_smob, SCM axis)
 {
   Grob *rest = unsmob_grob (element_smob);
 Beam::rest_collision_callback (SCM element_smob, SCM axis)
 {
   Grob *rest = unsmob_grob (element_smob);
-  Axis a = (Axis) gh_scm2int (axis);
+  Axis a = (Axis) scm_to_int (axis);
 
 
-  if (gh_number_p (rest->get_grob_property ("staff-position")))
-    return gh_int2scm (0);
+  if (scm_is_number (rest->get_property ("staff-position")))
+    return scm_int2num (0);
   
   assert (a == Y_AXIS);
 
   
   assert (a == Y_AXIS);
 
-  Grob *st = unsmob_grob (rest->get_grob_property ("stem"));
+  Grob *st = unsmob_grob (rest->get_property ("stem"));
   Grob *stem = st;
   if (!stem)
   Grob *stem = st;
   if (!stem)
-    return gh_double2scm (0.0);
-  Grob *beam = unsmob_grob (stem->get_grob_property ("beam"));
+    return scm_make_real (0.0);
+  Grob *beam = unsmob_grob (stem->get_property ("beam"));
   if (!beam
       || !Beam::has_interface (beam)
       || !Beam::visible_stem_count (beam))
   if (!beam
       || !Beam::has_interface (beam)
       || !Beam::visible_stem_count (beam))
-    return gh_double2scm (0.0);
+    return scm_make_real (0.0);
 
 
-  Interval pos (0, 0);
-  SCM s = beam->get_grob_property ("positions");
-  if (gh_pair_p (s) && gh_number_p (ly_car (s)))
+  Drul_array<Real> pos (0, 0);
+  SCM s = beam->get_property ("positions");
+  if (scm_is_pair (s) && scm_is_number (scm_car (s)))
     pos = ly_scm2interval (s);
   Real staff_space = Staff_symbol_referencer::staff_space (rest);
 
     pos = ly_scm2interval (s);
   Real staff_space = Staff_symbol_referencer::staff_space (rest);
 
-  pos  *= staff_space;
+  scale_drul (&pos, staff_space);
   
 
   
 
-  Real dy = pos.delta ();
+  Real dy = pos[RIGHT] - pos[LEFT];
   
   // ugh -> use commonx
   Real x0 = first_visible_stem (beam)->relative_coordinate (0, X_AXIS);
   Real dx = last_visible_stem (beam)->relative_coordinate (0, X_AXIS) - x0;
   
   // ugh -> use commonx
   Real x0 = first_visible_stem (beam)->relative_coordinate (0, X_AXIS);
   Real dx = last_visible_stem (beam)->relative_coordinate (0, X_AXIS) - x0;
-  Real dydx = dy && dx ? dy/dx : 0;
+  Real slope = dy && dx ? dy/dx : 0;
   
   Direction d = Stem::get_direction (stem);
   
   Direction d = Stem::get_direction (stem);
-  Real stem_y = pos[LEFT] + (stem->relative_coordinate (0, X_AXIS) - x0) * dydx;
+  Real stem_y = pos[LEFT] + (stem->relative_coordinate (0, X_AXIS) - x0) * slope;
   
   Real beam_translation = get_beam_translation (beam);
   Real beam_thickness = Beam::get_thickness (beam);
   
   Real beam_translation = get_beam_translation (beam);
   Real beam_thickness = Beam::get_thickness (beam);
+
+  /*
+    TODO: this is not strictly correct for 16th knee beams. 
+   */
+  int beam_count = 
+    Stem::beam_multiplicity (stem).length() + 1;
   
   
-  int beam_count = get_direction_beam_count (beam, d);
   Real height_of_my_beams = beam_thickness / 2
     + (beam_count - 1) * beam_translation;
   Real beam_y = stem_y - d * height_of_my_beams;
   Real height_of_my_beams = beam_thickness / 2
     + (beam_count - 1) * beam_translation;
   Real beam_y = stem_y - d * height_of_my_beams;
@@ -1496,9 +1369,10 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis)
 
   Real rest_dim = rest->extent (common_y, Y_AXIS)[d];
   Real minimum_distance =
 
   Real rest_dim = rest->extent (common_y, Y_AXIS)[d];
   Real minimum_distance =
-    staff_space * robust_scm2double (rest->get_grob_property ("minimum-distance"), 0.0);
+    + staff_space * (robust_scm2double (stem->get_property ("stemlet-length"), 0.0)
+                    + robust_scm2double (rest->get_property ("minimum-distance"), 0.0));
 
 
-  Real shift = d * (((beam_y - d * minimum_distance) - rest_dim) * d  <? 0.0);
+  Real shift = d * ( ((beam_y - d * minimum_distance) - rest_dim) * d  <? 0.0);
 
   shift /= staff_space;
   Real rad = Staff_symbol_referencer::line_count (rest) * staff_space / 2;
 
   shift /= staff_space;
   Real rad = Staff_symbol_referencer::line_count (rest) * staff_space / 2;
@@ -1507,27 +1381,27 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis)
   shift = ceil (fabs (shift * 2.0)) / 2.0 * sign (shift);
 
   /* Inside staff, move by whole spaces*/
   shift = ceil (fabs (shift * 2.0)) / 2.0 * sign (shift);
 
   /* Inside staff, move by whole spaces*/
-  if ((rest->extent (common_y, Y_AXIS)[d] + staff_space * shift) * d
+  if ( (rest->extent (common_y, Y_AXIS)[d] + staff_space * shift) * d
       < rad
       || (rest->extent (common_y, Y_AXIS)[-d] + staff_space * shift) * -d
       < rad)
     shift = ceil (fabs (shift)) *sign (shift);
 
       < rad
       || (rest->extent (common_y, Y_AXIS)[-d] + staff_space * shift) * -d
       < rad)
     shift = ceil (fabs (shift)) *sign (shift);
 
-  return gh_double2scm (staff_space * shift);
+  return scm_make_real (staff_space * shift);
 }
 
 bool
 }
 
 bool
-Beam::knee_b (Grob* me)
+Beam::is_knee (Grob* me)
 {
 {
-  SCM k = me->get_grob_property ("knee");
-  if (gh_boolean_p (k))
-    return gh_scm2bool (k);
+  SCM k = me->get_property ("knee");
+  if (scm_is_bool (k))
+    return ly_scm2bool (k);
 
   bool knee = false;
   int d = 0;
 
   bool knee = false;
   int d = 0;
-  for (SCM s = me->get_grob_property ("stems"); gh_pair_p (s); s = ly_cdr (s))
+  for (SCM s = me->get_property ("stems"); scm_is_pair (s); s = scm_cdr (s))
     {
     {
-      Direction dir = get_grob_direction (unsmob_grob (ly_car (s)));
+      Direction dir = get_grob_direction (unsmob_grob (scm_car (s)));
       if (d && d != dir)
        {
          knee = true;
       if (d && d != dir)
        {
          knee = true;
@@ -1536,7 +1410,7 @@ Beam::knee_b (Grob* me)
       d = dir;
     }
   
       d = dir;
     }
   
-  me->set_grob_property ("knee", gh_bool2scm (knee));
+  me->set_property ("knee", ly_bool2scm (knee));
 
   return knee;
 }
 
   return knee;
 }
@@ -1562,22 +1436,14 @@ Beam::get_direction_beam_count (Grob *me, Direction d )
 
 
 ADD_INTERFACE (Beam, "beam-interface",
 
 
 ADD_INTERFACE (Beam, "beam-interface",
-  "A beam. \n\n"
-" "
-"#'thickness= weight of beams, in staffspace "
-" "
-" "
-"We take the least squares line through the ideal-length stems, and "
-"then damp that using "
-" \n"
-"      damped = tanh (slope) \n"
-" \n"
-"this gives an unquantized left and right position for the beam end. "
-"Then we take all combinations of quantings near these left and right "
-"positions, and give them a score (according to how close they are to "
-"the ideal slope, how close the result is to the ideal stems, etc.). We "
-"take the best scoring combination. "
-,
-  "knee positioning-done position-callbacks concaveness-gap concaveness-threshold dir-function quant-score auto-knee-gap gap gap-count chord-tremolo beamed-stem-shorten shorten least-squares-dy damping flag-width-function neutral-direction positions space-function thickness");
+              "A beam. \n\n"
+              "The @code{thickness} property is the weight of beams, and is measured "
+              "in  staffspace"
+              ,
+              "knee positioning-done position-callbacks "
+              "concaveness dir-function quant-score auto-knee-gap gap "
+              "gap-count chord-tremolo beamed-stem-shorten shorten least-squares-dy "
+              "damping inspect-quants flag-width-function neutral-direction positions space-function "
+              "thickness");