From 11aa60835d836fdc3ca4318b32d0c5261c8cd50a Mon Sep 17 00:00:00 2001
From: hanwen <hanwen>
Date: Wed, 2 Nov 2005 00:33:24 +0000
Subject: [PATCH] * lily/rest.cc (y_offset_callback): merge function of 3
 callbacks.

* lily/grob.cc (y_parent_positioning): remove axis argument from
parent_positioning callbacks.
(Grob): junk init code
(get_offset): use generic property callbacks for
X-offset, Y-offset. Remove Grob::{add,has}_offset_callback.
(axis_parent_positioning): new function
(axis_offset_symbol): new function
(chain_offset_callback): new function
(add_offset_callback): new function

* lily/beam.cc (rest_collision_callback): change signature; this
is now a chained callback.

* lily/include/dimension-cache.hh (class Dimension_cache): remove
callback administration.

* lily/simple-closure.cc: new file. Smob type that allows "grob"
member functions

* lily/slur-engraver.cc (acknowledge_extra_object): use chained
callbacks.

* lily/slur.cc (outside_slur_callback): take 2 arguments.

* lily/rest.cc (polyphonic_offset_callback): remove.

* lily/script-engraver.cc (try_music): remove bool* argument.

* scm/script.scm (default-script-alist): set quantize-position
appropriately.

* lily/script-engraver.cc: remove follow_into_staff_ special coding.

* lily/side-position-interface.cc (aligned_side): move staff
position quantization from
Side_position_interface::quantised_position().
(quantised_position): remove
---
 ChangeLog                                |  47 +++++
 lily/accidental-placement.cc             |   2 +-
 lily/align-interface.cc                  |   7 +-
 lily/beam-engraver.cc                    |   5 +-
 lily/beam.cc                             |  24 +--
 lily/break-align-interface.cc            |  16 +-
 lily/breathing-sign.cc                   |   6 +-
 lily/dimension-cache.cc                  |   9 +-
 lily/dot-column.cc                       |  21 +--
 lily/drum-note-engraver.cc               |   7 +-
 lily/dynamic-engraver.cc                 |   4 +-
 lily/figured-bass-continuation.cc        |   8 +-
 lily/fingering-engraver.cc               |   8 +-
 lily/grid-line-interface.cc              |   4 +-
 lily/grob-property.cc                    |  13 +-
 lily/grob-smob.cc                        |  18 +-
 lily/grob.cc                             | 214 ++++++++++++++---------
 lily/hara-kiri-group-spanner.cc          |   9 +-
 lily/include/accidental-placement.hh     |   2 +-
 lily/include/align-interface.hh          |   2 -
 lily/include/beam.hh                     |   2 +-
 lily/include/break-align-interface.hh    |   2 +-
 lily/include/breathing-sign.hh           |   2 +-
 lily/include/dimension-cache.hh          |   5 +-
 lily/include/dot-column.hh               |   3 +-
 lily/include/grob.hh                     |  15 +-
 lily/include/misc.hh                     |   2 +
 lily/include/note-collision.hh           |   1 -
 lily/include/note-head.hh                |   2 +-
 lily/include/rest-collision.hh           |   4 +-
 lily/include/rest.hh                     |   5 +-
 lily/include/script-interface.hh         |   2 +-
 lily/include/self-alignment-interface.hh |  17 +-
 lily/include/side-position-interface.hh  |   8 +-
 lily/include/simple-closure.hh           |  18 ++
 lily/include/span-bar.hh                 |   2 +-
 lily/include/staff-symbol-referencer.hh  |   2 +-
 lily/include/stem-tremolo.hh             |   2 +-
 lily/include/stem.hh                     |   2 +-
 lily/misc.cc                             |  11 ++
 lily/new-fingering-engraver.cc           |  30 ++--
 lily/note-collision.cc                   |   2 +-
 lily/note-head.cc                        |   6 +-
 lily/phrasing-slur-engraver.cc           |   3 +-
 lily/rest-collision.cc                   |  23 +--
 lily/rest.cc                             |  52 +++---
 lily/script-column.cc                    |   4 +-
 lily/script-engraver.cc                  |  20 +--
 lily/self-aligment-interface.cc          | 124 +++++++------
 lily/side-position-interface.cc          | 179 +++++++++----------
 lily/simple-closure.cc                   | 106 +++++++++++
 lily/slur-engraver.cc                    |   4 +-
 lily/slur.cc                             |  20 +--
 lily/span-bar.cc                         |   8 +-
 lily/staff-symbol-referencer.cc          |  17 +-
 lily/stem-tremolo.cc                     |   4 +-
 lily/stem.cc                             |   6 +-
 scm/define-grobs.scm                     | 163 ++++++++---------
 scm/safe-lily.scm                        |   7 -
 scm/script.scm                           |  12 +-
 60 files changed, 755 insertions(+), 568 deletions(-)
 create mode 100644 lily/include/simple-closure.hh
 create mode 100644 lily/simple-closure.cc

diff --git a/ChangeLog b/ChangeLog
index a21300fa51..2a1be0aa19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,50 @@
+2005-11-02  Han-Wen Nienhuys  <hanwen@xs4all.nl>
+
+	* lily/rest.cc (y_offset_callback): merge function of 3 callbacks. 
+
+	* lily/grob.cc (y_parent_positioning): remove axis argument from
+	parent_positioning callbacks.
+	(Grob): junk init code
+	(get_offset): use generic property callbacks for
+	X-offset, Y-offset. Remove Grob::{add,has}_offset_callback.
+	(axis_parent_positioning): new function
+	(axis_offset_symbol): new function
+	(chain_offset_callback): new function
+	(add_offset_callback): new function
+
+	* lily/beam.cc (rest_collision_callback): change signature; this
+	is now a chained callback.
+
+	* lily/include/dimension-cache.hh (class Dimension_cache): remove
+	callback administration.
+
+	* lily/simple-closure.cc: new file. Smob type that allows "grob"
+	member functions
+
+	    (ly:make-simple-closure FUNC A B)
+
+	is evaluated as (FUNC grob A B). This allows chaining of callbacks
+	in various ways.
+
+	* lily/slur-engraver.cc (acknowledge_extra_object): use chained
+	callbacks.
+
+	* lily/slur.cc (outside_slur_callback): take 2 arguments.
+
+	* lily/rest.cc (polyphonic_offset_callback): remove.
+
+	* lily/script-engraver.cc (try_music): remove bool* argument.
+
+	* scm/script.scm (default-script-alist): set quantize-position
+	appropriately.
+
+	* lily/script-engraver.cc: remove follow_into_staff_ special coding. 
+
+	* lily/side-position-interface.cc (aligned_side): move staff
+	position quantization from
+	Side_position_interface::quantised_position().
+	(quantised_position): remove
+	
 2005-10-31  Han-Wen Nienhuys  <hanwen@xs4all.nl>
 
 	* input/regression/beam-quant-standard.ly: reindent, set
diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc
index 52cf9cc5ff..efe51e6725 100644
--- a/lily/accidental-placement.cc
+++ b/lily/accidental-placement.cc
@@ -23,7 +23,7 @@ void
 Accidental_placement::add_accidental (Grob *me, Grob *a)
 {
   a->set_parent (me, X_AXIS);
-  a->add_offset_callback (Grob::same_axis_parent_positioning_proc, X_AXIS);
+  a->set_property ("X-offset", Grob::x_parent_positioning_proc);
   SCM cause = a->get_parent (Y_AXIS)->get_property ("cause");
 
   Music *mcause = unsmob_music (cause);
diff --git a/lily/align-interface.cc b/lily/align-interface.cc
index 034f6d58d5..297a7ecc69 100644
--- a/lily/align-interface.cc
+++ b/lily/align-interface.cc
@@ -263,8 +263,11 @@ Align_interface::axis (Grob *me)
 void
 Align_interface::add_element (Grob *me, Grob *element)
 {
-  element->add_offset_callback (Grob::same_axis_parent_positioning_proc,
-				Align_interface::axis (me));
+  Axis a = Align_interface::axis (me);
+  SCM sym = axis_offset_symbol (a);
+  SCM proc = axis_parent_positioning (a);
+    
+  element->internal_set_property (sym, proc);
   Axis_group_interface::add_element (me, element);
 }
 
diff --git a/lily/beam-engraver.cc b/lily/beam-engraver.cc
index 9f4fa955a5..9b4e01a139 100644
--- a/lily/beam-engraver.cc
+++ b/lily/beam-engraver.cc
@@ -215,7 +215,10 @@ void
 Beam_engraver::acknowledge_rest (Grob_info info)
 {
   if (beam_)
-    info.grob ()->add_offset_callback (Beam::rest_collision_callback_proc, Y_AXIS);
+    {
+      chain_offset_callback (info.grob(),
+			     Beam::rest_collision_callback_proc, Y_AXIS);
+    }
 }
 
 void
diff --git a/lily/beam.cc b/lily/beam.cc
index 9cd5793264..591af1a147 100644
--- a/lily/beam.cc
+++ b/lily/beam.cc
@@ -1254,16 +1254,14 @@ Beam::last_visible_stem (Grob *me)
 */
 MAKE_SCHEME_CALLBACK (Beam, rest_collision_callback, 2);
 SCM
-Beam::rest_collision_callback (SCM element_smob, SCM axis)
+Beam::rest_collision_callback (SCM smob, SCM prev_offset)
 {
-  Grob *rest = unsmob_grob (element_smob);
-  (void) axis;
-
+  Grob *rest = unsmob_grob (smob);
   if (scm_is_number (rest->get_property ("staff-position")))
     return scm_from_int (0);
 
-  assert (scm_to_int (axis) == Y_AXIS);
-
+  Real offset = robust_scm2double (prev_offset, 0.0);
+  
   Grob *st = unsmob_grob (rest->get_object ("stem"));
   Grob *stem = st;
   if (!stem)
@@ -1309,11 +1307,13 @@ Beam::rest_collision_callback (SCM element_smob, SCM axis)
   Real beam_y = stem_y - d * height_of_my_beams;
 
   Grob *common_y = rest->common_refpoint (beam, Y_AXIS);
-
-  Real rest_dim = rest->extent (common_y, Y_AXIS)[d];
+  Interval rest_extent = rest->extent (common_y, Y_AXIS);
+  rest_extent.translate (offset);
+  
+  Real rest_dim = rest_extent[d];
   Real minimum_distance
-    = + staff_space * (robust_scm2double (stem->get_property ("stemlet-length"), 0.0)
-		       + robust_scm2double (rest->get_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 * min (((beam_y - d * minimum_distance) - rest_dim) * d, 0.0);
 
@@ -1324,9 +1324,9 @@ 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*/
-  if ((rest->extent (common_y, Y_AXIS)[d] + staff_space * shift) * d
+  if ((rest_extent[d] + staff_space * shift) * d
       < rad
-      || (rest->extent (common_y, Y_AXIS)[-d] + staff_space * shift) * -d
+      || (rest_extent[-d] + staff_space * shift) * -d
       < rad)
     shift = ceil (fabs (shift)) * sign (shift);
 
diff --git a/lily/break-align-interface.cc b/lily/break-align-interface.cc
index 1d82c0622a..4fe1e195f0 100644
--- a/lily/break-align-interface.cc
+++ b/lily/break-align-interface.cc
@@ -20,13 +20,11 @@
 #include "align-interface.hh"
 
 
-MAKE_SCHEME_CALLBACK (Break_align_interface, self_align_callback, 2);
+MAKE_SCHEME_CALLBACK (Break_align_interface, self_align_callback, 1);
 SCM
-Break_align_interface::self_align_callback (SCM element_smob, SCM axis)
+Break_align_interface::self_align_callback (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
-  (void) axis;
-  assert (scm_to_int (axis) == X_AXIS);
+  Grob *me = unsmob_grob (smob);
 
   Item *item = dynamic_cast<Item *> (me);
   Direction bsd = item->break_status_dir ();
@@ -36,7 +34,7 @@ Break_align_interface::self_align_callback (SCM element_smob, SCM axis)
   /*
     Force break alignment itself to be done first, in the case
   */
-  return Self_alignment_interface::aligned_on_self (element_smob, axis);
+  return Self_alignment_interface::aligned_on_self (me, X_AXIS);
 }
 
 /*
@@ -276,7 +274,11 @@ ADD_INTERFACE (Break_aligned_interface, "break-aligned-interface",
 	       "\n"
 	       "Rules for this spacing are much more complicated than this. \n"
 	       "See [Wanske] page 126 -- 134, [Ross] pg 143 -- 147\n",
-	       "break-align-symbol space-alist");
+
+	       /* properties */ 
+	       "break-align-symbol "
+	       "space-alist "
+	       );
 
 ADD_INTERFACE (Break_align_interface, "break-alignment-interface",
 	       "The object that performs break aligment. See @ref{break-aligned-interface}.",
diff --git a/lily/breathing-sign.cc b/lily/breathing-sign.cc
index ac24dcb7de..fc873d567d 100644
--- a/lily/breathing-sign.cc
+++ b/lily/breathing-sign.cc
@@ -160,11 +160,11 @@ Breathing_sign::finalis (SCM smob)
   return line1.smobbed_copy ();
 }
 
-MAKE_SCHEME_CALLBACK (Breathing_sign, offset_callback, 2);
+MAKE_SCHEME_CALLBACK (Breathing_sign, offset_callback, 1);
 SCM
-Breathing_sign::offset_callback (SCM element_smob, SCM)
+Breathing_sign::offset_callback (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
+  Grob *me = unsmob_grob (smob);
 
   Direction d = get_grob_direction (me);
   if (!d)
diff --git a/lily/dimension-cache.cc b/lily/dimension-cache.cc
index 749b8aca13..12fb2906e9 100644
--- a/lily/dimension-cache.cc
+++ b/lily/dimension-cache.cc
@@ -14,9 +14,7 @@
 Dimension_cache::Dimension_cache (Dimension_cache const &d)
 {
   init ();
-  offset_ = d.offset_;
-  offset_callbacks_ = d.offset_callbacks_;
-  offsets_left_ = d.offsets_left_;
+  offset_ = d.offset_ ? new Real (*d.offset_) : 0;
   parent_ = d.parent_;
   extent_ = d.extent_ ? new Interval (*d.extent_) : 0;
 }
@@ -29,9 +27,7 @@ Dimension_cache::Dimension_cache ()
 void
 Dimension_cache::init ()
 {
-  offsets_left_ = 0;
-  offset_callbacks_ = SCM_EOL;
-  offset_ = 0.0;
+  offset_ = 0;
   extent_ = 0;
   parent_ = 0;
 }
@@ -39,4 +35,5 @@ Dimension_cache::init ()
 Dimension_cache::~Dimension_cache ()
 {
   delete extent_;
+  delete offset_;
 }
diff --git a/lily/dot-column.cc b/lily/dot-column.cc
index 6a1cc7ef02..d551e2766f 100644
--- a/lily/dot-column.cc
+++ b/lily/dot-column.cc
@@ -26,14 +26,11 @@ using namespace std;
   TODO: let Dot_column communicate with stem via Note_column.
 */
 
-MAKE_SCHEME_CALLBACK (Dot_column, side_position, 2);
+MAKE_SCHEME_CALLBACK (Dot_column, side_position, 1);
 SCM
-Dot_column::side_position (SCM element_smob, SCM axis)
+Dot_column::side_position (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
-  (void) axis;
-  assert (scm_to_int (axis) == X_AXIS);
-
+  Grob *me = unsmob_grob (smob);
   Grob *stem = unsmob_grob (me->get_object ("stem"));
   if (stem
       && !Stem::get_beam (stem)
@@ -48,7 +45,7 @@ Dot_column::side_position (SCM element_smob, SCM axis)
       stem->get_property ("stem-end-position");
     }
   
-  return Side_position_interface::aligned_side (element_smob, axis);
+  return Side_position_interface::x_aligned_side (smob);
 }
 
 struct Dot_position
@@ -263,8 +260,12 @@ Dot_column::calc_positioning_done (SCM smob)
 
   for (Dot_configuration::const_iterator i (cfg.begin ());
        i != cfg.end (); i++)
-    Staff_symbol_referencer::set_position (i->second.dot_, i->first);
-
+    {
+      /*
+	Junkme?
+       */
+      Staff_symbol_referencer::set_position (i->second.dot_, i->first);
+    }
   return SCM_BOOL_T;
 }
 
@@ -277,7 +278,7 @@ Dot_column::add_head (Grob *me, Grob *rh)
       Side_position_interface::add_support (me, rh);
 
       Pointer_group_interface::add_grob (me, ly_symbol2scm ("dots"), d);
-      d->add_offset_callback (Grob::other_axis_parent_positioning_proc, Y_AXIS);
+      d->set_property ("Y-offset", Grob::x_parent_positioning_proc);
       Axis_group_interface::add_element (me, d);
     }
 }
diff --git a/lily/drum-note-engraver.cc b/lily/drum-note-engraver.cc
index 4e785658b7..fb37fae43b 100644
--- a/lily/drum-note-engraver.cc
+++ b/lily/drum-note-engraver.cc
@@ -103,14 +103,9 @@ Drum_notes_engraver::process_music ()
 	  if (scm_is_string (script))
 	    {
 	      Item *p = make_item ("Script", ev->self_scm ());
-	      bool follow;
-	      make_script_from_event (p, &follow,
-				      context (), script,
+	      make_script_from_event (p, context (), script,
 				      0);
 
-	      if (p->get_property ("follow-into-staff"))
-		p->set_property ("staff-padding", SCM_EOL);
-
 	      p->set_parent (note, Y_AXIS);
 	      Side_position_interface::add_support (p, note);
 	      scripts_.push (p);
diff --git a/lily/dynamic-engraver.cc b/lily/dynamic-engraver.cc
index b6021539d2..3a0d5ba042 100644
--- a/lily/dynamic-engraver.cc
+++ b/lily/dynamic-engraver.cc
@@ -398,8 +398,8 @@ Dynamic_engraver::acknowledge_note_column (Grob_info info)
 	{
 	  Grob *head = heads[0];
 	  script_->set_parent (head, X_AXIS);
-	  script_->add_offset_callback (Self_alignment_interface::centered_on_parent_proc,
-					X_AXIS);
+	  script_->set_property ("self-X-offset",
+				 Self_alignment_interface::centered_on_x_parent_proc);
 	}
     }
 
diff --git a/lily/figured-bass-continuation.cc b/lily/figured-bass-continuation.cc
index 4001dc5f26..c7018f6228 100644
--- a/lily/figured-bass-continuation.cc
+++ b/lily/figured-bass-continuation.cc
@@ -25,16 +25,14 @@ struct Figured_bass_continuation
   
 public:
   DECLARE_SCHEME_CALLBACK(print, (SCM));
-  DECLARE_SCHEME_CALLBACK(center_on_figures, (SCM, SCM));
+  DECLARE_SCHEME_CALLBACK(center_on_figures, (SCM));
 };
 
-MAKE_SCHEME_CALLBACK (Figured_bass_continuation, center_on_figures, 2);
+MAKE_SCHEME_CALLBACK (Figured_bass_continuation, center_on_figures, 1);
 SCM
-Figured_bass_continuation::center_on_figures (SCM grob, SCM axis)
+Figured_bass_continuation::center_on_figures (SCM grob)
 {
   Spanner *me = dynamic_cast<Spanner*> (unsmob_grob (grob));
-  (void) axis;
-  
   extract_grob_set (me, "figures", figures);
   if (figures.is_empty ())
     return scm_from_double (0.0);
diff --git a/lily/fingering-engraver.cc b/lily/fingering-engraver.cc
index 715179e41e..0997b19a0f 100644
--- a/lily/fingering-engraver.cc
+++ b/lily/fingering-engraver.cc
@@ -75,8 +75,6 @@ void
 Fingering_engraver::make_script (Direction d, Music *r, int i)
 {
   Item *fingering = make_item ("Fingering", r->self_scm ());
-  Axis a = Y_AXIS;
-  Axis other = other_axis (a);
 
   /*
     Huh, what's this for? --hwn.
@@ -91,9 +89,9 @@ Fingering_engraver::make_script (Direction d, Music *r, int i)
     We can't fold these definitions into define-grobs since
     fingerings for chords need different settings.
   */
-  Side_position_interface::set_axis (fingering, a);
-  fingering->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, other);
-  fingering->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, other);
+  Side_position_interface::set_axis (fingering, Y_AXIS);
+  fingering->set_property ("self-X-offset", Self_alignment_interface::x_aligned_on_self_proc);
+  fingering->set_property ("X-offset", Self_alignment_interface::centered_on_x_parent_proc);
 
   // Hmm
   int priority = 200;
diff --git a/lily/grid-line-interface.cc b/lily/grid-line-interface.cc
index a346d425d0..5661e1dfbe 100644
--- a/lily/grid-line-interface.cc
+++ b/lily/grid-line-interface.cc
@@ -51,9 +51,9 @@ Grid_line_interface::print (SCM smobbed_me)
 
 MAKE_SCHEME_CALLBACK (Grid_line_interface, width, 1);
 SCM
-Grid_line_interface::width (SCM element_smob)
+Grid_line_interface::width (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
+  Grob *me = unsmob_grob (smob);
 
   Real staffline = me->get_layout ()->get_dimension (ly_symbol2scm ("linethickness"));
   Real thick = robust_scm2double (me->get_property ("thickness"), 1.0)
diff --git a/lily/grob-property.cc b/lily/grob-property.cc
index e1d0446d7f..3df536b42d 100644
--- a/lily/grob-property.cc
+++ b/lily/grob-property.cc
@@ -16,6 +16,7 @@
 #include "item.hh"
 #include "program-option.hh"
 #include "profile.hh"
+#include "simple-closure.hh"
 
 SCM
 Grob::get_property_alist_chain (SCM def) const
@@ -100,7 +101,9 @@ SCM
 Grob::internal_get_property (SCM sym) const
 {
   SCM val = get_property_data (sym);
-  if (ly_is_procedure (val) || is_callback_chain (val))
+  if (ly_is_procedure (val)
+      || is_callback_chain (val)
+      || is_simple_closure (val))
     {
       val = ((Grob*)this)->try_callback (sym, val);
     }
@@ -141,9 +144,11 @@ Grob::try_callback (SCM sym, SCM proc)
 	  value = scm_call_2  (scm_car (s), self_scm (), value);
 	}
     }
-  else
-    assert (false);
-  
+  else if (is_simple_closure (proc))
+    {
+      value = evaluate_with_simple_closure (self_scm (),
+					    simple_closure_expression (proc));
+    }
 #ifndef NDEBUG
   if (debug_property_callbacks)
     grob_property_callback_stack = scm_cdr (grob_property_callback_stack);
diff --git a/lily/grob-smob.cc b/lily/grob-smob.cc
index 15593b353a..aa0956e567 100644
--- a/lily/grob-smob.cc
+++ b/lily/grob-smob.cc
@@ -24,17 +24,13 @@ Grob::mark_smob (SCM ses)
 
   if (s->key_)
     scm_gc_mark (s->key_->self_scm ());
-  for (int a = 0; a < 2; a++)
-    {
-      scm_gc_mark (s->dim_cache_[a].offset_callbacks_);
-
-      /* Do not mark the parents.  The pointers in the mutable
-	 property list form two tree like structures (one for X
-	 relations, one for Y relations).  Marking these can be done
-	 in limited stack space.  If we add the parents, we will jump
-	 between X and Y in an erratic manner, leading to much more
-	 recursion depth (and core dumps if we link to pthreads).  */
-    }
+
+  /* Do not mark the parents.  The pointers in the mutable
+     property list form two tree like structures (one for X
+     relations, one for Y relations).  Marking these can be done
+     in limited stack space.  If we add the parents, we will jump
+     between X and Y in an erratic manner, leading to much more
+     recursion depth (and core dumps if we link to pthreads).  */
 
   if (s->original_)
     scm_gc_mark (s->original_->self_scm ());
diff --git a/lily/grob.cc b/lily/grob.cc
index 9c2b19ca54..89be56aa19 100644
--- a/lily/grob.cc
+++ b/lily/grob.cc
@@ -28,36 +28,35 @@
 #include "ly-smobs.icc"
 #include "output-def.hh"
 
-MAKE_SCHEME_CALLBACK(Grob, same_axis_parent_positioning, 2);
+
+
+
+MAKE_SCHEME_CALLBACK(Grob, y_parent_positioning, 1);
 SCM
-Grob::same_axis_parent_positioning (SCM element_smob, SCM axis)
+Grob::y_parent_positioning (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
-  Axis ax = Axis (scm_to_int (axis));
-  
-  Grob *par = me->get_parent (ax);
+  Grob *me = unsmob_grob (smob);
+  Grob *par = me->get_parent (Y_AXIS);
   if (par)
-    par->get_property ("positioning-done");
+    (void) par->get_property ("positioning-done");
 
   return scm_from_double (0.0);
 }
 
-MAKE_SCHEME_CALLBACK(Grob,other_axis_parent_positioning, 2);
+
+MAKE_SCHEME_CALLBACK(Grob, x_parent_positioning, 1);
 SCM
-Grob::other_axis_parent_positioning (SCM element_smob, SCM axis)
+Grob::x_parent_positioning (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
-  Axis ax = other_axis ((Axis) scm_to_int (axis));
+  Grob *me = unsmob_grob (smob);
   
-  Grob *par = me->get_parent (ax);
+  Grob *par = me->get_parent (X_AXIS);
   if (par)
-    par->get_property ("positioning-done");
+    (void) par->get_property ("positioning-done");
 
   return scm_from_double (0.0);
 }
 
-
-
 Grob *
 Grob::clone (int count) const
 {
@@ -99,33 +98,6 @@ Grob::Grob (SCM basicprops,
   SCM meta = get_property ("meta");
   if (scm_is_pair (meta))
     interfaces_ = scm_cdr (scm_assq (ly_symbol2scm ("interfaces"), meta));
-
-  /* TODO:
-
-  - destill this into a function, so we can re-init the immutable
-  properties with a new BASICPROPS value after
-  creation. Convenient eg. when using \override with
-  StaffSymbol.  */
-
-  SCM off_callbacks[] = {
-    get_property ("X-offset-callbacks"),
-    get_property ("Y-offset-callbacks")
-  };
-
-  for (int a = X_AXIS; a <= Y_AXIS; a++)
-    {
-      SCM l = off_callbacks[a];
-
-      if (scm_ilength (l) >= 0)
-	{
-	  dim_cache_[a].offset_callbacks_ = l;
-	  dim_cache_[a].offsets_left_ = scm_ilength (l);
-	}
-      else
-	programming_error ("[XY]-offset-callbacks must be a list");
-
-    }
-
   
   if (get_property_data (ly_symbol2scm ("X-extent")) == SCM_EOL)
     set_property ("X-extent", Grob::stencil_width_proc);
@@ -159,17 +131,17 @@ Grob::~Grob ()
 
 MAKE_SCHEME_CALLBACK (Grob, stencil_height, 1);
 SCM
-Grob::stencil_height (SCM element_smob)
+Grob::stencil_height (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
+  Grob *me = unsmob_grob (smob);
   return stencil_extent (me, Y_AXIS);
 }
 
 MAKE_SCHEME_CALLBACK (Grob, stencil_width, 1);
 SCM
-Grob::stencil_width (SCM element_smob)
+Grob::stencil_width (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
+  Grob *me = unsmob_grob (smob);
   return stencil_extent (me, X_AXIS);
 }
 
@@ -310,12 +282,6 @@ Grob::suicide ()
   object_alist_ = SCM_EOL;
   immutable_property_alist_ = SCM_EOL;
   interfaces_ = SCM_EOL;
-
-  for (int a = X_AXIS; a <= Y_AXIS; a++)
-    {
-      dim_cache_[a].offset_callbacks_ = SCM_EOL;
-      dim_cache_[a].offsets_left_ = 0;
-    }
 }
 
 void
@@ -342,9 +308,15 @@ void
 Grob::translate_axis (Real y, Axis a)
 {
   if (isinf (y) || isnan (y))
-    programming_error (_ (INFINITY_MSG));
+    {
+      programming_error (_ (INFINITY_MSG));
+      return ;
+    }
+  
+  if (!dim_cache_[a].offset_)
+    dim_cache_[a].offset_ = new Real (y);
   else
-    dim_cache_[a].offset_ += y;
+    *dim_cache_[a].offset_ += y;  
 }
 
 /* Find the offset relative to D.  If D equals THIS, then it is 0.
@@ -372,24 +344,27 @@ Grob::relative_coordinate (Grob const *refp, Axis a) const
 Real
 Grob::get_offset (Axis a) const
 {
+  if (dim_cache_[a].offset_)
+    return *dim_cache_[a].offset_;
+
   Grob *me = (Grob *) this;
-  while (dim_cache_[a].offsets_left_)
-    {
-      int l = --me->dim_cache_[a].offsets_left_;
-      SCM cb = scm_list_ref (dim_cache_[a].offset_callbacks_, scm_from_int (l));
-      SCM retval = scm_call_2 (cb, self_scm (), scm_from_int (a));
 
-      Real r = scm_to_double (retval);
-      if (isinf (r) || isnan (r))
-	{
-	  programming_error (INFINITY_MSG);
-	  r = 0.0;
-	}
-      me->dim_cache_[a].offset_ += r;
-    }
-  return dim_cache_[a].offset_;
-}
+  me->dim_cache_[a].offset_ = new Real (0.0);
+  Real off = robust_scm2double (internal_get_property (axis_offset_symbol (a)), 0.0);
 
+  SCM self_off_sym
+    = (a == X_AXIS)
+    ? ly_symbol2scm ("self-X-offset")
+    : ly_symbol2scm ("self-Y-offset");
+
+  off += robust_scm2double (internal_get_property (self_off_sym), 0.0);
+  
+  *me->dim_cache_[a].offset_ += off;
+
+  me->del_property (self_off_sym);
+  me->del_property (axis_offset_symbol (a));
+  return off;
+}
 
 void
 Grob::flush_extent_cache (Axis axis)
@@ -501,23 +476,6 @@ Grob::name () const
   return scm_is_symbol (nm) ? ly_symbol2string (nm) : this->class_name ();
 }
 
-void
-Grob::add_offset_callback (SCM cb, Axis a)
-{
-  if (!has_offset_callback (cb, a))
-    {
-      dim_cache_[a].offset_callbacks_
-	= scm_cons (cb, dim_cache_[a].offset_callbacks_);
-      dim_cache_[a].offsets_left_++;
-    }
-}
-
-bool
-Grob::has_offset_callback (SCM cb, Axis a) const
-{
-  return scm_c_memq (cb, dim_cache_[a].offset_callbacks_) != SCM_BOOL_F;
-}
-
 void
 Grob::set_parent (Grob *g, Axis a)
 {
@@ -696,3 +654,87 @@ ADD_INTERFACE (Grob, "grob-interface",
 	       );
 
 
+#include "simple-closure.hh"
+
+/*
+  UGH : todo -> to different file.
+ */
+
+SCM
+axis_offset_symbol (Axis a)
+{
+  return a == X_AXIS
+    ? ly_symbol2scm ("X-offset")
+    : ly_symbol2scm ("Y-offset");
+}
+
+SCM
+axis_parent_positioning (Axis a)
+{
+  return (a == X_AXIS)
+    ? Grob::x_parent_positioning_proc
+    : Grob::y_parent_positioning_proc;
+}
+
+
+
+/*
+  Replace
+
+  (orig-proc GROB)
+
+  by
+
+  (+ (PROC GROB) (orig-proc GROB))
+  
+*/
+void
+add_offset_callback (Grob *g, SCM proc, Axis a)
+{
+  SCM data = g->get_property_data (axis_offset_symbol (a));
+
+  if (ly_is_procedure (data))
+    data = ly_make_simple_closure (scm_list_1  (data));
+  else if (is_simple_closure (data))
+    data = simple_closure_expression (data);
+  else if (!scm_is_number (data))
+    data = scm_from_int (0);
+
+  SCM plus = ly_lily_module_constant ("+");
+  SCM expr = scm_list_3 (plus,
+			 ly_make_simple_closure (scm_list_1 (proc)),
+			 data);
+  g->internal_set_property (axis_offset_symbol (a),
+			    ly_make_simple_closure (expr));
+}
+
+
+/*
+  replace
+
+  (orig-proc GROB)
+
+  by
+
+  (PROC GROB (orig-proc GROB)) 
+
+*/
+void
+chain_offset_callback (Grob *g, SCM proc, Axis a)
+{
+  SCM data = g->get_property_data (axis_offset_symbol (a));
+
+  if (ly_is_procedure (data))
+    data = ly_make_simple_closure (scm_list_1  (data));
+  else if (is_simple_closure (data))
+    data = simple_closure_expression (data);
+  else if (!scm_is_number (data))
+    data = scm_from_int (0);
+  
+  SCM expr = scm_list_2 (proc, data);
+  g->internal_set_property (axis_offset_symbol (a),
+			    
+			    // twice: one as a wrapper for grob property routines,
+			    // once for the actual delayed binding. 
+			    ly_make_simple_closure (ly_make_simple_closure (expr)));
+}
diff --git a/lily/hara-kiri-group-spanner.cc b/lily/hara-kiri-group-spanner.cc
index 1fc7edc6dd..3e2417f8eb 100644
--- a/lily/hara-kiri-group-spanner.cc
+++ b/lily/hara-kiri-group-spanner.cc
@@ -18,9 +18,9 @@
 
 MAKE_SCHEME_CALLBACK (Hara_kiri_group_spanner, y_extent, 1);
 SCM
-Hara_kiri_group_spanner::y_extent (SCM element_smob)
+Hara_kiri_group_spanner::y_extent (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
+  Grob *me = unsmob_grob (smob);
   consider_suicide (me);
   return Axis_group_interface::generic_group_extent (me, Y_AXIS);
 }
@@ -72,9 +72,9 @@ Hara_kiri_group_spanner::force_hara_kiri_callback (SCM smob, SCM axis)
 
 MAKE_SCHEME_CALLBACK (Hara_kiri_group_spanner, force_hara_kiri_in_parent_callback, 2);
 SCM
-Hara_kiri_group_spanner::force_hara_kiri_in_parent_callback (SCM element_smob, SCM axis)
+Hara_kiri_group_spanner::force_hara_kiri_in_parent_callback (SCM smob, SCM axis)
 {
-  Grob *daughter = unsmob_grob (element_smob);
+  Grob *daughter = unsmob_grob (smob);
   Axis a = (Axis) scm_to_int (axis);
   assert (a == Y_AXIS);
   force_hara_kiri_callback (daughter->get_parent (a)->self_scm (), axis);
@@ -84,7 +84,6 @@ Hara_kiri_group_spanner::force_hara_kiri_in_parent_callback (SCM element_smob, S
 void
 Hara_kiri_group_spanner::add_element (Grob *me, Grob *e)
 {
-  //  e->add_offset_callback (force_hara_kiri_in_parent_callback, Y_AXIS);
   Axis_group_interface::add_element (me, e);
 }
 
diff --git a/lily/include/accidental-placement.hh b/lily/include/accidental-placement.hh
index 2343e01e12..90f052add9 100644
--- a/lily/include/accidental-placement.hh
+++ b/lily/include/accidental-placement.hh
@@ -14,7 +14,7 @@
 class Accidental_placement
 {
 public:
-  DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element));
   static void add_accidental (Grob *, Grob *);
 
   static Interval get_relevant_accidental_extent (Grob *me,
diff --git a/lily/include/align-interface.hh b/lily/include/align-interface.hh
index f0e20d0064..f4b192c383 100644
--- a/lily/include/align-interface.hh
+++ b/lily/include/align-interface.hh
@@ -15,8 +15,6 @@
 struct Align_interface
 {
   DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM));
-  DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element, SCM axis));
-  DECLARE_SCHEME_CALLBACK (fixed_distance_alignment_callback, (SCM element, SCM axis));
   DECLARE_SCHEME_CALLBACK (stretch_after_break, (SCM element));
   static void align_to_fixed_distance (Grob *, Axis a);
   static void align_elements_to_extents (Grob *, Axis a);
diff --git a/lily/include/beam.hh b/lily/include/beam.hh
index 83e2c591f7..f27ad5748e 100644
--- a/lily/include/beam.hh
+++ b/lily/include/beam.hh
@@ -55,7 +55,7 @@ public:
   static Real get_thickness (Grob *me);
   static void connect_beams (Grob *me);
 
-  DECLARE_SCHEME_CALLBACK (rest_collision_callback, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (rest_collision_callback, (SCM element, SCM prev_off));
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_positions, (SCM));
diff --git a/lily/include/break-align-interface.hh b/lily/include/break-align-interface.hh
index cfa651bb9d..c13e54f763 100644
--- a/lily/include/break-align-interface.hh
+++ b/lily/include/break-align-interface.hh
@@ -18,7 +18,7 @@ public:
   static bool has_interface (Grob *);
   static void add_element (Grob *me, Grob *add);
   DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM element));
-  DECLARE_SCHEME_CALLBACK (self_align_callback, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (self_align_callback, (SCM element));
 };
 struct Break_aligned_interface
 {
diff --git a/lily/include/breathing-sign.hh b/lily/include/breathing-sign.hh
index acff1ea3cb..57bdf17c02 100644
--- a/lily/include/breathing-sign.hh
+++ b/lily/include/breathing-sign.hh
@@ -26,7 +26,7 @@ public:
   DECLARE_SCHEME_CALLBACK (divisio_maior, (SCM));
   DECLARE_SCHEME_CALLBACK (divisio_maxima, (SCM));
   DECLARE_SCHEME_CALLBACK (finalis, (SCM));
-  DECLARE_SCHEME_CALLBACK (offset_callback, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (offset_callback, (SCM element));
 
   static bool has_interface (Grob *);
 };
diff --git a/lily/include/dimension-cache.hh b/lily/include/dimension-cache.hh
index 00480e9fcb..66de466019 100644
--- a/lily/include/dimension-cache.hh
+++ b/lily/include/dimension-cache.hh
@@ -23,10 +23,7 @@ class Dimension_cache
      The offset wrt. to the center of #parent_#
   */
   Interval *extent_;
-  Real offset_;
-  SCM offset_callbacks_;
-
-  char offsets_left_;
+  Real *offset_;
 
   /**
      What to call to find extent.  Nil means empty.
diff --git a/lily/include/dot-column.hh b/lily/include/dot-column.hh
index 3a56cd9cc2..2cd1f9f685 100644
--- a/lily/include/dot-column.hh
+++ b/lily/include/dot-column.hh
@@ -23,8 +23,7 @@ public:
   static void add_head (Grob *dotcol, Grob *rh);
 
   static bool has_interface (Grob *);
-  DECLARE_SCHEME_CALLBACK (force_shift_callback, (SCM, SCM));
-  DECLARE_SCHEME_CALLBACK (side_position, (SCM, SCM));
+  DECLARE_SCHEME_CALLBACK (side_position, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM));
 };
 #endif // DOT_COLUMN_HH
diff --git a/lily/include/grob.hh b/lily/include/grob.hh
index 211bf08d39..b969f7478b 100644
--- a/lily/include/grob.hh
+++ b/lily/include/grob.hh
@@ -44,8 +44,8 @@ protected:
   DECLARE_CLASSNAME(Grob);
   Real get_offset (Axis a) const;
 public:
-  DECLARE_SCHEME_CALLBACK(same_axis_parent_positioning, (SCM, SCM));
-  DECLARE_SCHEME_CALLBACK(other_axis_parent_positioning, (SCM, SCM));
+  DECLARE_SCHEME_CALLBACK(x_parent_positioning, (SCM));
+  DECLARE_SCHEME_CALLBACK(y_parent_positioning, (SCM));
 
   Object_key const *get_key () const;
 
@@ -112,9 +112,6 @@ public:
   Real relative_coordinate (Grob const *refp, Axis) const;
   Grob *common_refpoint (Grob const *s, Axis a) const;
 
-  // duh. slim down interface here. (todo)
-  bool has_offset_callback (SCM callback, Axis) const;
-  void add_offset_callback (SCM callback, Axis);
   void flush_extent_cache (Axis);
 
   void set_parent (Grob *e, Axis);
@@ -142,4 +139,12 @@ Interval robust_relative_extent (Grob *, Grob *, Axis);
 bool is_callback_chain (SCM s);
 SCM callback_chain_extract_procedures (SCM chain_smob);
 
+
+SCM axis_offset_symbol (Axis a);
+SCM axis_self_offset_symbol (Axis a);
+SCM axis_parent_positioning (Axis a);
+void add_offset_callback (Grob *g, SCM proc, Axis a);
+void chain_offset_callback (Grob *g, SCM proc, Axis a);
+
+
 #endif /* GROB_HH */
diff --git a/lily/include/misc.hh b/lily/include/misc.hh
index 8ea878cc2e..c34f1094a8 100644
--- a/lily/include/misc.hh
+++ b/lily/include/misc.hh
@@ -37,5 +37,7 @@ linear_interpolate (Real x, Real x1, Real x2, Real y1, Real y2)
     + (x - x1) / (x2 - x1) * y2;
 }
 
+Real directed_round (Real f, Direction d);
+
 #endif
 
diff --git a/lily/include/note-collision.hh b/lily/include/note-collision.hh
index ed65a0cac1..0213480071 100644
--- a/lily/include/note-collision.hh
+++ b/lily/include/note-collision.hh
@@ -30,7 +30,6 @@ public:
   static SCM forced_shift (Grob *);
 
   static Drul_array<Link_array<Grob> > get_clash_groups (Grob *me);
-  DECLARE_SCHEME_CALLBACK (force_shift_callback, (SCM element, SCM axis));
   DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM smob));
   static void add_column (Grob *me, Grob *ncol);
   static bool has_interface (Grob *);
diff --git a/lily/include/note-head.hh b/lily/include/note-head.hh
index 478ed07baa..7d02ed3f57 100644
--- a/lily/include/note-head.hh
+++ b/lily/include/note-head.hh
@@ -21,7 +21,7 @@ class Note_head
 public:
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (brew_ez_stencil, (SCM));
-  DECLARE_SCHEME_CALLBACK (stem_x_shift, (SCM, SCM));
+  DECLARE_SCHEME_CALLBACK (stem_x_shift, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_stem_attachment, (SCM));
   static bool has_interface (Grob *);
   static Real stem_attachment_coordinate (Grob *, Axis a);
diff --git a/lily/include/rest-collision.hh b/lily/include/rest-collision.hh
index a9a80eb20b..5295fd435b 100644
--- a/lily/include/rest-collision.hh
+++ b/lily/include/rest-collision.hh
@@ -18,9 +18,9 @@ public:
   static void add_column (Grob *me, Grob *);
 
   static bool has_interface (Grob *);
-  DECLARE_SCHEME_CALLBACK (force_shift_callback, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (force_shift_callback, (SCM element));
   DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM element));
-  DECLARE_SCHEME_CALLBACK (force_shift_callback_rest, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (force_shift_callback_rest, (SCM element));
   static SCM do_shift (Grob *);
 };
 #endif // REST_COLLISION_HH
diff --git a/lily/include/rest.hh b/lily/include/rest.hh
index fb8dbf3aed..a62b5caa6a 100644
--- a/lily/include/rest.hh
+++ b/lily/include/rest.hh
@@ -16,13 +16,12 @@ class Grob;
 class Rest
 {
 public:
-  DECLARE_SCHEME_CALLBACK (y_offset_callback, (SCM, SCM));
+  DECLARE_SCHEME_CALLBACK (y_offset_callback, (SCM));
   static bool has_interface (Grob *);
   static String glyph_name (Grob *, int, String, bool);
   static SCM brew_internal_stencil (Grob*, bool);
   static SCM generic_extent_callback (Grob*, Axis);
-  DECLARE_SCHEME_CALLBACK (extent_callback, (SCM, SCM));
-  DECLARE_SCHEME_CALLBACK (polyphonic_offset_callback, (SCM, SCM));
+  DECLARE_SCHEME_CALLBACK (polyphonic_offset_callback, (SCM));
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (width, (SCM));
   DECLARE_SCHEME_CALLBACK (height, (SCM));
diff --git a/lily/include/script-interface.hh b/lily/include/script-interface.hh
index 8591ce0b47..e59cf5e59e 100644
--- a/lily/include/script-interface.hh
+++ b/lily/include/script-interface.hh
@@ -26,7 +26,7 @@ public:
   DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
 };
 
-void make_script_from_event (Grob *p, bool *follow, Context *tg,
+void make_script_from_event (Grob *p,  Context *tg,
 			     SCM type, int index);
 
 #endif /* SCRIPT_INTERFACE_HH */
diff --git a/lily/include/self-alignment-interface.hh b/lily/include/self-alignment-interface.hh
index aa47c7af76..c9438a764b 100644
--- a/lily/include/self-alignment-interface.hh
+++ b/lily/include/self-alignment-interface.hh
@@ -14,9 +14,18 @@
 struct Self_alignment_interface
 {
   static bool has_interface (Grob *);
-  DECLARE_SCHEME_CALLBACK (aligned_on_self, (SCM element, SCM axis));
-  DECLARE_SCHEME_CALLBACK (centered_on_parent, (SCM element, SCM axis));
-  DECLARE_SCHEME_CALLBACK (aligned_on_parent, (SCM element, SCM axis));
-  DECLARE_SCHEME_CALLBACK (centered_on_other_axis_parent, (SCM element, SCM axis));
+
+  static SCM aligned_on_self (Grob *me, Axis a);
+  static SCM centered_on_parent (Grob *me, Axis a);
+  static SCM aligned_on_parent (Grob *me, Axis a);
+  
+  DECLARE_SCHEME_CALLBACK (x_aligned_on_self, (SCM element));
+  DECLARE_SCHEME_CALLBACK (y_aligned_on_self, (SCM element));
+
+  DECLARE_SCHEME_CALLBACK (centered_on_x_parent, (SCM element));
+  DECLARE_SCHEME_CALLBACK (centered_on_y_parent, (SCM element));
+
+  DECLARE_SCHEME_CALLBACK (aligned_on_x_parent, (SCM element));
+  DECLARE_SCHEME_CALLBACK (aligned_on_y_parent, (SCM element));
 };
 #endif
diff --git a/lily/include/side-position-interface.hh b/lily/include/side-position-interface.hh
index ff16b0c386..7dc5638486 100644
--- a/lily/include/side-position-interface.hh
+++ b/lily/include/side-position-interface.hh
@@ -20,12 +20,12 @@
 struct Side_position_interface
 {
 public:
-  DECLARE_SCHEME_CALLBACK (aligned_on_support_extents, (SCM element, SCM axis));
-  DECLARE_SCHEME_CALLBACK (aligned_on_support_refpoints, (SCM element, SCM axis));
 
-  DECLARE_SCHEME_CALLBACK (aligned_side, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (y_aligned_on_support_refpoints, (SCM element));
+  DECLARE_SCHEME_CALLBACK (x_aligned_side, (SCM element));
+  DECLARE_SCHEME_CALLBACK (y_aligned_side, (SCM element));
 
-  DECLARE_SCHEME_CALLBACK (quantised_position, (SCM element, SCM axis));
+  static SCM Side_position_interface::aligned_side (Grob*me, Axis a);
 
   static SCM general_side_position (Grob *, Axis, bool);
   static Axis get_axis (Grob *);
diff --git a/lily/include/simple-closure.hh b/lily/include/simple-closure.hh
new file mode 100644
index 0000000000..4e6a126250
--- /dev/null
+++ b/lily/include/simple-closure.hh
@@ -0,0 +1,18 @@
+/*
+  simple-closure.hh -- declare simple closures 
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#ifndef SIMPLE_CLOSURE_HH
+#define SIMPLE_CLOSURE_HH
+
+bool is_simple_closure (SCM s);
+SCM simple_closure_expression (SCM smob);
+SCM evaluate_with_simple_closure (SCM delayed_argument, SCM expr);
+SCM ly_make_simple_closure (SCM);
+
+#endif /* SIMPLE_CLOSURE_HH */
diff --git a/lily/include/span-bar.hh b/lily/include/span-bar.hh
index 53b317e07d..f683310b18 100644
--- a/lily/include/span-bar.hh
+++ b/lily/include/span-bar.hh
@@ -30,7 +30,7 @@ public:
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_glyph_name, (SCM));
   DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM));
-  DECLARE_SCHEME_CALLBACK (center_on_spanned_callback, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (center_on_spanned_callback, (SCM element));
 };
 
 #endif // SPAN_BAR_HH
diff --git a/lily/include/staff-symbol-referencer.hh b/lily/include/staff-symbol-referencer.hh
index 2502f50baa..d035b01dbd 100644
--- a/lily/include/staff-symbol-referencer.hh
+++ b/lily/include/staff-symbol-referencer.hh
@@ -21,7 +21,7 @@ public:
   static bool has_interface (Grob *);
   static bool ugly_hack (Grob *);
   static void set_position (Grob *, Real);
-  DECLARE_SCHEME_CALLBACK (callback, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (callback, (SCM element));
 
   /**
      Leading are the lead strips between the sticks (lines) of
diff --git a/lily/include/stem-tremolo.hh b/lily/include/stem-tremolo.hh
index 86ddf33749..5099ea7914 100644
--- a/lily/include/stem-tremolo.hh
+++ b/lily/include/stem-tremolo.hh
@@ -17,7 +17,7 @@ class Stem_tremolo
 public:
 
   static bool has_interface (Grob *);
-  DECLARE_SCHEME_CALLBACK (dim_callback, (SCM smob, SCM axis));
+  DECLARE_SCHEME_CALLBACK (dim_callback, (SCM smob));
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (height, (SCM));
   static Stencil raw_stencil (Grob *);
diff --git a/lily/include/stem.hh b/lily/include/stem.hh
index 75f37b6a43..ee66ec15fa 100644
--- a/lily/include/stem.hh
+++ b/lily/include/stem.hh
@@ -40,7 +40,7 @@ public:
   static void set_spacing_hints (Grob *);
   
   DECLARE_SCHEME_CALLBACK (print, (SCM));
-  DECLARE_SCHEME_CALLBACK (offset_callback, (SCM element, SCM axis));
+  DECLARE_SCHEME_CALLBACK (offset_callback, (SCM element));
   DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_length, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_stem_end_position, (SCM));
diff --git a/lily/misc.cc b/lily/misc.cc
index 08f3827abb..bfc97761c0 100644
--- a/lily/misc.cc
+++ b/lily/misc.cc
@@ -58,3 +58,14 @@ split_string (String s, char c)
 
   return rv;
 }
+
+
+Real
+directed_round (Real f, Direction d)
+{
+  if (d < 0)
+    return floor (f);
+  else
+    return ceil (f);
+}
+
diff --git a/lily/new-fingering-engraver.cc b/lily/new-fingering-engraver.cc
index dc55d8e7f3..0285faec33 100644
--- a/lily/new-fingering-engraver.cc
+++ b/lily/new-fingering-engraver.cc
@@ -112,8 +112,7 @@ New_fingering_engraver::add_script (Grob *head,
   Finger_tuple ft;
 
   Grob *g = make_item ("Script", event->self_scm ());
-  make_script_from_event (g, &ft.follow_into_staff_, context (),
-			  event->get_property ("articulation-type"), 0);
+  make_script_from_event (g, context (), event->get_property ("articulation-type"), 0);
   if (g)
     {
       ft.script_ = g;
@@ -267,9 +266,10 @@ New_fingering_engraver::position_scripts (SCM orientations,
       Grob *f = ft.script_;
       f->set_parent (ft.head_, X_AXIS);
       f->set_parent (ft.head_, Y_AXIS);
-      f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, Y_AXIS);
-      f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, Y_AXIS);
-      f->add_offset_callback (Side_position_interface::aligned_side_proc, X_AXIS);
+
+      f->set_property ("self-Y-offset",Self_alignment_interface::y_aligned_on_self_proc);
+      f->set_property ("Y-offset",  Self_alignment_interface::centered_on_y_parent_proc);
+      f->set_property ("X-offset",  Side_position_interface::x_aligned_side_proc);
 
       f->set_property ("direction", scm_from_int (hordir));
     }
@@ -282,10 +282,11 @@ New_fingering_engraver::position_scripts (SCM orientations,
       f->set_parent (ft.head_, X_AXIS);
       f->set_property ("script-priority",
 		       scm_from_int (finger_prio + ft.position_));
-      f->add_offset_callback (Side_position_interface::aligned_side_proc, Y_AXIS);
-      f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, X_AXIS);
-      f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, X_AXIS);
 
+      f->set_property ("self-X-offset", Self_alignment_interface::x_aligned_on_self_proc);
+      f->set_property ("Y-offset", Side_position_interface::y_aligned_side_proc);
+      f->set_property ("X-offset", Self_alignment_interface::centered_on_x_parent_proc);
+      
       f->set_property ("direction", scm_from_int (UP));
     }
 
@@ -297,9 +298,10 @@ New_fingering_engraver::position_scripts (SCM orientations,
       f->set_property ("script-priority",
 		       scm_from_int (finger_prio + down.size () - ft.position_));
 
-      f->add_offset_callback (Self_alignment_interface::centered_on_parent_proc, X_AXIS);
-      f->add_offset_callback (Self_alignment_interface::aligned_on_self_proc, X_AXIS);
-      f->add_offset_callback (Side_position_interface::aligned_side_proc, Y_AXIS);
+      f->set_property ("self-X-offset", Self_alignment_interface::x_aligned_on_self_proc);
+      f->set_property ("X-offset", Self_alignment_interface::centered_on_x_parent_proc);
+      f->set_property ("Y-offset", Side_position_interface::y_aligned_side_proc);
+
       f->set_property ("direction", scm_from_int (DOWN));
     }
 }
@@ -334,11 +336,7 @@ New_fingering_engraver::stop_translation_timestep ()
       if (stem_ && to_boolean (script->get_property ("add-stem-support")))
 	Side_position_interface::add_support (script, stem_);
 
-      if (articulations_[i].follow_into_staff_)
-	{
-	  script->add_offset_callback (Side_position_interface::quantised_position_proc, Y_AXIS);
-	  script->set_property ("staff-padding", SCM_EOL);
-	}
+
     }
 
   stem_ = 0;
diff --git a/lily/note-collision.cc b/lily/note-collision.cc
index e80d21ff7d..1c31ad8e61 100644
--- a/lily/note-collision.cc
+++ b/lily/note-collision.cc
@@ -480,7 +480,7 @@ Note_collision_interface::forced_shift (Grob *me)
 void
 Note_collision_interface::add_column (Grob *me, Grob *ncol)
 {
-  ncol->add_offset_callback (Grob::same_axis_parent_positioning_proc, X_AXIS);
+  ncol->set_property ("X-offset", Grob::x_parent_positioning_proc);
   Axis_group_interface::add_element (me, ncol);
 }
 
diff --git a/lily/note-head.cc b/lily/note-head.cc
index 3b80b114ba..7a34e85a34 100644
--- a/lily/note-head.cc
+++ b/lily/note-head.cc
@@ -75,12 +75,10 @@ internal_print (Grob *me, String *font_char)
 /*
   TODO: make stem X-parent of notehead. 
  */
-MAKE_SCHEME_CALLBACK (Note_head, stem_x_shift, 2);
+MAKE_SCHEME_CALLBACK (Note_head, stem_x_shift, 1);
 SCM
-Note_head::stem_x_shift (SCM smob, SCM axis)
+Note_head::stem_x_shift (SCM smob)
 {
-  (void) axis;
-  
   Grob *me = unsmob_grob (smob);
   Grob *stem = unsmob_grob (me->get_object ("stem"));
   if (stem)
diff --git a/lily/phrasing-slur-engraver.cc b/lily/phrasing-slur-engraver.cc
index c240642d8f..d0891c08d7 100644
--- a/lily/phrasing-slur-engraver.cc
+++ b/lily/phrasing-slur-engraver.cc
@@ -13,6 +13,7 @@
 #include "note-column.hh"
 #include "spanner.hh"
 #include "tie.hh"
+#include "warn.hh"
 
 /*
   It is possible that a slur starts and ends on the same note.  At
@@ -112,7 +113,7 @@ Phrasing_slur_engraver::acknowledge_extra_object (Grob_info info)
 
       if (slur)
 	{
-	  e->add_offset_callback (Slur::outside_slur_callback_proc, Y_AXIS);
+	  chain_offset_callback (e, Slur::outside_slur_callback_proc, Y_AXIS);
 	  e->set_object ("slur", slur->self_scm ());
 	}
     }
diff --git a/lily/rest-collision.cc b/lily/rest-collision.cc
index ecac2bc08f..272aba6f41 100644
--- a/lily/rest-collision.cc
+++ b/lily/rest-collision.cc
@@ -22,14 +22,11 @@ using namespace std;
 #include "duration.hh"
 #include "directional-element-interface.hh"
 
-MAKE_SCHEME_CALLBACK (Rest_collision, force_shift_callback, 2);
+MAKE_SCHEME_CALLBACK (Rest_collision, force_shift_callback, 1);
 SCM
-Rest_collision::force_shift_callback (SCM element_smob, SCM axis)
+Rest_collision::force_shift_callback (SCM smob)
 {
-  Grob *them = unsmob_grob (element_smob);
-  (void) axis;
-  assert (scm_to_int (axis) == Y_AXIS);
-
+  Grob *them = unsmob_grob (smob);
   if (Note_column::has_rests (them))
     {
       Grob *collision = unsmob_grob (them->get_object ("rest-collision"));
@@ -42,16 +39,14 @@ Rest_collision::force_shift_callback (SCM element_smob, SCM axis)
   return scm_from_double (0.0);
 }
 
-MAKE_SCHEME_CALLBACK (Rest_collision, force_shift_callback_rest, 2);
+MAKE_SCHEME_CALLBACK (Rest_collision, force_shift_callback_rest, 1);
 SCM
-Rest_collision::force_shift_callback_rest (SCM rest, SCM axis)
+Rest_collision::force_shift_callback_rest (SCM rest)
 {
   Grob *rest_grob = unsmob_grob (rest);
-  assert ((Axis) scm_to_int (axis) == Y_AXIS);
-
   Grob *parent = rest_grob->get_parent (X_AXIS);
   if (Note_column::has_interface (parent))
-    return force_shift_callback (parent->self_scm (), axis);
+    return force_shift_callback (parent->self_scm ());
   else
     return scm_from_double (0.0);
 }
@@ -67,14 +62,14 @@ Rest_collision::add_column (Grob *me, Grob *p)
 
     (not?)
   */
-  p->add_offset_callback (Rest_collision::force_shift_callback_proc, Y_AXIS);
+  add_offset_callback (p, Rest_collision::force_shift_callback_proc, Y_AXIS);
   p->set_object ("rest-collision", me->self_scm ());
 
   Grob *rest = unsmob_grob (p->get_object ("rest"));
   if (rest)
     {
-      rest->add_offset_callback (Rest_collision::force_shift_callback_rest_proc,
-				 Y_AXIS);
+      rest->set_property ("Y-offset" ,
+			  Rest_collision::force_shift_callback_rest_proc);
     }
 }
 
diff --git a/lily/rest.cc b/lily/rest.cc
index 0645fe1bba..b362a5de03 100644
--- a/lily/rest.cc
+++ b/lily/rest.cc
@@ -17,37 +17,38 @@
 #include "directional-element-interface.hh"
 
 // -> offset callback
-MAKE_SCHEME_CALLBACK (Rest, y_offset_callback, 2);
+MAKE_SCHEME_CALLBACK (Rest, y_offset_callback, 1);
 SCM
-Rest::y_offset_callback (SCM smob, SCM axis)
+Rest::y_offset_callback (SCM smob)
 {
   Grob *me = unsmob_grob (smob);
-  (void) axis;
-  
-  int bt = scm_to_int (me->get_property ("duration-log"));
+  int duration_log = scm_to_int (me->get_property ("duration-log"));
   int lc = Staff_symbol_referencer::line_count (me);
   Real ss = Staff_symbol_referencer::staff_space (me);
 
   Real amount = 0.0;
   if (lc % 2)
     {
-      if (bt == 0 && lc > 1)
+      if (duration_log == 0 && lc > 1)
 	amount += ss;
     }
   else
     amount += ss / 2;
 
-  Grob *d = unsmob_grob (me->get_object ("dot"));
-  if (d && bt > 4) // UGH.
+  Grob *dot = unsmob_grob (me->get_object ("dot"));
+  if (dot && duration_log > 4) // UGH.
     {
-      d->set_property ("staff-position",
-		       scm_from_int ((bt == 7) ? 4 : 3));
+      dot->set_property ("staff-position",
+		       scm_from_int ((duration_log == 7) ? 4 : 3));
     }
-  if (d && bt >= -1 && bt <= 1) // UGH again.
+  if (dot && duration_log >= -1 && duration_log <= 1) // UGH again.
     {
-      d->set_property ("staff-position",
-		       scm_from_int ((bt == 0) ? -1 : 1));
+      dot->set_property ("staff-position",
+		       scm_from_int ((duration_log == 0) ? -1 : 1));
     }
+
+  amount += 2 * ss * get_grob_direction (me);; 
+  
   return scm_from_double (amount);
 }
 
@@ -159,7 +160,7 @@ MAKE_SCHEME_CALLBACK (Rest, height, 1);
 SCM
 Rest::height (SCM smob)
 {
-  return  generic_extent_callback (unsmob_grob (smob), Y_AXIS);
+  return generic_extent_callback (unsmob_grob (smob), Y_AXIS);
 }
 
 /*
@@ -180,23 +181,12 @@ Rest::generic_extent_callback (Grob *me, Axis a)
   return ly_interval2scm (unsmob_stencil (m)->extent (a));
 }
 
-MAKE_SCHEME_CALLBACK (Rest, polyphonic_offset_callback, 2);
-SCM
-Rest::polyphonic_offset_callback (SCM smob, SCM)
-{
-  Grob *me = unsmob_grob (smob);
-  if (scm_is_number (me->get_property ("staff-position")))
-    return scm_from_double (0);
-
-  Direction d = get_grob_direction (me);
-  Real off = 2 * d;
-  if (off)
-    off *= Staff_symbol_referencer::staff_space (me);
-
-  return scm_from_double (off);
-}
-
 ADD_INTERFACE (Rest, "rest-interface",
 	       "A rest symbol.",
-	       "style direction minimum-distance");
+
+	       /* properties */
+		  
+	       "style "
+	       "direction "
+	       "minimum-distance");
 
diff --git a/lily/script-column.cc b/lily/script-column.cc
index 7d72ffc5bb..4c67ed0971 100644
--- a/lily/script-column.cc
+++ b/lily/script-column.cc
@@ -52,8 +52,8 @@ Script_column::before_line_breaking (SCM smob)
       /*
 	Don't want to consider scripts horizontally next to notes.
       */
-      if (!sc->has_offset_callback (Side_position_interface::aligned_side_proc,
-				    X_AXIS))
+      if (sc->get_property_data (ly_symbol2scm ("X-offset")) !=
+	  Side_position_interface::x_aligned_side_proc)
 	staff_sided.push (sc);
     }
 
diff --git a/lily/script-engraver.cc b/lily/script-engraver.cc
index f9ecf93ebd..2f7eee9a4e 100644
--- a/lily/script-engraver.cc
+++ b/lily/script-engraver.cc
@@ -23,10 +23,8 @@ struct Script_tuple
 {
   Music *event_;
   Grob *script_;
-  bool follow_into_staff_;
   Script_tuple ()
   {
-    follow_into_staff_ = false;
     event_ = 0;
     script_ = 0;
   }
@@ -92,7 +90,7 @@ copy_property (Grob *g, SCM sym, SCM alist)
    could be saved by tacking the props onto the Script grob (i.e. make
    ScriptStaccato , ScriptMarcato, etc. ).
 */
-void make_script_from_event (Grob *p, bool *follow, Context *tg,
+void make_script_from_event (Grob *p,  Context *tg,
 			     SCM art_type, int index)
 {
   SCM alist = tg->get_property ("scriptDefinitions");
@@ -110,10 +108,6 @@ void make_script_from_event (Grob *p, bool *follow, Context *tg,
 
   art = scm_cdr (art);
 
-  SCM follow_scm = scm_assoc (ly_symbol2scm ("follow-into-staff"),
-			      art);
-
-  *follow = scm_is_pair (follow_scm) && to_boolean (scm_cdr (follow_scm));
   bool priority_found = false;
 
   for (SCM s = art; scm_is_pair (s); s = scm_cdr (s))
@@ -159,7 +153,7 @@ Script_engraver::process_music ()
 
       Grob *p = make_item ("Script", music->self_scm ());
 
-      make_script_from_event (p, &scripts_[i].follow_into_staff_, context (),
+      make_script_from_event (p, context (),
 			      music->get_property ("articulation-type"),
 			      i);
 
@@ -233,16 +227,6 @@ Script_engraver::acknowledge_slur (Grob_info info)
 void
 Script_engraver::stop_translation_timestep ()
 {
-  int script_count = scripts_.size ();
-  for (int i = 0; i < script_count; i++)
-    if (scripts_[i].follow_into_staff_)
-      {
-	Grob *sc = scripts_[i].script_;
-	sc->add_offset_callback (Side_position_interface
-				 ::quantised_position_proc, Y_AXIS);
-	sc->set_property ("staff-padding", SCM_EOL);
-      }
-
   scripts_.clear ();
 }
 
diff --git a/lily/self-aligment-interface.cc b/lily/self-aligment-interface.cc
index c3ef66b54f..ed66d30ef1 100644
--- a/lily/self-aligment-interface.cc
+++ b/lily/self-aligment-interface.cc
@@ -1,34 +1,90 @@
 /*
-  self-alignment-interface.cc
-
+  self-alignment-interface.cc -- implement Self_alignment_interface
+ 
   source file of the GNU LilyPond music typesetter
 
   (c) 2004--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
 */
 
 #include "self-alignment-interface.hh"
-
 #include "warn.hh"
 
-/* Position centered on parent.  */
-MAKE_SCHEME_CALLBACK (Self_alignment_interface, centered_on_parent, 2);
+MAKE_SCHEME_CALLBACK (Self_alignment_interface, y_aligned_on_self, 1);
+SCM
+Self_alignment_interface::y_aligned_on_self (SCM element)
+{
+  return aligned_on_self (unsmob_grob (element), Y_AXIS);
+}
+
+MAKE_SCHEME_CALLBACK (Self_alignment_interface, x_aligned_on_self, 1);
+SCM
+Self_alignment_interface::x_aligned_on_self (SCM element)
+{
+  return aligned_on_self (unsmob_grob (element), X_AXIS);
+}
+
+SCM
+Self_alignment_interface::aligned_on_self (Grob *me, Axis a)
+{
+  SCM sym = (a == X_AXIS) ? ly_symbol2scm ("self-alignment-X")
+    : ly_symbol2scm ("self-alignment-Y");
+
+  SCM align (me->internal_get_property (sym));
+  if (scm_is_number (align))
+    {
+      Interval ext (me->extent (me, a));
+      if (ext.is_empty ())
+	programming_error ("can't align on self: empty element");
+      else
+	return scm_from_double (- ext.linear_combination (scm_to_double (align)));
+    }
+  return scm_from_double (0.0);
+}
+
+
+
+
+MAKE_SCHEME_CALLBACK (Self_alignment_interface, centered_on_x_parent, 1);
+SCM
+Self_alignment_interface::centered_on_x_parent (SCM smob)
+{
+  return centered_on_parent (unsmob_grob (smob), X_AXIS);
+}
+
+
+MAKE_SCHEME_CALLBACK (Self_alignment_interface, centered_on_y_parent, 1);
+SCM
+Self_alignment_interface::centered_on_y_parent (SCM smob)
+{
+  return centered_on_parent (unsmob_grob (smob), Y_AXIS);
+}
+
 SCM
-Self_alignment_interface::centered_on_parent (SCM element_smob, SCM axis)
+Self_alignment_interface::centered_on_parent (Grob *me, Axis a)
 {
-  Grob *me = unsmob_grob (element_smob);
-  Axis a = (Axis) scm_to_int (axis);
   Grob *him = me->get_parent (a);
   Interval he = him->extent (him, a);
 
   return scm_from_double (he.is_empty () ? 0.0 : he.center ());
 }
 
-MAKE_SCHEME_CALLBACK (Self_alignment_interface, aligned_on_parent, 2);
+MAKE_SCHEME_CALLBACK (Self_alignment_interface, aligned_on_x_parent,1);
+SCM
+Self_alignment_interface::aligned_on_x_parent (SCM smob)
+{
+  return aligned_on_parent (unsmob_grob (smob), X_AXIS);
+}
+
+MAKE_SCHEME_CALLBACK (Self_alignment_interface, aligned_on_y_parent,1);
+SCM
+Self_alignment_interface::aligned_on_y_parent (SCM smob)
+{
+  return aligned_on_parent (unsmob_grob (smob), Y_AXIS);
+}
+
 SCM
-Self_alignment_interface::aligned_on_parent (SCM element_smob, SCM axis)
+Self_alignment_interface::aligned_on_parent (Grob *me, Axis a)
 {
-  Grob *me = unsmob_grob (element_smob);
-  Axis a = (Axis) scm_to_int (axis);
   Grob *him = me->get_parent (a);
   Interval he = him->extent (him, a);
 
@@ -54,44 +110,6 @@ Self_alignment_interface::aligned_on_parent (SCM element_smob, SCM axis)
   return scm_from_double (x);
 }
 
-/* Position centered on parent. */
-MAKE_SCHEME_CALLBACK (Self_alignment_interface, centered_on_other_axis_parent, 2);
-SCM
-Self_alignment_interface::centered_on_other_axis_parent (SCM element_smob,
-							 SCM axis)
-{
-  Grob *me = unsmob_grob (element_smob);
-  Axis a = (Axis) scm_to_int (axis);
-  Grob *him = me->get_parent (other_axis (a));
-  Interval he = him->extent (him, a);
-
-  return scm_from_double (he.is_empty () ? 0.0 : he.center ());
-}
-
-/** callback that centers the element on itself
-    Requires that self-alignment-{X, Y} be set.  */
-MAKE_SCHEME_CALLBACK (Self_alignment_interface, aligned_on_self, 2);
-SCM
-Self_alignment_interface::aligned_on_self (SCM element_smob, SCM axis)
-{
-  Grob *me = unsmob_grob (element_smob);
-  Axis a = (Axis) scm_to_int (axis);
-
-  SCM sym = (a == X_AXIS) ? ly_symbol2scm ("self-alignment-X")
-    : ly_symbol2scm ("self-alignment-Y");
-
-  SCM align (me->internal_get_property (sym));
-  if (scm_is_number (align))
-    {
-      Interval ext (me->extent (me, a));
-      if (ext.is_empty ())
-	programming_error ("can't align on self: empty element");
-      else
-	return scm_from_double (- ext.linear_combination (scm_to_double (align)));
-    }
-  return scm_from_double (0.0);
-}
-
 ADD_INTERFACE (Self_alignment_interface, "self-alignment-interface",
 	       "Position this object on itself and/or on its parent. To this end, the following functions "
 	       " are provided: \n"
@@ -106,5 +124,9 @@ ADD_INTERFACE (Self_alignment_interface, "self-alignment-interface",
 	       "@item Self_alignment_interface::centered_on_other_axis_parent\n"
 	       " For X-axis, center on the Y-parent, and vice versa.\n "
 	       "@end table\n",
-	       "self-alignment-X self-alignment-Y");
+
+
+	       /* porperties */
+	       "self-alignment-X "
+	       "self-alignment-Y ");
 
diff --git a/lily/side-position-interface.cc b/lily/side-position-interface.cc
index 3546bc2b76..498818f447 100644
--- a/lily/side-position-interface.cc
+++ b/lily/side-position-interface.cc
@@ -20,7 +20,9 @@ using namespace std;
 #include "pointer-group-interface.hh"
 #include "directional-element-interface.hh"
 #include "staff-symbol-referencer.hh"
+#include "staff-symbol.hh"
 #include "string-convert.hh"
+#include "misc.hh"
 
 void
 Side_position_interface::add_support (Grob *me, Grob *e)
@@ -32,7 +34,7 @@ Direction
 Side_position_interface::get_direction (Grob *me)
 {
   Direction relative_dir = Direction (1);
-  SCM reldir = me->get_property ("side-relative-direction");	// should use a lambda.
+  SCM reldir = me->get_property ("side-relative-direction");
   if (is_direction (reldir))
     relative_dir = to_dir (reldir);
 
@@ -44,16 +46,6 @@ Side_position_interface::get_direction (Grob *me)
   return CENTER;
 }
 
-MAKE_SCHEME_CALLBACK (Side_position_interface, aligned_on_support_extents, 2);
-SCM
-Side_position_interface::aligned_on_support_extents (SCM element_smob, SCM axis)
-{
-  Grob *me = unsmob_grob (element_smob);
-  Axis a = (Axis) scm_to_int (axis);
-
-  return general_side_position (me, a, true);
-}
-
 /* Put the element next to the support, optionally taking in
    account the extent of the support.  */
 SCM
@@ -64,16 +56,25 @@ Side_position_interface::general_side_position (Grob *me, Axis a, bool use_exten
   extract_grob_set (me, "side-support-elements", support);
 
   Grob *common = common_refpoint_of_array (support, me->get_parent (a), a);
-  Grob *st = Staff_symbol_referencer::get_staff_symbol (me);
-  bool include_staff = (st
-			&& a == Y_AXIS
-			&& scm_is_number (me->get_property ("staff-padding")));
+  Grob *staff_symbol = Staff_symbol_referencer::get_staff_symbol (me);
+  bool include_staff = false;
+
+  if (staff_symbol
+      && a == Y_AXIS)
+    {
+      if (scm_is_number (me->get_property ("staff-padding")))
+	include_staff = true;
+    }
 
   Interval dim;
+  Interval staff_extents;
   if (include_staff)
     {
-      common = st->common_refpoint (common, Y_AXIS);
-      dim = st->extent (common, Y_AXIS);
+      common = staff_symbol->common_refpoint (common, Y_AXIS);
+      staff_extents = staff_symbol->extent (common, Y_AXIS);
+
+      if (include_staff)
+	dim.unite (staff_extents);
     }
 
   for (int i = 0; i < support.size (); i++)
@@ -104,7 +105,7 @@ Side_position_interface::general_side_position (Grob *me, Axis a, bool use_exten
       && dir
       && total_off * dir < minimum_space)
     total_off = minimum_space * dir;
-
+  
   /* FIXME: 100CM should relate to paper size.  */
   if (fabs (total_off) > 100 CM)
     {
@@ -118,90 +119,50 @@ Side_position_interface::general_side_position (Grob *me, Axis a, bool use_exten
   return scm_from_double (total_off);
 }
 
-/*
-  Cut & paste (ugh.)
-*/
-MAKE_SCHEME_CALLBACK (Side_position_interface, aligned_on_support_refpoints, 2);
+
+MAKE_SCHEME_CALLBACK (Side_position_interface, y_aligned_on_support_refpoints, 1);
 SCM
-Side_position_interface::aligned_on_support_refpoints (SCM smob, SCM axis)
+Side_position_interface::y_aligned_on_support_refpoints (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
-  Axis a = (Axis) scm_to_int (axis);
-
-  return general_side_position (me, a, false);
+  return general_side_position (unsmob_grob (smob), Y_AXIS, false); 
 }
 
-Real
-directed_round (Real f, Direction d)
-{
-  if (d < 0)
-    return floor (f);
-  else
-    return ceil (f);
-}
+
 
 /*
-  Callback that quantises in staff-spaces, rounding in the direction
-  of the elements "direction" elt property.
+  Position next to support, taking into account my own dimensions and padding.
+*/
 
-  Only rounds when we're inside the staff, as determined by
-  Staff_symbol_referencer::staff_radius () */
-MAKE_SCHEME_CALLBACK (Side_position_interface, quantised_position, 2);
+MAKE_SCHEME_CALLBACK (Side_position_interface, x_aligned_side, 1);
 SCM
-Side_position_interface::quantised_position (SCM element_smob, SCM)
+Side_position_interface::x_aligned_side (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
-
-  Direction d = get_grob_direction (me);
-
-  Grob *stsym = Staff_symbol_referencer::get_staff_symbol (me);
-  if (stsym)
-    {
-      Real p = Staff_symbol_referencer::get_position (me);
-      Real rp = directed_round (p, d);
-      Real rad = Staff_symbol_referencer::staff_radius (me) * 2;
-      int ip = int (rp);
-
-      Grob *head = me->get_parent (X_AXIS);
-
-      if (Staff_symbol_referencer::on_staffline (me, ip)
-	  && ((abs (ip) <= rad)
-	      || (Note_head::has_interface (head)
-		  && sign (Staff_symbol_referencer::get_position (head))
-		  == -d)))
-	{
-	  ip += d;
-	  rp += d;
-	}
-
-      return scm_from_double ((rp - p) * Staff_symbol_referencer::staff_space (me) / 2.0);
-    }
-  return scm_from_double (0.0);
+  return aligned_side (unsmob_grob (smob), X_AXIS);
 }
 
-/*
-  Position next to support, taking into account my own dimensions and padding.
-*/
-MAKE_SCHEME_CALLBACK (Side_position_interface, aligned_side, 2);
+MAKE_SCHEME_CALLBACK (Side_position_interface, y_aligned_side, 1);
 SCM
-Side_position_interface::aligned_side (SCM element_smob, SCM axis)
+Side_position_interface::y_aligned_side (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
-  Axis a = (Axis) scm_to_int (axis);
+  return aligned_side (unsmob_grob (smob), Y_AXIS);
+}
 
-  Direction d = get_grob_direction (me);
-  Real o = scm_to_double (aligned_on_support_extents (element_smob, axis));
+SCM
+Side_position_interface::aligned_side (Grob*me, Axis a)
+{
+  Direction dir = get_grob_direction (me);
 
+  Real o = scm_to_double (general_side_position (me, a, true));
   Interval iv = me->extent (me, a);
 
   if (!iv.is_empty ())
     {
-      if (!d)
+      if (!dir)
 	{
 	  programming_error ("direction unknown, but aligned-side wanted");
-	  d = DOWN;
+	  dir = DOWN;
 	}
-      o += -iv[-d];
+      o += -iv[-dir];
     }
 
   /*
@@ -209,39 +170,66 @@ Side_position_interface::aligned_side (SCM element_smob, SCM axis)
     position with padding, but it will put adjoining objects on a row if
     stuff sticks out of the staff a little.
   */
-  Grob *st = Staff_symbol_referencer::get_staff_symbol (me);
-  if (st && a == Y_AXIS
-      && scm_is_number (me->get_property ("staff-padding")))
+  Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
+  if (staff && a == Y_AXIS)
     {
-      Real padding
-	= Staff_symbol_referencer::staff_space (me)
-	* scm_to_double (me->get_property ("staff-padding"));
+      if (scm_is_number (me->get_property ("staff-padding")))
+	{
+	  Real padding
+	    = Staff_symbol_referencer::staff_space (me)
+	    * scm_to_double (me->get_property ("staff-padding"));
 
-      Grob *common = me->common_refpoint (st, Y_AXIS);
+	  Grob *common = me->common_refpoint (staff, Y_AXIS);
 
-      Interval staff_size = st->extent (common, Y_AXIS);
-      Real diff = d*staff_size[d] + padding - d * (o + iv[-d]);
-      o += d * max (diff, 0.0);
+	  Interval staff_size = staff->extent (common, Y_AXIS);
+	  Real diff = dir*staff_size[dir] + padding - dir * (o + iv[-dir]);
+	  o += dir * max (diff, 0.0);
+	}
+      
+      if (to_boolean (me->get_property ("quantize-position")))
+	{
+	  Grob *common = me->common_refpoint (staff, Y_AXIS);
+	  Real my_off = me->relative_coordinate (common, Y_AXIS);
+	  Real staff_off = staff->relative_coordinate (common, Y_AXIS);
+	  Real ss = Staff_symbol::staff_space (staff);
+	  Real position = 2 * (my_off + o - staff_off) / ss;
+	  Real rounded = directed_round (position, dir);
+	  Grob *head = me->get_parent (X_AXIS);
+      
+	  if (rounded <= Staff_symbol_referencer::staff_radius (me) 
+	      || (Note_head::has_interface (head)
+		  && sign (Staff_symbol_referencer::get_position (head)) == - dir))
+	    {
+	      o += dir *(rounded - position) * 0.5 * ss;
+	      if (Staff_symbol_referencer::on_staffline (me, int (rounded)))
+		o += dir * 0.5 * ss;
+	    }
+	}
     }
-
   return scm_from_double (o);
 }
 
 void
 Side_position_interface::set_axis (Grob *me, Axis a)
 {
-  me->add_offset_callback (Side_position_interface::aligned_side_proc, a);
+  me->internal_set_property (axis_offset_symbol (a),
+		    (a==X_AXIS)
+		    ? x_aligned_side_proc
+		    : y_aligned_side_proc);
 }
 
 // ugh. doesn't catch all variants. 
 Axis
 Side_position_interface::get_axis (Grob *me)
 {
-  if (me->has_offset_callback (Side_position_interface::aligned_side_proc, X_AXIS)
-      || me->has_offset_callback (Side_position_interface::aligned_side_proc, X_AXIS))
+  if (me->get_property_data (ly_symbol2scm ("X-offset"))
+      == Side_position_interface::x_aligned_side_proc)
     return X_AXIS;
+  else if (me->get_property_data (ly_symbol2scm ("Y-offset"))
+	   == Side_position_interface::y_aligned_side_proc)
+    return Y_AXIS;
 
-  return Y_AXIS;
+  return NO_AXES;
 }
 
 ADD_INTERFACE (Side_position_interface, "side-position-interface",
@@ -260,4 +248,5 @@ ADD_INTERFACE (Side_position_interface, "side-position-interface",
 	       "side-support-elements "
 	       "slur-padding "
 	       "staff-padding "
+	       "quantize-position "
 	       );
diff --git a/lily/simple-closure.cc b/lily/simple-closure.cc
new file mode 100644
index 0000000000..8a32a02871
--- /dev/null
+++ b/lily/simple-closure.cc
@@ -0,0 +1,106 @@
+/*
+  closure.cc -- chained closures.
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#include "lily-guile.hh"
+
+static scm_t_bits simple_closure_tag;
+
+bool
+is_simple_closure (SCM s)
+{
+  return (SCM_NIMP (s) && SCM_CELL_TYPE (s) == simple_closure_tag);
+}
+
+SCM
+simple_closure_expression (SCM smob)
+{
+  assert (is_simple_closure (smob));
+  return (SCM) SCM_CELL_WORD_1(smob);
+}
+
+SCM evaluate_with_simple_closure (SCM delayed_argument, SCM expr);
+
+SCM
+evaluate_args (SCM delayed_argument, SCM args)
+{
+  SCM new_args = SCM_EOL;
+  SCM *tail = &new_args;
+  for (SCM s = args; scm_is_pair (s); s = scm_cdr (s))
+    {
+      *tail = scm_cons (evaluate_with_simple_closure (delayed_argument, scm_car (s)),
+			SCM_EOL);
+      tail = SCM_CDRLOC (*tail);
+    }
+  
+  return new_args;
+}
+
+SCM
+evaluate_with_simple_closure (SCM delayed_argument,
+			      SCM expr)
+{
+  if (is_simple_closure (expr))
+    {
+      SCM inside = simple_closure_expression (expr);
+      return scm_apply_1 (scm_car (inside),
+			  delayed_argument,
+			  evaluate_args (delayed_argument, scm_cdr (inside)));
+    }
+  else if (!scm_is_pair (expr))
+    return expr;
+  else if (scm_car (expr) == ly_symbol2scm ("quote"))
+    return scm_cadr (expr);
+  else
+    {
+      return scm_apply_0 (scm_car (expr), evaluate_args (delayed_argument, scm_cdr (expr)));
+    }
+
+  assert (false);
+  return SCM_EOL;
+}
+
+LY_DEFINE(ly_simple_closure_p, "ly:simple-closure?",
+	  1,0,0, (SCM clos),
+	  "Type predicate.")
+{
+  return scm_from_bool (is_simple_closure (clos));
+}
+
+LY_DEFINE(ly_make_simple_closure, "ly:make-simple-closure",
+	  0, 0, 1, (SCM expr),
+	  "Make a simple closure. @var{expr} should be form of "
+	  "@code{(@var{func} @var{a1} @var{A2} ...)}, and will be invoked "
+	  "as @code{(@var{func} @var{delayed-arg} @var{a1} @var{a2} ... )}.")
+{
+  SCM z;
+
+  SCM_NEWSMOB(z, simple_closure_tag, expr);
+  return z;
+}
+ 
+int
+print_simple_closure (SCM s, SCM port, scm_print_state *)
+{
+  scm_puts ("#<simple-closure ", port);
+  scm_display (scm_cdr (s), port);
+  scm_puts (" >", port);
+  return 1;
+}
+
+
+void init_simple_closure ()
+{
+  simple_closure_tag = scm_make_smob_type ("simple-closure", 0);
+  scm_set_smob_mark (simple_closure_tag, scm_markcdr);
+  scm_set_smob_print (simple_closure_tag, print_simple_closure);
+};
+
+
+
+ADD_SCM_INIT_FUNC(simple_closure, init_simple_closure);
diff --git a/lily/slur-engraver.cc b/lily/slur-engraver.cc
index 3d48426464..4d6fd001dd 100644
--- a/lily/slur-engraver.cc
+++ b/lily/slur-engraver.cc
@@ -13,13 +13,13 @@
 #include "engraver.hh"
 #include "spanner.hh"
 #include "tie.hh"
+#include "warn.hh"
 
 /*
   It is possible that a slur starts and ends on the same note.  At
   least, it is for phrasing slurs: a note can be both beginning and
   ending of a phrase.
 */
-
 class Slur_engraver : public Engraver
 {
   Drul_array<Music *> events_;
@@ -112,7 +112,7 @@ Slur_engraver::acknowledge_extra_object (Grob_info info)
 
       if (slur)
 	{
-	  e->add_offset_callback (Slur::outside_slur_callback_proc, Y_AXIS);
+	  chain_offset_callback (e, Slur::outside_slur_callback_proc, Y_AXIS);
 	  e->set_object ("slur", slur->self_scm ());
 	}
     }
diff --git a/lily/slur.cc b/lily/slur.cc
index 807b30e782..2c8165ac72 100644
--- a/lily/slur.cc
+++ b/lily/slur.cc
@@ -149,21 +149,17 @@ Slur::add_extra_encompass (Grob *me, Grob *n)
 
 MAKE_SCHEME_CALLBACK (Slur, outside_slur_callback, 2);
 SCM
-Slur::outside_slur_callback (SCM grob, SCM axis)
+Slur::outside_slur_callback (SCM grob, SCM offset_scm)
 {
   Grob *script = unsmob_grob (grob);
-  Axis a = Axis (scm_to_int (axis));
-  (void) a;
-  assert (a == Y_AXIS);
-
   Grob *slur = unsmob_grob (script->get_object ("slur"));
 
   if (!slur)
-    return scm_from_int (0);
+    return offset_scm;
 
   Direction dir = get_grob_direction (script);
   if (dir == CENTER)
-    return scm_from_int (0);
+    return offset_scm;
 
   Grob *cx = script->common_refpoint (slur, X_AXIS);
   Grob *cy = script->common_refpoint (slur, Y_AXIS);
@@ -176,6 +172,9 @@ Slur::outside_slur_callback (SCM grob, SCM axis)
   Interval yext = robust_relative_extent (script, cy, Y_AXIS);
   Interval xext = robust_relative_extent (script, cx, X_AXIS);
 
+  yext.translate (robust_scm2double (offset_scm, 0));
+  
+  
   /* FIXME: slur property, script property?  */
   Real slur_padding = robust_scm2double (script->get_property ("slur-padding"),
 					 0.0);
@@ -211,15 +210,16 @@ Slur::outside_slur_callback (SCM grob, SCM axis)
 	    do_shift = true;
 	}
     }
-  Real offset = 0.0;
+
+  Real avoidance_offset = 0.0;
   if (do_shift)
     {
       for (int d = LEFT, k = 0; d <= RIGHT; d++, k++)
-	offset = dir * (max (dir * offset,
+	avoidance_offset = dir * (max (dir * avoidance_offset,
 			     dir * (ys[k] - yext[-dir] + dir * slur_padding)));
     }
 
-  return scm_from_double (offset);
+  return scm_from_double (scm_to_double (offset_scm) + avoidance_offset);
 }
 
 
diff --git a/lily/span-bar.cc b/lily/span-bar.cc
index 8e36450e29..95222b34c1 100644
--- a/lily/span-bar.cc
+++ b/lily/span-bar.cc
@@ -138,14 +138,12 @@ Span_bar::before_line_breaking (SCM smob)
   return SCM_UNSPECIFIED;
 }
 
-MAKE_SCHEME_CALLBACK (Span_bar, center_on_spanned_callback, 2);
+MAKE_SCHEME_CALLBACK (Span_bar, center_on_spanned_callback, 1);
 
 SCM
-Span_bar::center_on_spanned_callback (SCM element_smob, SCM axis)
+Span_bar::center_on_spanned_callback (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
-  (void) axis;
-  assert (scm_to_int (axis) == Y_AXIS);
+  Grob *me = unsmob_grob (smob);
   Interval i (get_spanned_interval (me));
 
   /* Bar_line::print delivers a barline of y-extent (-h/2, h/2), so
diff --git a/lily/staff-symbol-referencer.cc b/lily/staff-symbol-referencer.cc
index ea7d70f799..1a729e1e0f 100644
--- a/lily/staff-symbol-referencer.cc
+++ b/lily/staff-symbol-referencer.cc
@@ -105,12 +105,11 @@ LY_DEFINE (ly_grob_staff_position, "ly:grob-staff-position",
     return scm_from_double (pos);
 }
 
-/* should use offset callback!  */
-MAKE_SCHEME_CALLBACK (Staff_symbol_referencer, callback, 2);
+MAKE_SCHEME_CALLBACK (Staff_symbol_referencer, callback, 1);
 SCM
-Staff_symbol_referencer::callback (SCM element_smob, SCM)
+Staff_symbol_referencer::callback (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
+  Grob *me = unsmob_grob (smob);
 
   SCM pos = me->get_property ("staff-position");
   Real off = 0.0;
@@ -140,15 +139,15 @@ void
 Staff_symbol_referencer::set_position (Grob *me, Real p)
 {
   Grob *st = get_staff_symbol (me);
+  Real oldpos = 0.0;
   if (st && me->common_refpoint (st, Y_AXIS))
     {
-      Real oldpos = get_position (me);
-      me->set_property ("staff-position", scm_from_double (p - oldpos));
+      oldpos = get_position (me);
     }
-  else
-    me->set_property ("staff-position", scm_from_double (p));
 
-  me->add_offset_callback (Staff_symbol_referencer::callback_proc, Y_AXIS);
+  
+  Real ss = Staff_symbol_referencer::staff_space (me);
+  me->translate_axis ((p  - oldpos) * ss * 0.5, Y_AXIS);
 }
 
 /* Half of the height, in staff space, i.e. 2.0 for a normal staff. */
diff --git a/lily/stem-tremolo.cc b/lily/stem-tremolo.cc
index 2f642d2598..54b5a2243f 100644
--- a/lily/stem-tremolo.cc
+++ b/lily/stem-tremolo.cc
@@ -20,11 +20,11 @@
 
 /* TODO: lengthen stem if necessary  */
 
-MAKE_SCHEME_CALLBACK (Stem_tremolo, dim_callback, 2);
+MAKE_SCHEME_CALLBACK (Stem_tremolo, dim_callback, 1);
 
 /* todo: init with cons.  */
 SCM
-Stem_tremolo::dim_callback (SCM e, SCM)
+Stem_tremolo::dim_callback (SCM e)
 {
   Grob *se = unsmob_grob (e);
 
diff --git a/lily/stem.cc b/lily/stem.cc
index b3b2058fc8..2b771164ce 100644
--- a/lily/stem.cc
+++ b/lily/stem.cc
@@ -729,11 +729,11 @@ Stem::get_translated_flag (Grob *me)
 /*
   move the stem to right of the notehead if it is up.
 */
-MAKE_SCHEME_CALLBACK (Stem, offset_callback, 2);
+MAKE_SCHEME_CALLBACK (Stem, offset_callback, 1);
 SCM
-Stem::offset_callback (SCM element_smob, SCM)
+Stem::offset_callback (SCM smob)
 {
-  Grob *me = unsmob_grob (element_smob);
+  Grob *me = unsmob_grob (smob);
   Real r = 0.0;
 
   if (Grob *f = first_head (me))
diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm
index 314c1e4921..2cfd8c8e17 100644
--- a/scm/define-grobs.scm
+++ b/scm/define-grobs.scm
@@ -29,18 +29,16 @@
 	(meta . ((class . Item)
 		 (interfaces . (accidental-interface
 				font-interface))))))
-
+    
     (AccidentalSuggestion
      . (
-
 	(stencil . ,Accidental_interface::print)
-					
-	(X-offset-callbacks . (,Self_alignment_interface::centered_on_parent
-			       ,Self_alignment_interface::aligned_on_self))
+	(X-offset . ,Self_alignment_interface::centered_on_x_parent)
+	(self-X-offset . Self_alignment_interface::x_aligned_on_self)
 	(self-alignment-X . ,CENTER)
 	(cautionary . #t)
 	(cautionary-style . smaller)
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(cautionary-style . parentheses)
 	(direction . ,UP)
 	(staff-padding . 0.25)
@@ -67,7 +65,6 @@
     (Ambitus
      . (
 	(axes . (0 1))
-
 	(X-extent . ,Axis_group_interface::width)
 	(X-extent . ,Axis_group_interface::height)
 
@@ -92,7 +89,7 @@
 
 	(join-heads . #t)
 	(thickness . 2)
-	(X-offset-callbacks . (,Self_alignment_interface::centered_on_parent))
+	(X-offset . ,Self_alignment_interface::centered_on_x_parent)
 
 	(meta . ((class . Item)
 		 (interfaces . (ambitus-interface
@@ -102,7 +99,7 @@
      . (
 	(font-family . music)
 	(padding . 0.5)
-	(X-offset-callbacks . (,Side_position_interface::aligned_side))
+	(X-offset . ,Side_position_interface::x_aligned_side)
 	(direction . -1)
 	(cautionary-style . parentheses)
 
@@ -123,7 +120,7 @@
 	(stencil . ,Note_head::print)
 	(glyph-name . ,note-head::calc-glyph-name)
 	
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(meta . ((class . Item)
 		 (interfaces . (font-interface
 				note-head-interface
@@ -138,8 +135,8 @@
 	(X-extent . ,Arpeggio::width)
 	(stencil . ,Arpeggio::print)
 
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
-	(X-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Staff_symbol_referencer::callback)
+	(X-offset . ,Side_position_interface::x_aligned_side)
 	(direction . -1)
 	(padding . 0.5)
 	(staff-position . 0.0)
@@ -196,8 +193,8 @@
 	(direction . 1)
 	(font-family . roman)
 	(font-size . -2)
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
+	(X-offset . ,Self_alignment_interface::x_aligned_on_self)
 	(self-alignment-X . 1)
 
 	(meta .
@@ -214,7 +211,7 @@
 
 	(stencil . ,Text_interface::print)
 
-	(Y-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(Y-offset . ,Self_alignment_interface::y_aligned_on_self)
 	(direction . 1)
 	(font-family . number)
 
@@ -253,7 +250,7 @@
 
 	(stencil . ,Figured_bass_continuation::print)
 
-	(Y-offset-callbacks . (,Figured_bass_continuation::center_on_figures))
+	(Y-offset . ,Figured_bass_continuation::center_on_figures)
 	(meta . ((class . Spanner)
 		 (interfaces . (figured-bass-continuation-interface))
 		 ))))
@@ -399,7 +396,7 @@
 	(stencil . ,Text_interface::print)
 
 	(text . ,(make-musicglyph-markup "scripts.rcomma"))
-	(Y-offset-callbacks . (,Breathing_sign::offset_callback))
+	(Y-offset . ,Breathing_sign::offset_callback)
 	(break-visibility . ,begin-of-line-invisible)
 	(meta . ((class . Item)
 		 (interfaces . (break-aligned-interface
@@ -425,7 +422,7 @@
 			(first-note . (minimum-fixed-space . 5.0))
 			(next-note . (extra-space . 0.5))
 			(right-edge . (extra-space . 0.5))))
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(meta . ((class . Item)
 		 (interfaces . (clef-interface
 				staff-symbol-referencer-interface
@@ -475,8 +472,8 @@
 	(stencil . ,Text_interface::print)
 
 	(no-spacing-rods . #t)
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
 	(direction . 1)
 	(padding . 0.5)
 	(staff-padding . 0.5)
@@ -500,7 +497,7 @@
 	(break-visibility . ,end-of-line-visible)
 	(style . vaticana)
 	(neutral-direction . -1)
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(space-alist . (
 			(first-note . (minimum-fixed-space . 0.0))
 			(right-edge . (extra-space . 0.1))))
@@ -519,7 +516,7 @@
 	(positioning-done . ,Dot_column::calc_positioning_done) 
 	(X-extent . ,Axis_group_interface::width)
 	
-	(X-offset-callbacks . (,Dot_column::side_position))
+	(X-offset . ,Dot_column::side_position)
 	(meta . ((class . Item)
 		 (interfaces . (dot-column-interface
 				axis-group-interface))))))
@@ -557,9 +554,9 @@
 
 	(stencil . ,Text_interface::print)
 
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self
-			       ,Self_alignment_interface::centered_on_other_axis_parent))
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
+	(X-offset . ,Self_alignment_interface::centered_on_y_parent)
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(font-encoding . fetaNumber)
 	(self-alignment-X . 0)
 	(font-size . -2) 
@@ -575,7 +572,7 @@
     (DynamicLineSpanner
      . (
 	(axes . (1))
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(staff-padding . 0.1)
 	(padding . 0.6)
 	(avoid-slur . outside)
@@ -601,9 +598,9 @@
 	(stencil . ,Text_interface::print)
 	(direction . ,Script_interface::calc_direction)
 
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
 	(self-alignment-X . 0)
-	(Y-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(self-Y-offset . ,Self_alignment_interface::y_aligned_on_self)
 	(self-alignment-Y . 0)
 	(font-series . bold)
 	(font-encoding . fetaDynamic)
@@ -696,8 +693,9 @@
 	(stencil . ,Grid_line_interface::print)
 
 	(self-alignment-X . ,CENTER)
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self
-			       ,Self_alignment_interface::centered_on_parent))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
+	(X-offset . ,Self_alignment_interface::centered_on_x_parent)
+	
 	(layer . 0)
 	(meta . ((class . Item)
 		 (interfaces . (self-alignment-interface
@@ -716,7 +714,7 @@
 	(minimum-length . 2.0)
 	(bound-padding . 1.0)
 	(self-alignment-Y . 0)
-	(Y-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(self-Y-offset . ,Self_alignment_interface::y_aligned_on_self)
 	(meta . ((class . Spanner)
 		 (interfaces . (hairpin-interface
 				line-interface
@@ -730,7 +728,7 @@
 
 	(stencil . ,Horizontal_bracket::print)
 
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(padding . 0.2)
 	(staff-padding . 0.2)
 	(direction . -1)
@@ -743,8 +741,8 @@
     (InstrumentName
      . (
 	(breakable . #t)
-	(Y-offset-callbacks . (,Self_alignment_interface::aligned_on_self
-			       ,Side_position_interface::aligned_on_support_refpoints))
+	(self-Y-offset . ,Self_alignment_interface::y_aligned_on_self)
+	(Y-offset . ,Side_position_interface::y_aligned_on_support_refpoints)
 	;; This direction is for aligned_on_support_refpoints
 	;; (?) --hwn
 	(direction . 0)
@@ -776,7 +774,7 @@
 			(key-signature . (extra-space . 0.5))
 			(right-edge . (extra-space . 0.5))
 			(first-note . (fixed-space . 2.5))))
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(break-align-symbol . key-cancellation)
 	(break-visibility . ,begin-of-line-invisible)
 	(breakable . #t)
@@ -795,7 +793,7 @@
 			(staff-bar . (extra-space . 1.1))
 			(right-edge . (extra-space . 0.5))
 			(first-note . (fixed-space . 2.5))))
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(break-align-symbol . key-signature)
 	(break-visibility . ,begin-of-line-visible)
 	(breakable . #t)
@@ -921,7 +919,7 @@
 
 	(stencil . ,Text_interface::print)
 
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_parent))
+	(X-offset . ,Self_alignment_interface::aligned_on_x_parent)
 	(self-alignment-X . 0)
 	(word-space . 0.6)
 	(font-series . bold-narrow)
@@ -948,7 +946,7 @@
 
 	(stencil . ,Text_interface::print)
 
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(direction . 1)
 	(padding . 0.8)
 	(meta . ((class . Item)
@@ -959,7 +957,7 @@
 
     (MeasureGrouping
      . (
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 
 	(stencil . ,Measure_grouping::print)
 
@@ -977,7 +975,7 @@
 
 	(stencil . ,Multi_measure_rest::print)
 
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(staff-position . 0)
 	(expand-limit . 10)
 	(thick-thickness . 6.6)
@@ -995,9 +993,9 @@
      . (
 	(springs-and-rods . ,Multi_measure_rest::set_spacing_rods)
 	(stencil . ,Text_interface::print)
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self
-			       ,Self_alignment_interface::centered_on_other_axis_parent))
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(self-X-offset . ,Self_alignment_interface::y_aligned_on_self)
+	(X-offset . ,Self_alignment_interface::centered_on_y_parent)
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(self-alignment-X . 0)
 	(direction . 1)
 	(padding . 0.4)
@@ -1014,12 +1012,11 @@
 
     (MultiMeasureRestText
      . (
-
 	(stencil . ,Text_interface::print)
-
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self
-			       ,Self_alignment_interface::centered_on_other_axis_parent))
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(X-offset . ,Self_alignment_interface::centered_on_y_parent)
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
+	
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(self-alignment-X . 0)
 	(direction . 1)
 	(padding . 0.2)
@@ -1059,8 +1056,8 @@
 	(stencil . ,Note_head::print)
 	(stem-attachment . ,Note_head::calc_stem_attachment)
 	(glyph-name . ,note-head::calc-glyph-name) 
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
-	(X-offset-callbacks . (,Note_head::stem_x_shift))
+	(Y-offset . ,Staff_symbol_referencer::callback)
+	(X-offset . ,Note_head::stem_x_shift)
 	(meta . ((class . Item)
 		 (interfaces . (rhythmic-grob-interface
 				rhythmic-head-interface
@@ -1095,9 +1092,9 @@
      . (
 	(self-alignment-X . 0)
 	(break-visibility . ,begin-of-line-visible)
-	(X-offset-callbacks . (,Self_alignment_interface::centered_on_parent
-			       ,Self_alignment_interface::aligned_on_self))
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(X-offset . ,Self_alignment_interface::centered_on_x_parent)
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 
 	(stencil . ,Text_interface::print)
 
@@ -1116,7 +1113,7 @@
 
     (OttavaBracket
      . (
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 
 	(stencil . ,Ottava_bracket::print)
 
@@ -1205,9 +1202,9 @@
 
 	(stencil . ,Text_interface::print)
 
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self
-			       ,Self_alignment_interface::centered_on_other_axis_parent))
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
+	(X-offset . ,Self_alignment_interface::centered_on_y_parent)
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(self-alignment-X . 0)
 	(direction . 1)
 	(padding . 0.2)
@@ -1244,8 +1241,8 @@
 
 	(stencil . ,Text_interface::print)
 
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 
 	(after-line-breaking . ,shift-right-at-line-begin)
 
@@ -1279,12 +1276,7 @@
 	(stencil . ,Rest::print)
 	(X-extent . ,Rest::width)
 	(Y-extent . ,Rest::height)
-
-	(Y-offset-callbacks . (
-			       ,Staff_symbol_referencer::callback
-			       ,Rest::polyphonic_offset_callback
-			       ,Rest::y_offset_callback
-			       ))
+	(Y-offset . ,Rest::y_offset_callback)
 	(minimum-distance . 0.25)
 	(meta . ((class . Item)
 		 (interfaces . (font-interface
@@ -1310,7 +1302,7 @@
 	(padding . 0.20)
 	(staff-padding . 0.25)
 	;; (script-priority . 0) priorities for scripts, see script.scm
-	(X-offset-callbacks . (,Self_alignment_interface::centered_on_parent))
+	(X-offset . ,Self_alignment_interface::centered_on_x_parent)
 
 	(stencil . ,Script_interface::print)
 	(direction . ,Script_interface::calc_direction)
@@ -1410,7 +1402,7 @@
 
 	(font-series . bold)
 	(padding . 1.0)
-	(X-offset-callbacks . (,Side_position_interface::aligned_side))
+	(X-offset . ,Side_position_interface::x_aligned_side)
 	(direction . ,LEFT)
 	(meta . ((class . Item)
 		 (interfaces . (side-position-interface
@@ -1453,7 +1445,7 @@
 	(stencil . ,Text_interface::print)
 
 	(direction . 1)
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
 	(no-spacing-rods . #t)
 	(padding . 0.0) ;; padding relative to SostenutoPedalLineSpanner
 	(font-shape . italic)
@@ -1469,7 +1461,7 @@
 
 	(X-extent . ,Axis_group_interface::height)
 
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 
 	(padding . 1.2)
 	(minimum-space . 1.0)
@@ -1538,8 +1530,8 @@
 	;; We use the normal minima as minimum for the ideal lengths,
 	;; and the extreme minima as abolute minimum length.
 
-	(X-offset-callbacks . (,Stem::offset_callback))
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(X-offset . ,Stem::offset_callback)
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(meta . ((class . Item)
 		 (interfaces . (stem-interface
 				font-interface))))))
@@ -1561,7 +1553,7 @@
 	(self-alignment-X . 0)
 	(direction . 1)
 	(padding . 0.0)  ;; padding relative to SustainPedalLineSpanner
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
 	(meta . ((class . Item)
 		 (interfaces . (piano-pedal-interface
 				text-spanner-interface
@@ -1573,7 +1565,7 @@
      . (
 	(axes . (1))
 	(X-extent . ,Axis_group_interface::height)
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(padding . 1.2)
 	(staff-padding . 1.2)
 	(minimum-space . 1.0)
@@ -1606,7 +1598,7 @@
     (SystemStartBracket
      . (
 	(Y-extent . #f)
-	(X-offset-callbacks . (,(lambda (g a) -0.8)))
+	(X-offset . -0.8)
 	(stencil . ,System_start_delimiter::print)
 	(glyph . "bracket")
 	(collapse-height . 5.0)
@@ -1628,7 +1620,7 @@
      . (
 
 	(stencil . ,Text_interface::print)
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(font-size . -2)
 	(stem-attachment . (1.0 . 1.35))
 	(font-series . bold)
@@ -1643,7 +1635,7 @@
     (TextScript
      . (
 	(no-spacing-rods . #t)
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
 	(direction . -1)
 
 	;; sync with Fingering ?
@@ -1724,14 +1716,14 @@
 	(staff-padding . 1.0)
 	(padding . 0.5)
 	(direction . 1)
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(meta . ((class . Spanner)
 		 (interfaces . (text-spanner-interface
 				side-position-interface
 				font-interface))))))
 
     (TrillPitchAccidental
-     . ((X-offset-callbacks . (,Side_position_interface::aligned_side))
+     . ((X-offset . ,Side_position_interface::x_aligned_side)
 	(padding . 0.2)
 	(direction . ,LEFT)
 	(font-size . -4)
@@ -1743,7 +1735,7 @@
 				font-interface))))))
 
     (TrillPitchGroup
-     . ((X-offset-callbacks . (,Side_position_interface::aligned_side))
+     . ((X-offset . ,Side_position_interface::x_aligned_side)
 	(axes . (,X))
 	(font-size . -4)
 	(stencil . ,parenthesize-elements)
@@ -1761,7 +1753,7 @@
      . (
 	(stencil . ,Note_head::print)
 	(duration-log . 2)
-	(Y-offset-callbacks . (,Staff_symbol_referencer::callback))
+	(Y-offset . ,Staff_symbol_referencer::callback)
 	(font-size . -4)
 	(meta . ((class . Item)
 		 (interfaces . (item-interface
@@ -1796,7 +1788,7 @@
 	(self-alignment-X . 0)
 	(direction . 1)
 	(padding . 0.0)  ;; padding relative to UnaCordaPedalLineSpanner
-	(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
+	(self-X-offset . ,Self_alignment_interface::x_aligned_on_self)
 	(meta . ((class . Item)
 		 (interfaces . (text-interface
 				self-alignment-interface
@@ -1806,7 +1798,7 @@
      . (
 	(axes . (1))
 	(X-extent . ,Axis_group_interface::height)
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(padding . 1.2)
 	(staff-padding . 1.2)
 	(minimum-space . 1.0)
@@ -1839,8 +1831,7 @@
     (VerticalAxisGroup
      . (
 	(axes . (1))
-	(Y-offset-callbacks . (,Hara_kiri_group_spanner::force_hara_kiri_callback))
-
+	(Y-offset . ,Hara_kiri_group_spanner::force_hara_kiri_callback)
 	(Y-extent . ,Hara_kiri_group_spanner::y_extent)
 	(X-extent . ,Axis_group_interface::width)
 	(meta . ((class . Spanner)
@@ -1850,7 +1841,7 @@
     (VocalName
      . (
 	(breakable . #t)
-	(Y-offset-callbacks . (,Side_position_interface::aligned_on_support_refpoints))
+	(Y-offset . ,Side_position_interface::y_aligned_on_support_refpoints)
 	(direction . 0)
 	(space-alist . ((left-edge . (extra-space . 1.0))))
 	(break-align-symbol . instrument-name)
@@ -1872,7 +1863,7 @@
 	(direction . ,UP)
 	(padding . 1)
 	(font-encoding . fetaNumber)
-	(Y-offset-callbacks . (,Side_position_interface::aligned_side))
+	(Y-offset . ,Side_position_interface::y_aligned_side)
 	(thickness . 1.6)  ;;  linethickness
 	(edge-height . (2.0 . 2.0)) ;; staffspace;
 	(minimum-space . 5)
diff --git a/scm/safe-lily.scm b/scm/safe-lily.scm
index 26a326ef06..1f0ee16956 100644
--- a/scm/safe-lily.scm
+++ b/scm/safe-lily.scm
@@ -178,16 +178,9 @@
    Percent_repeat_item_interface::beat_slash
    Percent_repeat_item_interface::double_percent
    Piano_pedal_bracket::print
-   Rest::polyphonic_offset_callback
    Rest::print
    Script_interface::print
-   Self_alignment_interface::aligned_on_parent
-   Self_alignment_interface::aligned_on_self
-   Self_alignment_interface::centered_on_other_axis_parent
-   Self_alignment_interface::centered_on_parent
    Separating_group_spanner::set_spacing_rods
-   Side_position_interface::aligned_on_support_refpoints
-   Side_position_interface::aligned_side
    Slur::height
    Slur::print
    Spacing_spanner::set_springs
diff --git a/scm/script.scm b/scm/script.scm
index 18959121db..c6af502c76 100644
--- a/scm/script.scm
+++ b/scm/script.scm
@@ -11,17 +11,17 @@
 	   (direction . 1)))
          ("accent" .
 	  ((avoid-slur . around)
-	   (follow-into-staff . #t)
+	   (staff-padding . #f) (quantize-position . #t)
 	   (script-stencil . (feta . ("sforzato" .  "sforzato")))
 	   (side-relative-direction . -1)))	 
          ("espressivo" .
 	  ((avoid-slur . around)
-	   (follow-into-staff . #t)
+	   (staff-padding . #f) (quantize-position . #t)
 	   (script-stencil . (feta . ("espr" .  "espr")))
 	   (side-relative-direction . -1)))	 
 	 ("marcato" .
 	  ((script-stencil . (feta . ("dmarcato" . "umarcato")))
-	   (follow-into-staff . #t)
+	   (staff-padding . #f) (quantize-position . #t)
 	   (side-relative-direction .  -1)))
 	 ("staccatissimo" .
 	  ((avoid-slur . inside) 
@@ -85,16 +85,16 @@
 	   (script-priority . -100)))
 	 ("tenuto" .
 	  ((script-stencil . (feta . ("tenuto" . "tenuto")))
-	   (follow-into-staff . #t)
+	   (staff-padding . #f) (quantize-position . #t)
 	   (avoid-slur . inside)
 	   (side-relative-direction . -1)))
 	 ("comma" .
 	  ((script-stencil . (feta . ("lcomma" . "rcomma")))
-	   (follow-into-staff . #t)
+	   (staff-padding . #f) (quantize-position . #t)
 	   (direction . 1)))
 	 ("varcomma" .
 	  ((script-stencil . (feta . ("lvarcomma" . "rvarcomma")))
-	   (follow-into-staff . #t)
+	   (staff-padding . #f) (quantize-position . #t)
 	   (direction . 1)))
 	 ("upbow" .
 	  ((script-stencil . (feta . ("upbow" . "upbow")))
-- 
2.39.5