From: fred <fred>
Date: Wed, 27 Mar 2002 02:04:59 +0000 (+0000)
Subject: lilypond-1.5.28
X-Git-Tag: release/1.5.59~360
X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=6f8b95906563e3ccd2cb5d6ab371eaaafb305ef1;p=lilypond.git

lilypond-1.5.28
---

diff --git a/ChangeLog b/ChangeLog
index ded1e51b59..520a07988c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,50 @@
+2001-12-29  Han-Wen  <hanwen@cs.uu.nl>
+	
+	* VERSION: 1.5.28 released
+
+        * lily/parser.yy (My_lily_parser): Slightly kludgy warning for
+        illicit beams on [c4 c4] etc.
+
+        * lily/bar-check-iterator.cc (Bar_check_iterator): new
+        file. Make separate iterator for Bar_checks. Bar_check now happen
+        outside engravers, meaning that you can use them with
+        skipTypesetting. Associated changes in other files.
+        
+        * lily/new-spacing-spanner.cc (stem_dir_correction): removed
+        function
+        
+        * lily/spacing-spanner.cc (stem_dir_correction): removed function
+
+        * lily/include/grob.hh (unsmob_item, unsmob_spanner): Add functions
+
+        * lily/bar.cc (before_line_breaking): remove bar-line spacing code.
+
+        * lily/stem.cc (set_spacing_hints): removed function
+
+        * lily/note-spacing.cc (stem_dir_correction): new stem-direction
+        correction for spacing; now take vertical extents of the stem into
+        account.  
+
+        * lily/third-try.cc: More hacking to get spacing working.
+
+        * lily/note-spacing-engraver.cc: new file, Note_spacing_engraver
+        sits at staff level and creates note spacing objects. Scrap it
+        again, and document why.
+
+        * lily/include/group-interface.hh: rename functions. 
+
+2001-12-27  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* stepmake/stepmake/c++-rules.make:
+	* stepmake/stepmake/c-rules.make: Fixes for bison-1.28.
+
+2001-12-25  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* make/lilypond-vars.make: 
+	* scripts/ly2dvi.py (setup_environment): 
+	* scripts/lilypond-book.py (setup_environment): Also set tex
+	memory options.
+
 2001-12-24  Han-Wen Nienhuys  <hanwen@cs.uu.nl>
 
 	* VERSION: 1.5.27 released.
diff --git a/Documentation/regression-test.tely b/Documentation/regression-test.tely
index 42f5aad17e..6dbe5dd5b9 100644
--- a/Documentation/regression-test.tely
+++ b/Documentation/regression-test.tely
@@ -224,22 +224,28 @@ Grace note do weird things with timing. Fragile.
 
 @section Spacing
 
-@lilypondfile[printfilename]{stem-spacing.ly}
+@lilypondfile[printfilename]{spacing-accidental.ly}
 
-@lilypondfile[printfilename]{spacing-tight.ly}
+@lilypondfile[printfilename]{spacing-accidental-staffs.ly}
 
-@lilypondfile[printfilename]{spacing-natural.ly}
+@lilypondfile[printfilename]{spacing-folded-clef.ly}
 
-@lilypondfile[printfilename]{spacing-loose.ly}
+@lilypondfile[printfilename]{spacing-ended-voice.ly}
 
-@lilypondfile[printfilename]{spacing-accidental.ly}
+@lilypondfile[printfilename]{spacing-stem-direction.ly}
 
-@lilypondfile[printfilename]{spacing-accidental-staffs.ly}
+@lilypondfile[printfilename]{spacing-individual-tuning.ly}
 
 @lilypondfile[printfilename]{lyrics-bar.ly}
 
 @lilypondfile[printfilename]{non-empty-text.ly}
 
+@c @l ilypondfile[printfilename]{spacing-tight.ly}
+
+@c @l ilypondfile[printfilename]{spacing-natural.ly}
+
+@c @l ilypondfile[printfilename]{spacing-loose.ly}
+
 
 
 @section PianoStaff
diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely
index 2dbad10f96..2dcb351440 100644
--- a/Documentation/user/refman.itely
+++ b/Documentation/user/refman.itely
@@ -3977,6 +3977,12 @@ A bar check is entered using the bar symbol, @code{|}:
   \time 3/4 c2 e4 | g2.
 @end example
 
+@cindex skipTypesetting
+
+Bar checks are not affected by @code{skipTypesetting}, so if you are
+debugging a large score, you are advised to run it with skipTypesetting
+first to correct all overfull and underfull measures.
+
 @c .  {Point and click}
 @node Point and click
 @subsection Point and click
diff --git a/VERSION b/VERSION
index c939db38f5..390387bfc1 100644
--- a/VERSION
+++ b/VERSION
@@ -1,7 +1,7 @@
 PACKAGE_NAME=LilyPond
 MAJOR_VERSION=1
 MINOR_VERSION=5
-PATCH_LEVEL=27
+PATCH_LEVEL=28
 MY_PATCH_LEVEL=
 
 # use the above to send patches: MY_PATCH_LEVEL is always empty for a
diff --git a/input/no-notation/bar-check.ly b/input/no-notation/bar-check.ly
new file mode 100644
index 0000000000..c8a706a201
--- /dev/null
+++ b/input/no-notation/bar-check.ly
@@ -0,0 +1,12 @@
+
+\header {
+
+texidoc = "skipTypesetting doesn't affect bar checks."
+
+}
+
+\score { \notes {
+	\property Score.skipTypesetting = ##t
+	c4 c4
+	|
+	c4 c4 }}
diff --git a/input/no-notation/beam-warn.ly b/input/no-notation/beam-warn.ly
new file mode 100644
index 0000000000..02c86dab7f
--- /dev/null
+++ b/input/no-notation/beam-warn.ly
@@ -0,0 +1,10 @@
+
+\header	{
+
+texidoc = "The first duration following a beam-open request is checked if it is short enough."
+
+}
+
+\score {
+  \notes { [c4 c] }
+}
diff --git a/input/regression/auto-change.ly b/input/regression/auto-change.ly
index e377fbf3cf..cd26b7ce94 100644
--- a/input/regression/auto-change.ly
+++ b/input/regression/auto-change.ly
@@ -1,16 +1,18 @@
 \version "1.3.146"
 
-\header{
-texidoc="
-Auto change piano staff switches  voices  between up and down staves
-automatically rests are switched along with the coming note.
+\header {
+
+texidoc=" Auto change piano staff switches voices between up
+and down staves automatically rests are switched along with the coming
+note. When central C is reached, we don't switch (by default).
+
 "
 }
 
 \score {
 	\notes \context PianoStaff <
 	\context Staff = "up" {
-		\autochange Staff \context Voice = VA < \relative c' { g4 a  b c d r4 a g } >
+		\autochange Staff \context Voice = VA < \relative c' { g4 c e d c r4 a g } >
 	}
 	\context Staff = "down" {
 		\clef bass 
diff --git a/input/regression/spacing-ended-voice.ly b/input/regression/spacing-ended-voice.ly
new file mode 100644
index 0000000000..562c8de413
--- /dev/null
+++ b/input/regression/spacing-ended-voice.ly
@@ -0,0 +1,23 @@
+\header { texidoc = "
+
+A voicelet (a very short voice to get polyphonic chords correct)
+should not confuse the spacing engine."
+ }
+
+
+	\score {
+\notes {  \context Staff {
+  c4
+  <
+    \context Voice = I \relative c'' { \stemUp r4 dis4 }
+    \context Voice = III \relative c'' { \stemUp \shiftOn r4 bis  \shiftOff}
+    \context Voice = IV \relative c'' {
+      \stemDown
+      \shiftOn s4 gis }
+    \context Voice =  II \relative c' { \stemDown
+       % idem
+
+      r4 fis  }
+  >
+  c4
+}}}
diff --git a/input/regression/spacing-folded-clef2.ly b/input/regression/spacing-folded-clef2.ly
new file mode 100644
index 0000000000..95ce23f023
--- /dev/null
+++ b/input/regression/spacing-folded-clef2.ly
@@ -0,0 +1,23 @@
+\header {
+
+texidoc = "A clef can be folded below notes in a different staff, if
+there is space enough. With Paper_column molecule callbacks we can
+show where columns are in the score."
+}
+
+\score { \notes \relative c'' <
+	\context Staff = SA  { c4 c4 c4 \bar "|." }
+	\context Staff = SB { \clef bass c,2 \clef treble  c'2 }
+	>
+
+	\paper { linewidth = -1.
+
+	\translator { \ScoreContext
+	  NonMusicalPaperColumn \override #'molecule-callback = #Paper_column::brew_molecule
+	  PaperColumn \override #'molecule-callback = #Paper_column::brew_molecule	  
+	  NonMusicalPaperColumn \override #'font-family = #'roman
+	  PaperColumn \override #'font-family = #'roman	  
+
+	}
+	}}
+
diff --git a/input/regression/spacing-individual-tuning.ly b/input/regression/spacing-individual-tuning.ly
new file mode 100644
index 0000000000..1845bfc0d3
--- /dev/null
+++ b/input/regression/spacing-individual-tuning.ly
@@ -0,0 +1,22 @@
+\header {
+
+texidoc = "
+
+You can tune spacing of individual notes
+by setting @code{space-factor} in @code{NoteSpacing}.
+
+"
+}
+
+\score { \notes {
+\relative c'' { 
+c8 c8
+\property Voice.NoteSpacing \set #'space-factor = #0.7
+ c8 c8
+\property Voice.NoteSpacing \set #'space-factor = #1.4
+ c8 c8
+\property Voice.NoteSpacing \set #'space-factor = #1.0
+ c8 c8 
+} }
+\paper { linewidth = -1. }
+}
diff --git a/input/regression/spacing-stem-direction.ly b/input/regression/spacing-stem-direction.ly
new file mode 100644
index 0000000000..91aef48ea1
--- /dev/null
+++ b/input/regression/spacing-stem-direction.ly
@@ -0,0 +1,23 @@
+\version "1.3.146"
+
+\header{
+
+texidoc="
+
+LilyPond corrects for optical spacing of stems. The overlap between to
+adjacent stems of different direction is used as a measure for how
+much to correct."
+
+}
+
+\score { 
+  \context Voice \notes\relative c {
+  % make sure neutral is down.
+    \property Voice.Stem \override #'neutral-direction = #-1
+	\time 16/4  c''4 c c,  c' d, c' e, c' f, c' g c a c b c
+	
+  }
+  \paper {
+    linewidth=-1.0
+  }  
+}
diff --git a/lily/accidental-engraver.cc b/lily/accidental-engraver.cc
index 0f9b126eb3..016832382b 100644
--- a/lily/accidental-engraver.cc
+++ b/lily/accidental-engraver.cc
@@ -11,7 +11,6 @@
 #include "item.hh"
 #include "tie.hh"
 #include "rhythmic-head.hh"
-#include "timing-translator.hh"
 #include "engraver-group-engraver.hh"
 
 #include "staff-symbol-referencer.hh"
diff --git a/lily/align-interface.cc b/lily/align-interface.cc
index 4c5151b6d5..c8ef6c9f4e 100644
--- a/lily/align-interface.cc
+++ b/lily/align-interface.cc
@@ -65,7 +65,7 @@ Align_interface::align_to_fixed_distance (Grob *me , Axis a)
     }
   
   Link_array<Grob> elems
-    = Pointer_group_interface__extract_elements (me, (Grob*) 0, "elements");
+    = Pointer_group_interface__extract_grobs (me, (Grob*) 0, "elements");
 
   Real where_f=0;
 
@@ -150,7 +150,7 @@ Align_interface::align_elements_to_extents (Grob * me, Axis a)
 
   Link_array<Grob> elems;
   Link_array<Grob> all_grobs
-    = Pointer_group_interface__extract_elements (me, (Grob*) 0, "elements");
+    = Pointer_group_interface__extract_grobs (me, (Grob*) 0, "elements");
   for (int i=0; i < all_grobs.size (); i++) 
     {
       Interval y = all_grobs[i]->extent (me, a);
diff --git a/lily/arpeggio-engraver.cc b/lily/arpeggio-engraver.cc
index f366159596..5a0a67ca1b 100644
--- a/lily/arpeggio-engraver.cc
+++ b/lily/arpeggio-engraver.cc
@@ -85,7 +85,7 @@ Arpeggio_engraver::create_grobs ()
       
       for (int i = 0; i < stems_.size (); i++)
 	{
-	  Pointer_group_interface::add_element (arpeggio_, ly_symbol2scm ("stems"), stems_[i]);
+	  Pointer_group_interface::add_grob (arpeggio_, ly_symbol2scm ("stems"), stems_[i]);
 	}
       for (int i = 0; i < supports_.size (); i++)
 	{
diff --git a/lily/auto-change-iterator.cc b/lily/auto-change-iterator.cc
index 32b1b05608..59cad0bc07 100644
--- a/lily/auto-change-iterator.cc
+++ b/lily/auto-change-iterator.cc
@@ -119,7 +119,14 @@ Auto_change_iterator::process (Moment m)
     {
       Pitch p = ps[0];
       Direction s = Direction (sign (p.steps ()));
-      if (s != where_dir_)
+      /*
+	Don't change for central C.
+
+	TODO: make this tunable somehow. Sometimes, you'd want to
+	switch for C.C. as well.
+
+      */
+      if (s && s != where_dir_)
 	{
 	  where_dir_ = s;
 	  String to_id = (s >= 0) ?  "up" : "down";
diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc
index 34541a5a5d..85e21bda28 100644
--- a/lily/axis-group-interface.cc
+++ b/lily/axis-group-interface.cc
@@ -21,7 +21,7 @@ Axis_group_interface::add_element (Grob*me,Grob *e)
 	e->set_parent (me, a);
     }
 
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("elements"), e);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), e);
   me->add_dependency (e);
 }
 
diff --git a/lily/bar-check-iterator.cc b/lily/bar-check-iterator.cc
new file mode 100644
index 0000000000..bfcaf62327
--- /dev/null
+++ b/lily/bar-check-iterator.cc
@@ -0,0 +1,70 @@
+/*   
+
+     bar-check-iterator.cc -- implement Bar_check_iterator
+
+     source file of the GNU LilyPond music typesetter
+
+     (c) 2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+
+ */
+
+#include "simple-music-iterator.hh"
+#include "command-request.hh"
+#include "translator-group.hh"
+
+/*
+  Check bar checks. We do this outside the engravers so that you can
+  race through the score using skipTypesetting to correct durations.
+ */
+class Bar_check_iterator : Simple_music_iterator
+{
+public:
+  VIRTUAL_COPY_CONS(Bar_check_iterator);
+  virtual void process (Moment);
+  Bar_check_iterator( );
+  static SCM constructor_cxx_function;
+};
+
+IMPLEMENT_CTOR_CALLBACK (Bar_check_iterator);
+
+Music * get_barcheck ()
+{
+  Music *bc = new Music;
+  bc->set_mus_property ("iterator-ctor", Bar_check_iterator::constructor_cxx_function);
+  return bc;
+}
+
+Bar_check_iterator::Bar_check_iterator()
+{
+}
+
+void
+Bar_check_iterator::process (Moment m)
+{
+  Simple_music_iterator::process(m);
+  if (!m.to_bool ())
+    {
+      Translator_group *tr = report_to_l ();
+
+      SCM mp = tr->get_property ("measurePosition");
+      SCM sync= tr->get_property ("barCheckNoSynchronize");
+
+      Moment * where =unsmob_moment (mp);
+      if (!where)
+	return;
+      
+      if (where->main_part_)
+	{
+	  music_l ()->origin ()->warning (_f ("barcheck failed at: %s", 
+					    where->str ()));
+	}
+      
+      if (!to_boolean (sync))
+	{
+	  tr = tr->where_defined (ly_symbol2scm("measurePosition"));
+	  Moment zero;
+	  tr->set_property ("measurePosition", zero.smobbed_copy ());
+	}
+    }
+}
+    
diff --git a/lily/bar.cc b/lily/bar.cc
index bd38f9637c..497af0fa3a 100644
--- a/lily/bar.cc
+++ b/lily/bar.cc
@@ -159,27 +159,6 @@ Bar::before_line_breaking (SCM smob)
   if (! gh_equal_p (g, orig))
     me->set_grob_property ("glyph", g);
 
-  
-  /*
-    set a (pseudo) stem-direction, so we extra space is inserted
-    between stemup and barline.
-
-    TODO: should check if the barline is the leftmost object of the
-    break alignment.
-
-  */
-  if (gh_string_p (g))
-    {
-      Grob * col = item->column_l ();
-      SCM dirlist = col->get_grob_property ("dir-list");
-      SCM scmdir = gh_int2scm (-1); 
-      if (scm_memq (scmdir, dirlist) == SCM_BOOL_F)
-	{
-	  dirlist = gh_cons (scmdir, dirlist);
-	  col->set_grob_property ("dir-list", dirlist);
-	}
-    }
-  
   return SCM_UNSPECIFIED;
 }
   
diff --git a/lily/beam.cc b/lily/beam.cc
index 1c0ed8e545..3c12f0053f 100644
--- a/lily/beam.cc
+++ b/lily/beam.cc
@@ -40,7 +40,7 @@
 void
 Beam::add_stem (Grob*me, Grob*s)
 {
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("stems"), s);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("stems"), s);
   
   s->add_dependency (me);
 
@@ -130,7 +130,7 @@ Beam::get_default_dir (Grob*me)
   Direction d = DOWN;
 
   Link_array<Item> stems=
-	Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
+	Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
 
   for (int i=0; i <stems.size (); i++)
     do {
@@ -173,7 +173,7 @@ void
 Beam::set_stem_directions (Grob*me)
 {
   Link_array<Item> stems
-    =Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
+    =Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems");
   Direction d = Directional_element_interface::get (me);
   
   for (int i=0; i <stems.size (); i++)
@@ -206,7 +206,7 @@ Beam::consider_auto_knees (Grob *me)
 
       Direction d = Directional_element_interface::get (me);
       Link_array<Item> stems=
-	Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
+	Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
       
       Grob *common = me->common_refpoint (stems[0], Y_AXIS);
       for (int i=1; i < stems.size (); i++)
@@ -287,7 +287,7 @@ Beam::set_stem_shorten (Grob*m)
     shorten_f /= 2;
 
   Link_array<Item> stems=
-    Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
+    Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
 
   for (int i=0; i < stems.size (); i++)
     {
@@ -364,7 +364,7 @@ Beam::least_squares (SCM smob)
       // ugh -> use commonx
       Real x0 = first_visible_stem (me)->relative_coordinate (0, X_AXIS);
       Link_array<Item> stems=
-	Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
+	Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
 
       for (int i=0; i < stems.size (); i++)
 	{
@@ -637,7 +637,7 @@ Beam::check_stem_length_f (Grob*me,Real y, Real dy)
   Direction dir = Directional_element_interface::get (me);
 
   Link_array<Item> stems=
-    Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
+    Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
 
   for (int i=0; i < stems.size (); i++)
     {
@@ -678,7 +678,7 @@ Beam::set_stem_lengths (Grob *me)
 
   Real half_space = Staff_symbol_referencer::staff_space (me)/2;
   Link_array<Item> stems=
-    Pointer_group_interface__extract_elements (me, (Item*)0, "stems");
+    Pointer_group_interface__extract_grobs (me, (Item*)0, "stems");
 
   Grob *common = me->common_refpoint (stems[0], Y_AXIS);
   for (int i=1; i < stems.size (); i++)
@@ -754,7 +754,7 @@ void
 Beam::set_beaming (Grob*me,Beaming_info_list *beaming)
 {
   Link_array<Grob> stems=
-    Pointer_group_interface__extract_elements (me, (Grob*)0, "stems");
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems");
   
   Direction d = LEFT;
   for (int i=0; i  < stems.size (); i++)
@@ -946,7 +946,7 @@ Beam::brew_molecule (SCM smob)
     return SCM_EOL;
   Real x0,dx;
   Link_array<Item>stems = 
-    Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");  
+    Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems");  
   if (visible_stem_count (me))
     {
   // ugh -> use commonx
@@ -994,7 +994,7 @@ int
 Beam::forced_stem_count (Grob*me) 
 {
   Link_array<Item>stems = 
-    Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
+    Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems");
   int f = 0;
   for (int i=0; i < stems.size (); i++)
     {
@@ -1020,7 +1020,7 @@ int
 Beam::visible_stem_count (Grob*me) 
 {
   Link_array<Item>stems = 
-    Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
+    Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems");
   int c = 0;
   for (int i = stems.size (); i--;)
     {
@@ -1034,7 +1034,7 @@ Item*
 Beam::first_visible_stem (Grob*me) 
 {
   Link_array<Item>stems = 
-    Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
+    Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems");
   
   for (int i = 0; i < stems.size (); i++)
     {
@@ -1048,7 +1048,7 @@ Item*
 Beam::last_visible_stem (Grob*me) 
 {
   Link_array<Item>stems = 
-    Pointer_group_interface__extract_elements (me, (Item*) 0, "stems");
+    Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems");
   for (int i = stems.size (); i--;)
     {
       if (!Stem::invisible_b (stems[i]))
diff --git a/lily/break-align-item.cc b/lily/break-align-item.cc
index be0b995068..69ed53ecf3 100644
--- a/lily/break-align-item.cc
+++ b/lily/break-align-item.cc
@@ -86,7 +86,7 @@ Break_align_interface::do_alignment (Grob *me)
 
   Link_array<Grob> elems;
   Link_array<Grob> all_elems
-    = Pointer_group_interface__extract_elements (me, (Grob*)0,
+    = Pointer_group_interface__extract_grobs (me, (Grob*)0,
 						 "elements");
   
   for (int i=0; i < all_elems.size (); i++) 
diff --git a/lily/chord-name.cc b/lily/chord-name.cc
index 2c0e717a89..1cf1cc0a0c 100644
--- a/lily/chord-name.cc
+++ b/lily/chord-name.cc
@@ -20,7 +20,7 @@ MAKE_SCHEME_CALLBACK (Chord_name,after_line_breaking,1);
 SCM
 Chord_name::after_line_breaking (SCM smob)
 {
-  Item* me = dynamic_cast<Item*> (unsmob_grob (smob));
+  Item* me = unsmob_item (smob);
   assert (me);
     
   SCM s = me->get_grob_property ("begin-of-line-visible");
diff --git a/lily/clef-item.cc b/lily/clef-item.cc
index d7c323ee60..b1c38317cc 100644
--- a/lily/clef-item.cc
+++ b/lily/clef-item.cc
@@ -20,7 +20,7 @@ MAKE_SCHEME_CALLBACK (Clef,before_line_breaking,1);
 SCM
 Clef::before_line_breaking (SCM smob)
 {
-  Item * s = dynamic_cast<Item*> (unsmob_grob (smob));
+  Item * s = unsmob_item (smob);
 
   SCM glyph = s->get_grob_property ("glyph-name");
   
diff --git a/lily/command-request.cc b/lily/command-request.cc
index 13089e2743..6bf73e3657 100644
--- a/lily/command-request.cc
+++ b/lily/command-request.cc
@@ -10,13 +10,6 @@
 #include "debug.hh"
 #include "musical-request.hh"
 
-bool
-Barcheck_req::do_equal_b (Request const *r) const
-{
-  Barcheck_req  const*b = dynamic_cast<Barcheck_req const*> (r);
-  return b;
-}
-
 Tempo_req::Tempo_req ()
 {
   set_mus_property ("duration", Duration (2,0).smobbed_copy ());
@@ -101,7 +94,6 @@ Mark_req::do_equal_b (Request const * r) const
 
 
 ADD_MUSIC (Articulation_req);
-ADD_MUSIC (Barcheck_req);
 ADD_MUSIC (Break_req);
 ADD_MUSIC (Breathing_sign_req);
 ADD_MUSIC (Busy_playing_req);
diff --git a/lily/directional-element-interface.cc b/lily/directional-element-interface.cc
index ac2c40927d..b65fe31582 100644
--- a/lily/directional-element-interface.cc
+++ b/lily/directional-element-interface.cc
@@ -34,6 +34,9 @@ Directional_element_interface::set (Grob*me, Direction d)
 {
   SCM sd = gh_int2scm (d);
 
+  /*
+    Vain attempt to save some conses.
+   */
   if (me->get_grob_property ("direction") != sd)
     me->set_grob_property ("direction", sd);
 }
diff --git a/lily/dot-column.cc b/lily/dot-column.cc
index f59a32c20a..fc6edcb963 100644
--- a/lily/dot-column.cc
+++ b/lily/dot-column.cc
@@ -135,7 +135,7 @@ Dot_column::add_head (Grob * me, Grob *rh)
     {
       Side_position_interface::add_support (me,rh);
 
-      Pointer_group_interface::add_element (me, ly_symbol2scm ("dots"), d);
+      Pointer_group_interface::add_grob (me, ly_symbol2scm ("dots"), d);
       d->add_offset_callback (Dot_column::force_shift_callback_proc , Y_AXIS);
       Axis_group_interface::add_element (me, d);
     }
diff --git a/lily/grob.cc b/lily/grob.cc
index fd519adb74..c579990a7e 100644
--- a/lily/grob.cc
+++ b/lily/grob.cc
@@ -330,7 +330,7 @@ Grob::add_dependency (Grob*e)
 {
   if (e)
     {
-      Pointer_group_interface::add_element (this, ly_symbol2scm ("dependencies"),e);
+      Pointer_group_interface::add_grob (this, ly_symbol2scm ("dependencies"),e);
     }
   else
     programming_error ("Null dependency added");
diff --git a/lily/group-interface.cc b/lily/group-interface.cc
index 74bd4ad751..092170d606 100644
--- a/lily/group-interface.cc
+++ b/lily/group-interface.cc
@@ -54,7 +54,7 @@ Group_interface::count (Grob *me, String name)
 
 
 void
-Pointer_group_interface::add_element (Grob*me, SCM name, Grob*p) 
+Pointer_group_interface::add_grob (Grob*me, SCM name, Grob*p) 
 {
   Group_interface::add_thing (me, name, p->self_scm ());
 }
diff --git a/lily/hara-kiri-group-spanner.cc b/lily/hara-kiri-group-spanner.cc
index 11ac30e8ac..50dd0dbc2e 100644
--- a/lily/hara-kiri-group-spanner.cc
+++ b/lily/hara-kiri-group-spanner.cc
@@ -99,5 +99,5 @@ void
 Hara_kiri_group_spanner::add_interesting_item (Grob* me,Grob* n)
 {
   me->add_dependency (n);
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("items-worth-living"),n);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("items-worth-living"),n);
 }
diff --git a/lily/hyphen-spanner.cc b/lily/hyphen-spanner.cc
index c222091ef4..6b42b5b554 100644
--- a/lily/hyphen-spanner.cc
+++ b/lily/hyphen-spanner.cc
@@ -24,7 +24,7 @@ MAKE_SCHEME_CALLBACK (Hyphen_spanner,brew_molecule,1)
 SCM 
 Hyphen_spanner::brew_molecule (SCM smob)
 {
-  Spanner * sp = dynamic_cast<Spanner*> (unsmob_grob (smob));
+  Spanner * sp = unsmob_spanner (smob);
 
   Grob * common = sp;
   Direction d = LEFT;
diff --git a/lily/include/command-request.hh b/lily/include/command-request.hh
index fa7d7f4e63..8a1fe19278 100644
--- a/lily/include/command-request.hh
+++ b/lily/include/command-request.hh
@@ -40,13 +40,6 @@ protected:
   VIRTUAL_COPY_CONS (Music);
 };
 
-/// check if we're at start of a  measure.
-class Barcheck_req  : public Request  {
-public:
-  bool do_equal_b (Request const *) const;
-  VIRTUAL_COPY_CONS (Music);
-};
-
 class Breathing_sign_req : public Request {
   VIRTUAL_COPY_CONS (Music);
 };
diff --git a/lily/include/grob.hh b/lily/include/grob.hh
index 228a73fc60..aa0d1e13ce 100644
--- a/lily/include/grob.hh
+++ b/lily/include/grob.hh
@@ -181,6 +181,9 @@ public:
 };
 
 DECLARE_UNSMOB(Grob,grob);
+Spanner* unsmob_spanner (SCM );
+Item* unsmob_item (SCM );
+
 
 #endif // STAFFELEM_HH
 
diff --git a/lily/include/group-interface.hh b/lily/include/group-interface.hh
index 8df58bce5b..5db7948752 100644
--- a/lily/include/group-interface.hh
+++ b/lily/include/group-interface.hh
@@ -33,14 +33,14 @@ public:
 
 struct Pointer_group_interface : public Group_interface {
 public:
-  static void add_element (Grob*, SCM nm, Grob*e);
+  static void add_grob (Grob*, SCM nm, Grob*e);
 };
 /** 
   Put all score elements of ELT's property called NAME into an array,
   and return it.  */
 template<class T>
 Link_array<T>
-Pointer_group_interface__extract_elements (Grob const *elt, T *, const char* name)
+Pointer_group_interface__extract_grobs (Grob const *elt, T *, const char* name)
 {
   Link_array<T> arr;
 
diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh
index bafbe11578..20e4444760 100644
--- a/lily/include/lily-proto.hh
+++ b/lily/include/lily-proto.hh
@@ -184,6 +184,5 @@ class Translator_group;
 class Transposed_music;
 class Tremolo_req;
 class Type_swallow_translator;
-class Unfolded_repeat_iterator;
 class yyFlexLexer;
 #endif // LILY_PROTO_HH;
diff --git a/lily/include/my-lily-parser.hh b/lily/include/my-lily-parser.hh
index b82571b20c..c4f500cf5e 100644
--- a/lily/include/my-lily-parser.hh
+++ b/lily/include/my-lily-parser.hh
@@ -48,6 +48,9 @@ public:
 
   My_lily_lexer * lexer_p_;
   bool ignore_version_b_;
+
+  SCM last_beam_start_;
+  void beam_check (SCM); 
   
   Input here_input () const;
   void push_spot ();
diff --git a/lily/include/note-spacing.hh b/lily/include/note-spacing.hh
index 1905c72e85..cedd931120 100644
--- a/lily/include/note-spacing.hh
+++ b/lily/include/note-spacing.hh
@@ -18,8 +18,9 @@ public:
   static bool has_interface (Grob*);
 
   static Real get_spacing (Grob *me);
-
-  DECLARE_SCHEME_CALLBACK(before_line_breaking,(SCM));
+  static Real stem_dir_correction (Grob *me);  
+  static Item * right_column (Grob*);
+  static Item * left_column (Grob*);  
 };
 
 #endif /* NOTE_SPACING_HH */
diff --git a/lily/include/spacing-spanner.hh b/lily/include/spacing-spanner.hh
index b045401a02..f7a43ccd2b 100644
--- a/lily/include/spacing-spanner.hh
+++ b/lily/include/spacing-spanner.hh
@@ -20,7 +20,6 @@ public:
   static void do_measure (Grob*,Link_array<Grob> const &) ;
   static void stretch_to_regularity (Grob*, Array<Spring> *, Link_array<Grob> const &);
   DECLARE_SCHEME_CALLBACK (set_springs, (SCM ));
-  static Real stem_dir_correction (Grob*,Grob*,Grob*)  ;
   static Real default_bar_spacing (Grob*,Grob*,Grob*,Moment)  ;
   static Real note_spacing (Grob*,Grob*,Grob*,Moment)  ;
   static Real get_duration_space (Grob*,Moment dur, Moment shortest) ;
diff --git a/lily/include/timing-translator.hh b/lily/include/timing-translator.hh
index 8a170e3019..a201518067 100644
--- a/lily/include/timing-translator.hh
+++ b/lily/include/timing-translator.hh
@@ -20,12 +20,9 @@ class Timing_translator : public virtual Translator
 public:
   VIRTUAL_COPY_CONS (Translator);
   Timing_translator ();
-  Music *check_;
 
 protected: 
   virtual void initialize ();
-  virtual bool try_music (Music *req_l);
-  virtual void process_music ();
   virtual void stop_translation_timestep ();
   virtual void start_translation_timestep ();
 
diff --git a/lily/item.cc b/lily/item.cc
index 4447f3f64f..08c2e76de8 100644
--- a/lily/item.cc
+++ b/lily/item.cc
@@ -186,3 +186,9 @@ Item::do_derived_mark ()
     scm_gc_mark (broken_to_drul_[RIGHT]->self_scm ());
   return SCM_EOL;
 }
+
+Item*
+unsmob_item (SCM s )
+{
+  return dynamic_cast<Item*> (unsmob_grob (s));
+}
diff --git a/lily/key-engraver.cc b/lily/key-engraver.cc
index 445d197265..6f331d75c4 100644
--- a/lily/key-engraver.cc
+++ b/lily/key-engraver.cc
@@ -11,7 +11,6 @@
 #include "musical-request.hh"
 #include "item.hh"
 #include "bar.hh"
-#include "timing-translator.hh"
 #include "staff-symbol-referencer.hh"
 #include "translator-group.hh"
 #include "engraver.hh"
diff --git a/lily/line-of-score.cc b/lily/line-of-score.cc
index eaadc08fa5..22a9521178 100644
--- a/lily/line-of-score.cc
+++ b/lily/line-of-score.cc
@@ -51,7 +51,7 @@ void
 Line_of_score::typeset_grob (Grob * elem_p)
 {
   elem_p->pscore_l_ = pscore_l_;
-  Pointer_group_interface::add_element (this, ly_symbol2scm ("all-elements"),elem_p);
+  Pointer_group_interface::add_grob (this, ly_symbol2scm ("all-elements"),elem_p);
   scm_gc_unprotect_object (elem_p->self_scm ());
 }
 
@@ -469,7 +469,7 @@ Link_array<Grob>
 Line_of_score::column_l_arr ()const
 {
   Link_array<Grob> acs
-    = Pointer_group_interface__extract_elements (this, (Grob*) 0, "columns");
+    = Pointer_group_interface__extract_grobs (this, (Grob*) 0, "columns");
   bool bfound = false;
   for (int i= acs.size (); i -- ;)
     {
diff --git a/lily/lyric-extender.cc b/lily/lyric-extender.cc
index 57d790618f..5e4750221b 100644
--- a/lily/lyric-extender.cc
+++ b/lily/lyric-extender.cc
@@ -20,7 +20,7 @@ MAKE_SCHEME_CALLBACK (Lyric_extender,brew_molecule,1)
 SCM 
 Lyric_extender::brew_molecule (SCM smob) 
 {
-  Spanner *sp = dynamic_cast<Spanner*> (unsmob_grob (smob));
+  Spanner *sp = unsmob_spanner (smob);
 
   // ugh: refp
   Real leftext = sp->get_bound (LEFT)->extent (sp->get_bound (LEFT),
diff --git a/lily/multi-measure-rest.cc b/lily/multi-measure-rest.cc
index ac54514748..0ea2cf13f3 100644
--- a/lily/multi-measure-rest.cc
+++ b/lily/multi-measure-rest.cc
@@ -223,7 +223,7 @@ Multi_measure_rest::brew_molecule (SCM smob)
 void
 Multi_measure_rest::add_column (Grob*me,Item* c)
 {
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("columns"),c);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("columns"),c);
 
   add_bound_item (dynamic_cast<Spanner*> (me),c);
 }
diff --git a/lily/my-lily-parser.cc b/lily/my-lily-parser.cc
index 937c0f338a..f5221ad0e3 100644
--- a/lily/my-lily-parser.cc
+++ b/lily/my-lily-parser.cc
@@ -21,7 +21,7 @@ My_lily_parser::My_lily_parser (Sources * source_l)
   lexer_p_ = 0;
   default_duration_ = Duration (2,0);
   error_level_i_ = 0;
-
+  last_beam_start_ = SCM_EOL;
 
   default_header_p_ =0;
 }
diff --git a/lily/new-spacing-spanner.cc b/lily/new-spacing-spanner.cc
index 9ec228cad1..4107f1deba 100644
--- a/lily/new-spacing-spanner.cc
+++ b/lily/new-spacing-spanner.cc
@@ -27,7 +27,6 @@ public:
   static void stretch_to_regularity (Grob*, Array<Spring> *, Link_array<Grob> const &);
   static void breakable_column_spacing (Item* l, Item *r);
   DECLARE_SCHEME_CALLBACK (set_springs, (SCM ));
-  static Real stem_dir_correction (Grob*,Grob*,Grob*)  ;
   static Real default_bar_spacing (Grob*,Grob*,Grob*,Moment)  ;
   static Real note_spacing (Grob*,Grob*,Grob*,Moment)  ;
   static Real get_duration_space (Grob*,Moment dur, Moment shortest) ;
@@ -187,8 +186,6 @@ cout << "params for cols " << Paper_column::rank_i (l) << " " << Paper_column::r
 	      hinterfleisch += -headwid + Separation_item::my_width (lm)[RIGHT] -
 		0.5 * Separation_item::my_width (rm)[LEFT];
 
-
-	      hinterfleisch += stem_dir_correction (me, l, r);
 	    }
 
 	  // ? why.
@@ -478,55 +475,6 @@ New_spacing_spanner::note_spacing (Grob*me, Grob *lc, Grob *rc,
   return dist;
 }
 
-
-/**
-   Correct for optical illusions. See [Wanske] p. 138. The combination
-   up-stem + down-stem should get extra space, the combination
-   down-stem + up-stem less.
-
-   This should be more advanced, since relative heights of the note
-   heads also influence required correction.
-
-   Also might not work correctly in case of multi voices or staff
-   changing voices
-
-   TODO: lookup correction distances?  More advanced correction?
-   Possibly turn this off?
-
-   TODO: have to check wether the stems are in the same staff.
-
-   This routine reads the DIR-LIST property of both its L and R arguments.  */
-Real
-New_spacing_spanner::stem_dir_correction (Grob*me, Grob*l, Grob*r) 
-{
-  SCM dl = l->get_grob_property ("dir-list");
-  SCM dr = r->get_grob_property ("dir-list");
-  
-  if (scm_ilength (dl) != 1 || scm_ilength (dr) != 1)
-    return 0.;
-
-  dl = ly_car (dl);
-  dr = ly_car (dr);
-
-  assert (gh_number_p (dl) && gh_number_p (dr));
-  int d1 = gh_scm2int (dl);
-  int d2 = gh_scm2int (dr);
-
-  if (d1 == d2)
-    return 0.0;
-
-
-  Real correction = 0.0;
-  Real ssc = gh_scm2double (me->get_grob_property ("stem-spacing-correction"));
-
-  if (d1 && d2 && d1 * d2 == -1)
-    {
-      correction = d1 * ssc;
-    }
-  else
-    programming_error ("Stem directions not set correctly for optical correction");
-  return correction;
-}
   
 
 MAKE_SCHEME_CALLBACK (New_spacing_spanner, set_springs,1);
diff --git a/lily/note-column.cc b/lily/note-column.cc
index 95b2cd67ed..5c1b664bbe 100644
--- a/lily/note-column.cc
+++ b/lily/note-column.cc
@@ -47,7 +47,7 @@ Item *
 Note_column::stem_l (Grob*me) 
 {
   SCM s = me->get_grob_property ("stem");
-  return  dynamic_cast<Item*> (unsmob_grob (s));
+  return  unsmob_item (s);
 }
   
 Slice
@@ -99,7 +99,7 @@ Note_column::add_head (Grob*me,Grob *h)
     }
   else if (Note_head::has_interface (h))
     {
-      Pointer_group_interface::add_element (me, ly_symbol2scm ("note-heads"),h);
+      Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-heads"),h);
     }
   Axis_group_interface::add_element (me, h);
 }
diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc
index 0628ffab82..4b0d784b18 100644
--- a/lily/note-spacing.cc
+++ b/lily/note-spacing.cc
@@ -14,6 +14,7 @@
 #include "grob.hh"
 #include "note-column.hh"
 #include "warn.hh"
+#include "stem.hh"
 
 bool
 Note_spacing::has_interface (Grob* g)
@@ -21,8 +22,6 @@ Note_spacing::has_interface (Grob* g)
   return g && g->has_interface (ly_symbol2scm ("note-spacing-interface"));
 }
 
-
-
 Real
 Note_spacing::get_spacing (Grob *me)
 {
@@ -40,6 +39,9 @@ Note_spacing::get_spacing (Grob *me)
 	  if (d == RIGHT)
 	    {
 	      Grob * accs = Note_column::accidentals (it);
+	      if (!accs)
+		accs = Note_column::accidentals (it->get_parent (X_AXIS));
+	      
 	      if (accs)
 		extents[d].unite (accs->extent (it->column_l (), X_AXIS));
 	    }
@@ -60,29 +62,149 @@ Note_spacing::get_spacing (Grob *me)
   return dx;
 }
 
+Item *
+Note_spacing::left_column (Grob *me)
+{
+  if (me->immutable_property_alist_ == SCM_EOL)
+    return 0;
+  
+  return dynamic_cast<Item*> (me)->column_l ();
+}
 
-MAKE_SCHEME_CALLBACK(Note_spacing, before_line_breaking, 1)
-SCM
-Note_spacing::before_line_breaking (SCM g)
+/*
+  Compute the column of the right-items.  This is a big function,
+since RIGHT-ITEMS may span more columns (eg. if a clef if inserted,
+this will add a new columns to RIGHT-ITEMS. Here we look at the
+columns, and return the left-most. If there are multiple columns, we
+prune RIGHT-ITEMS.
+   
+ */
+Item *
+Note_spacing::right_column (Grob*me)
 {
-  Grob * me = unsmob_grob (g);
+  /*
+    ugh. should have generic is_live() method?
+   */
+  if (me->immutable_property_alist_ == SCM_EOL)
+    return 0;
+  
   SCM right = me->get_grob_property ("right-items");
+  Item *mincol = 0;
+  int min_rank = INT_MAX;
+  bool prune = false;
+  for (SCM s = right ; gh_pair_p (s) ; s = gh_cdr (s))
+    {
+      Item * ri = unsmob_item (gh_car (s));
+
+      Item * col = ri->column_l ();
+      int rank = Paper_column::rank_i (col);
+
+      if (rank < min_rank)
+	{
+	  min_rank = rank;
+	  if (mincol)
+	    prune = true;
 
-  if (gh_pair_p (right))
-    right = gh_car (right);
+	  mincol = col;
+	}
+    }
   
-  Grob *right_grob = unsmob_grob (right);
+  if (prune)
+    {
+      // I'm a lazy bum. We could do this in-place.
+      SCM newright  = SCM_EOL;
+      for (SCM s = right ; gh_pair_p (s) ; s =gh_cdr (s))
+	{
+	  if (unsmob_item (gh_car (s))->column_l () == mincol)
+	    newright = gh_cons (gh_car (s), newright);
+	}
 
-  Item * ri = dynamic_cast<Item*> (right_grob);
-  if (!ri)
+      me->set_grob_property ("right-items", newright);
+    }
+  
+  if (!mincol)
     {
+      /*
       int r = Paper_column::rank_i (dynamic_cast<Item*>(me)->column_l ());
       programming_error (_f("Spacing wish column %d has no right item.", r));
+      */
+
+      return 0;
     }
-  else
+
+  return mincol;
+}
+
+/**
+   Correct for optical illusions. See [Wanske] p. 138. The combination
+   up-stem + down-stem should get extra space, the combination
+   down-stem + up-stem less.
+
+   TODO: have to check wether the stems are in the same staff.
+
+   TODO: also correct for bar lines in RIGHT-ITEMS.  Should check if
+   the barline is the leftmost object of the break alignment.
+
+*/
+Real
+Note_spacing::stem_dir_correction (Grob*me) 
+{
+  Drul_array<Direction> stem_dirs(CENTER,CENTER);
+  Drul_array<Interval> posns;
+  Drul_array<SCM> props(me->get_grob_property ("left-items"),
+			me->get_grob_property ("right-items"));
+
+  stem_dirs[LEFT] = stem_dirs[RIGHT] = CENTER;
+  Interval intersect;
+  bool correct = true;
+  Direction d = LEFT;
+  do
     {
-      me->set_grob_property ("right-column", ri->column_l ()->self_scm());
+      for (SCM  s = props[d]; gh_pair_p (s); s = gh_cdr (s))
+	{
+	  Item * it= dynamic_cast<Item*> (unsmob_grob (gh_car(s)));
+
+	  Grob *stem = Note_column::stem_l (it);
+
+	  if (!stem || Stem::invisible_b (stem))
+	    {
+	      correct = false;
+	      goto exit_loop ;
+	    }
+
+	  Direction sd = Stem::get_direction (stem);
+	  if (stem_dirs[d] && stem_dirs[d] != sd)
+	    {
+	      correct = false;
+	      goto exit_loop;
+	    }
+	  stem_dirs[d] = sd;
+
+	  Real chord_start = Stem::head_positions (stem)[sd];
+	  Real stem_end = Stem::stem_end_position (stem);
+	  
+	  posns[d] = Interval(chord_start<?stem_end, chord_start>? stem_end);
+	}
     }
+  while (flip (&d) != LEFT);
   
-  return SCM_UNSPECIFIED;
+  intersect = posns[LEFT];  
+  intersect.intersect(posns[RIGHT]);
+  correct = correct && !intersect.empty_b ();
+  correct = correct && (stem_dirs[LEFT] *stem_dirs[RIGHT] == -1);
+  
+ exit_loop:
+  if(!correct)
+    return 0.0;
+
+  /*
+    Ugh. 7 is hardcoded.
+   */
+  Real correction = abs (intersect.length ());
+  correction = (correction/7) <? 1.0;
+  correction *= stem_dirs[LEFT] ;
+  correction *= gh_scm2double (me->get_grob_property ("stem-spacing-correction"));
+
+  return correction;
 }
+ 
diff --git a/lily/parser.yy b/lily/parser.yy
index 0a7437fead..0de5be0bf5 100644
--- a/lily/parser.yy
+++ b/lily/parser.yy
@@ -284,7 +284,7 @@ yylex (YYSTYPE *s,  void * v_l)
 %type <scm>	identifier_init 
 
 %type <scm> steno_duration optional_notemode_duration multiplied_duration
-%type <scm>  explicit_duration
+%type <scm>  verbose_duration
 	
 %type <reqvec>  pre_requests post_requests
 %type <request> gen_text_def
@@ -468,7 +468,7 @@ identifier_init:
 		$$ = $1->self_scm ();
 		scm_gc_unprotect_object ($$);
 	}
-	| explicit_duration {
+	| verbose_duration {
 		$$ = $1;
 	}
 	| number_expression {
@@ -1112,6 +1112,11 @@ command_element:
 		$$-> set_spot (THIS->here_input ());
 		$1-> set_spot (THIS->here_input ());
 	}
+	| '|'      {
+		extern Music * get_barcheck();
+		$$ = get_barcheck ();
+		$$->set_spot (THIS->here_input ());
+	}
 	| BAR STRING  			{
 		Music *t = set_property_music (ly_symbol2scm ("whichBar"), $2);
 
@@ -1206,9 +1211,6 @@ shorthand_command_req:
 	| hyphen_req {
 		$$ = $1;
 	}
-	| '|'				{
-		$$ = new Barcheck_req;
-	}
 	| '~'	{
 		$$ = new Tie_req;
 	}
@@ -1217,6 +1219,9 @@ shorthand_command_req:
 		b->set_span_dir (START);
 		b->set_mus_property ("span-type", ly_str02scm ("beam"));
 		$$ =b;
+
+
+		THIS->last_beam_start_ = b->self_scm ();
 	}
 	| ']'		{
 		Span_req*b= new Span_req;
@@ -1449,7 +1454,7 @@ explicit_pitch:
 	}
 	;
 
-explicit_duration:
+verbose_duration:
 	DURATION embedded_scm 	{
 		$$ = $2;
 		if (!unsmob_duration ($2))
@@ -1602,20 +1607,25 @@ duration_length:
 	multiplied_duration {
 		$$ = $1;
 	}
-	| explicit_duration {
+	| verbose_duration {
 		$$ = $1;
 	}	
 	;
 
 optional_notemode_duration:
 	{
-		$$ = THIS->default_duration_.smobbed_copy ();
+		Duration dd = THIS->default_duration_;
+		$$ = dd.smobbed_copy ();
+
+		THIS->beam_check ($$);
 	}
 	| multiplied_duration	{
 		$$ = $1;
 		THIS->default_duration_ = *unsmob_duration ($$);
+
+		THIS->beam_check ($$);
 	}
-	| explicit_duration {
+	| verbose_duration {
 		$$ = $1;
 		THIS->default_duration_ = *unsmob_duration ($$);
 	}	
@@ -2067,3 +2077,24 @@ My_lily_parser::do_yyparse ()
 }
 
 
+/*
+Should make this optional?    It will also complain when you do
+
+	[s4]
+
+which is entirely legitimate.
+
+Or we can scrap it. Barchecks should detect wrong durations, and
+skipTypesetting speeds it up a lot.
+*/
+void
+My_lily_parser::beam_check (SCM dur)
+{
+  Duration *d = unsmob_duration (dur);
+  if (unsmob_music (last_beam_start_) && d->duration_log () <= 2)
+    {
+      Music * m = unsmob_music (last_beam_start_);
+      m->origin ()->warning (_("Suspect duration found following this beam"));
+    }
+  last_beam_start_ = SCM_EOL;
+}
diff --git a/lily/porrectus.cc b/lily/porrectus.cc
index e05da73520..1ef6002699 100644
--- a/lily/porrectus.cc
+++ b/lily/porrectus.cc
@@ -47,7 +47,7 @@ Porrectus::get_left_head (Grob *me)
     }
   else
     {
-      Item *left_head = dynamic_cast<Item*> (unsmob_grob (left_head_scm));
+      Item *left_head = unsmob_item (left_head_scm);
       return left_head;
     }
 }
@@ -77,7 +77,7 @@ Porrectus::get_right_head (Grob *me)
     }
   else
     {
-      Item *right_head = dynamic_cast<Item*> (unsmob_grob (right_head_scm));
+      Item *right_head = unsmob_item (right_head_scm);
       return right_head;
     }
 }
diff --git a/lily/request-chord.cc b/lily/request-chord.cc
index 50835d2946..170d4996df 100644
--- a/lily/request-chord.cc
+++ b/lily/request-chord.cc
@@ -16,8 +16,6 @@ Request_chord::Request_chord ()
 		    Request_chord_iterator::constructor_cxx_function);
 }
 
-
-
 Pitch
 Request_chord::to_relative_octave (Pitch last)
 {
@@ -43,6 +41,4 @@ Request_chord::start_mom () const
   return Music::start_mom ();
 }
 
-
-
 ADD_MUSIC (Request_chord);
diff --git a/lily/rest-collision.cc b/lily/rest-collision.cc
index a521f8aaf9..c3caa235c1 100644
--- a/lily/rest-collision.cc
+++ b/lily/rest-collision.cc
@@ -47,7 +47,7 @@ void
 Rest_collision::add_column (Grob*me,Grob *p)
 {
   me->add_dependency (p);
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("elements"), p);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), p);
 
   /*
     only add callback for the rests, since we don't move anything else.
diff --git a/lily/rhythmic-column-engraver.cc b/lily/rhythmic-column-engraver.cc
index 84bd2ae16c..905af21186 100644
--- a/lily/rhythmic-column-engraver.cc
+++ b/lily/rhythmic-column-engraver.cc
@@ -15,6 +15,35 @@
 #include "dot-column.hh"
 #include "musical-request.hh"
 #include "item.hh"
+#include "group-interface.hh"
+
+
+
+/*
+  this engraver  glues together stems, rests and note heads into a NoteColumn
+  grob.
+
+  It also generates spacing objects.  Originally, we have tried to
+  have the spacing functionality at different levels.
+  
+  - by simply using the sequence of Separation-item as
+  spacing-sequences (at staff level). Unfortunately, this fucks up if
+  there are different kinds of tuplets in different voices (8th and
+  8ths triplets combined made the program believe there were 1/12 th
+  notes.).
+
+  Doing it in a separate engraver using timing info is generally
+  complicated (start/end time management), and fucks up if a voice
+  changes staff.
+
+  Now we do it from here again. This has the problem that voices can
+  appear and disappear at will, leaving lots of loose ends (the note
+  spacing engraver don't know where to connect the last note of the
+  voice on the right with), but we don't complain about those, and let
+  the default spacing do its work.
+
+ */
+
 
 class Rhythmic_column_engraver :public Engraver
 {
@@ -58,6 +87,19 @@ Rhythmic_column_engraver::create_grobs ()
 	  note_column_ = new Item (get_property ("NoteColumn"));
 	  Note_column::set_interface (note_column_);
 	  announce_grob (note_column_, 0);
+
+
+         spacing_ = new Item (get_property ("NoteSpacing"));
+         spacing_->set_grob_property ("left-items", gh_cons (note_column_->self_scm (), SCM_EOL));
+         announce_grob (spacing_, 0);
+
+         if (last_spacing_)
+           {
+	     Pointer_group_interface::add_grob (last_spacing_,
+						ly_symbol2scm ("right-items" ),
+						note_column_);
+           }
+
 	}
 
       for (int i=0; i < rhead_l_arr_.size (); i++)
@@ -133,7 +175,7 @@ Rhythmic_column_engraver::start_translation_timestep ()
 
 ENTER_DESCRIPTION(Rhythmic_column_engraver,
 /* descr */       "Generates NoteColumn, an objects that groups stems, noteheads and rests.",
-/* creats*/       "NoteColumn",
+/* creats*/       "NoteColumn NoteSpacing",
 /* acks  */       "stem-interface rhythmic-head-interface dot-column-interface",
 /* reads */       "",
 /* write */       "");
diff --git a/lily/rhythmic-head.cc b/lily/rhythmic-head.cc
index 849a849e43..889b9112c7 100644
--- a/lily/rhythmic-head.cc
+++ b/lily/rhythmic-head.cc
@@ -18,7 +18,7 @@ Item*
 Rhythmic_head::dots_l (Grob*me) 
 {
   SCM s = me->get_grob_property ("dot");
-  return dynamic_cast<Item*> (unsmob_grob (s));
+  return unsmob_item (s);
 }
 
 int
@@ -32,7 +32,7 @@ Item*
 Rhythmic_head::stem_l (Grob*me) 
 {
   SCM s = me->get_grob_property ("stem");
-  return dynamic_cast<Item*> (unsmob_grob (s));
+  return unsmob_item (s);
 }
 
 int
diff --git a/lily/scm-hash.cc b/lily/scm-hash.cc
index 5a4d27018a..7fc08cd6ef 100644
--- a/lily/scm-hash.cc
+++ b/lily/scm-hash.cc
@@ -67,10 +67,10 @@ Scheme_hash_table::print_smob (SCM s, SCM p, scm_print_state*)
   assert (unsmob (s));
   char str[1000];
   sprintf (str, "#<Scheme_hash_table 0x%0lx ", SCM_UNPACK(s));
-   Scheme_hash_table *me = (Scheme_hash_table*) SCM_CELL_WORD_1 (s);
-   scm_display (me->hash_tab_, p);      
-   scm_puts ("> ",p);        
-   return 1;
+  Scheme_hash_table *me = (Scheme_hash_table*) SCM_CELL_WORD_1 (s);
+  scm_display (me->hash_tab_, p);      
+  scm_puts ("> ",p);        
+  return 1;
 }
 
 bool
diff --git a/lily/score-engraver.cc b/lily/score-engraver.cc
index 6aad0e533e..74ca09b651 100644
--- a/lily/score-engraver.cc
+++ b/lily/score-engraver.cc
@@ -289,15 +289,15 @@ Score_engraver::acknowledge_grob (Grob_info gi)
 {
   if (Staff_spacing::has_interface (gi.grob_l_))
     {
-      Pointer_group_interface::add_element (command_column_l_,
+      Pointer_group_interface::add_grob (command_column_l_,
 					    ly_symbol2scm ("spacing-wishes"),
 					    gi.grob_l_);
     }
   if (Note_spacing::has_interface (gi.grob_l_))
     {
-      Pointer_group_interface::add_element (musical_column_l_,
-					    ly_symbol2scm ("spacing-wishes"),
-					    gi.grob_l_);
+      Pointer_group_interface::add_grob (musical_column_l_,
+					 ly_symbol2scm ("spacing-wishes"),
+					 gi.grob_l_);
     }
 }
 
diff --git a/lily/script-column.cc b/lily/script-column.cc
index 7d8cdc7467..c45ee3c92c 100644
--- a/lily/script-column.cc
+++ b/lily/script-column.cc
@@ -18,7 +18,7 @@ Script_column::add_staff_sided (Grob *me, Item *i)
   if (!gh_number_p (p))
     return;
 
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("scripts"),i);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("scripts"),i);
   
   me->add_dependency (i);
 }
@@ -41,7 +41,7 @@ Script_column::before_line_breaking (SCM smob)
   Grob* me = unsmob_grob (smob);
   Drul_array<Link_array<Grob> > arrs;
   Link_array<Grob> staff_sided 
-    = Pointer_group_interface__extract_elements (me, (Grob*)0, "scripts");
+    = Pointer_group_interface__extract_grobs (me, (Grob*)0, "scripts");
 				     
 				     
   for (int i=0; i < staff_sided.size (); i++)
diff --git a/lily/separating-group-spanner.cc b/lily/separating-group-spanner.cc
index 52d25ec489..4b24e99501 100644
--- a/lily/separating-group-spanner.cc
+++ b/lily/separating-group-spanner.cc
@@ -92,7 +92,7 @@ Separating_group_spanner::set_spacing_rods (SCM smob)
 	Order of elements is reversed!
        */
       SCM elt = ly_car (s);
-      Item *r = dynamic_cast<Item*> (unsmob_grob (elt));
+      Item *r = unsmob_item (elt);
 
       if (!r)
 	continue;
@@ -131,7 +131,7 @@ Separating_group_spanner::set_spacing_rods (SCM smob)
 void
 Separating_group_spanner::add_spacing_unit (Grob* me ,Item*i)
 {
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("elements"), i);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"), i);
   me->add_dependency (i);
 }
 
diff --git a/lily/separating-line-group-engraver.cc b/lily/separating-line-group-engraver.cc
index 57100c952e..26e59e6439 100644
--- a/lily/separating-line-group-engraver.cc
+++ b/lily/separating-line-group-engraver.cc
@@ -14,7 +14,7 @@
 #include "engraver.hh"
 #include "axis-group-interface.hh"
 #include "note-spacing.hh"
-
+#include "group-interface.hh"
 
 struct Spacings
 {
@@ -132,10 +132,10 @@ Separating_line_group_engraver::acknowledge_grob (Grob_info i)
 
 	  if (int i = last_spacings_.note_spacings_.size ())
 	    {
-	      SCM break_malt = gh_cons (break_malt_p_->self_scm (), SCM_EOL);
 	      for (; i--;)
-		last_spacings_.note_spacings_[i]
-		  ->set_grob_property ("right-items",break_malt);
+		Pointer_group_interface::add_grob (last_spacings_.note_spacings_[i],
+						   ly_symbol2scm ("right-items"),
+						   break_malt_p_);
 				     
 	    }
 	  else if (last_spacings_.staff_spacing_)
@@ -174,7 +174,8 @@ Separating_line_group_engraver::stop_translation_timestep ()
 	note-spacing grobs.
        */
       if (musical_malt_p_)
-	sp->set_grob_property ("right-items", musical_malt_p_->self_scm());
+	Pointer_group_interface::add_grob (sp, ly_symbol2scm ("right-items"),
+					   musical_malt_p_);
 
       typeset_grob (sp);
     }
diff --git a/lily/separation-item.cc b/lily/separation-item.cc
index 534d209182..ca51ff9c2b 100644
--- a/lily/separation-item.cc
+++ b/lily/separation-item.cc
@@ -23,7 +23,7 @@ void
 Separation_item::add_item (Grob*s,Item* i)
 {
   assert (i);
-  Pointer_group_interface::add_element (s, ly_symbol2scm ("elements"),i);
+  Pointer_group_interface::add_grob (s, ly_symbol2scm ("elements"),i);
   s->add_dependency (i);
 }
 
@@ -40,7 +40,7 @@ Separation_item::my_width (Grob *me)
       if (!unsmob_grob (elt))
 	continue;
 
-      Item *il = dynamic_cast<Item*> (unsmob_grob (elt));
+      Item *il = unsmob_item (elt);
       if (pc != il->column_l ())
 	{
 	  /* this shouldn't happen, but let's continue anyway. */
diff --git a/lily/sequential-music-iterator.cc b/lily/sequential-music-iterator.cc
index e77983a529..9b8b19c989 100644
--- a/lily/sequential-music-iterator.cc
+++ b/lily/sequential-music-iterator.cc
@@ -10,7 +10,6 @@
 #include "debug.hh"
 #include "sequential-music-iterator.hh"
 #include "music-list.hh"
-#include "request-chord-iterator.hh"
 
 
 /*
diff --git a/lily/side-position-interface.cc b/lily/side-position-interface.cc
index a006af5a69..a382836e20 100644
--- a/lily/side-position-interface.cc
+++ b/lily/side-position-interface.cc
@@ -19,7 +19,7 @@
 void
 Side_position_interface::add_support (Grob*me, Grob*e)
 {
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("side-support-elements"), e);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("side-support-elements"), e);
 }
 
 
diff --git a/lily/simple-music-iterator.cc b/lily/simple-music-iterator.cc
index 6db86ee0d9..ea9c26d2cd 100644
--- a/lily/simple-music-iterator.cc
+++ b/lily/simple-music-iterator.cc
@@ -29,6 +29,14 @@ Simple_music_iterator::ok ()const
   return last_processed_mom_ < music_length_mom ();
 }
 
+/*
+  TODO: remove last_processed_mom_, and the complete shit.  We should
+  only process a simple-music once, and that is at its start.
+
+  Engravers can detect and request the end-moments to be processed as
+  well.
+
+*/
 Moment
 Simple_music_iterator::pending_moment ()const
 {
diff --git a/lily/slur.cc b/lily/slur.cc
index 479e11f665..15a8b30ea8 100644
--- a/lily/slur.cc
+++ b/lily/slur.cc
@@ -48,7 +48,7 @@ Slur::add_column (Grob*me, Grob*n)
     warning (_ ("Putting slur over rest.  Ignoring."));
   else
     {
-      Pointer_group_interface::add_element (me, ly_symbol2scm ("note-columns"), n);
+      Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-columns"), n);
       me->add_dependency (n);
     }
 
@@ -92,7 +92,7 @@ Direction
 Slur::get_default_dir (Grob*me) 
 {
   Link_array<Grob> encompass_arr =
-    Pointer_group_interface__extract_elements (me, (Grob*)0, "note-columns");
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "note-columns");
   
   Direction d = DOWN;
   for (int i=0; i < encompass_arr.size (); i ++) 
diff --git a/lily/spaceable-grob.cc b/lily/spaceable-grob.cc
index ec1e0430c0..3d54aa3723 100644
--- a/lily/spaceable-grob.cc
+++ b/lily/spaceable-grob.cc
@@ -67,7 +67,6 @@ Spaceable_grob::remove_interface (Grob*me)
 {
   me->remove_grob_property ("minimum-distances");
   me->remove_grob_property ("ideal-distances");
-  me->remove_grob_property ("dir-list");
 }
 
 
diff --git a/lily/spacing-engraver.cc b/lily/spacing-engraver.cc
index ebba459d17..f9849da294 100644
--- a/lily/spacing-engraver.cc
+++ b/lily/spacing-engraver.cc
@@ -97,7 +97,7 @@ Spacing_engraver::acknowledge_grob (Grob_info i)
 {
   if (Note_spacing::has_interface (i.grob_l_) || Staff_spacing::has_interface (i.grob_l_))
     {
-      Pointer_group_interface::add_element (spacing_p_, ly_symbol2scm  ("wishes"), i.grob_l_);
+      Pointer_group_interface::add_grob (spacing_p_, ly_symbol2scm  ("wishes"), i.grob_l_);
     }
   
   if (to_boolean (i.grob_l_->get_grob_property ("non-rhythmic")))
diff --git a/lily/spacing-spanner.cc b/lily/spacing-spanner.cc
index 92b7cb7480..841fa7ccfb 100644
--- a/lily/spacing-spanner.cc
+++ b/lily/spacing-spanner.cc
@@ -163,12 +163,7 @@ Spacing_spanner::do_measure (Grob*me, Link_array<Grob> const & cols)
 	    don't want to create too much extra space for accidentals
 	  */
 	  if (Paper_column::musical_b (rc))
-	   {
-	      if (to_boolean (rc->get_grob_property ("contains-grace")))
-		right_dist *= gh_scm2double (rc->get_grob_property ("before-grace-spacing-factor")); // fixme.
-	      else
-		right_dist *= gh_scm2double (lc->get_grob_property ("before-musical-spacing-factor"));
-	   }
+	    right_dist *= gh_scm2double (lc->get_grob_property ("before-musical-spacing-factor"));
 
  	  s.distance_f_ = left_distance + right_dist;
 	    
@@ -407,14 +402,6 @@ Spacing_spanner::note_spacing (Grob*me, Grob *lc, Grob *rc,
 
 
 
-  /*
-    UGH: KLUDGE!
-  */
-  
-  if (delta_t > Moment (Rational (1,32)))
-    dist += stem_dir_correction (me, lc,rc);
-
-
   Moment *lm = unsmob_moment (lc->get_grob_property ("when"));
   Moment *rm = unsmob_moment (rc->get_grob_property ("when"));
 
@@ -430,57 +417,6 @@ Spacing_spanner::note_spacing (Grob*me, Grob *lc, Grob *rc,
   return dist;
 }
 
-
-/**
-   Correct for optical illusions. See [Wanske] p. 138. The combination
-   up-stem + down-stem should get extra space, the combination
-   down-stem + up-stem less.
-
-   This should be more advanced, since relative heights of the note
-   heads also influence required correction.
-
-   Also might not work correctly in case of multi voices or staff
-   changing voices
-
-   TODO: lookup correction distances?  More advanced correction?
-   Possibly turn this off?
-
-   TODO: have to check wether the stems are in the same staff.
-
-   This routine reads the DIR-LIST property of both its L and R arguments.  */
-Real
-Spacing_spanner::stem_dir_correction (Grob*me, Grob*l, Grob*r) 
-{
-  SCM dl = l->get_grob_property ("dir-list");
-  SCM dr = r->get_grob_property ("dir-list");
-  
-  if (scm_ilength (dl) != 1 || scm_ilength (dr) != 1)
-    return 0.;
-
-  dl = ly_car (dl);
-  dr = ly_car (dr);
-
-  assert (gh_number_p (dl) && gh_number_p (dr));
-  int d1 = gh_scm2int (dl);
-  int d2 = gh_scm2int (dr);
-
-  if (d1 == d2)
-    return 0.0;
-
-
-  Real correction = 0.0;
-  Real ssc = gh_scm2double (me->get_grob_property ("stem-spacing-correction"));
-
-  if (d1 && d2 && d1 * d2 == -1)
-    {
-      correction = d1 * ssc;
-    }
-  else
-    programming_error ("Stem directions not set correctly for optical correction");
-  return correction;
-}
-  
-
 MAKE_SCHEME_CALLBACK (Spacing_spanner, set_springs,1);
 SCM
 Spacing_spanner::set_springs (SCM smob)
diff --git a/lily/span-bar.cc b/lily/span-bar.cc
index bf39b2d3ac..55b700a9bd 100644
--- a/lily/span-bar.cc
+++ b/lily/span-bar.cc
@@ -20,7 +20,7 @@
 void
 Span_bar::add_bar (Grob*me, Grob*b)
 {
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("elements"),  b);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("elements"),  b);
 
   me->add_dependency (b);
 }
diff --git a/lily/spanner.cc b/lily/spanner.cc
index 3579abefca..8f9cdd2412 100644
--- a/lily/spanner.cc
+++ b/lily/spanner.cc
@@ -190,7 +190,7 @@ Spanner::set_bound (Direction d, Grob*s)
   */
   if (dynamic_cast<Paper_column*> (i))
     {
-      Pointer_group_interface::add_element (i, ly_symbol2scm ("bounded-by-me"), this);  
+      Pointer_group_interface::add_grob (i, ly_symbol2scm ("bounded-by-me"), this);  
     }
 }
 
@@ -399,3 +399,10 @@ Spanner::set_spacing_rods (SCM smob)
   r.add_to_cols ();
   return SCM_UNSPECIFIED;
 }
+
+
+Spanner*
+unsmob_spanner (SCM s )
+{
+  return dynamic_cast<Spanner*> (unsmob_grob (s));
+}
diff --git a/lily/staff-spacing.cc b/lily/staff-spacing.cc
index a662f54133..38c2b7072c 100644
--- a/lily/staff-spacing.cc
+++ b/lily/staff-spacing.cc
@@ -1,5 +1,5 @@
 /*   
-staff-spacing.cc --  implement 
+staff-spacing.cc --  implement Staff_spacing
 
 source file of the GNU LilyPond music typesetter
 
@@ -16,3 +16,10 @@ Staff_spacing::has_interface (Grob* g)
   return g && g->has_interface (ly_symbol2scm ("staff-spacing-interface"));
 }
 
+
+/*
+  
+  TODO: move computation of clef/key-sig/whatever to first-note
+  distance here.
+
+*/
diff --git a/lily/stem.cc b/lily/stem.cc
index 8502c7581c..304c382a81 100644
--- a/lily/stem.cc
+++ b/lily/stem.cc
@@ -82,7 +82,6 @@ Stem::stem_end_position (Grob*me)
   Real pos;
   if (!gh_number_p (p))
     {
-
       pos = get_default_stem_end_position (me);
       me->set_grob_property ("stem-end-position", gh_double2scm (pos));
     }
@@ -228,7 +227,7 @@ Stem::add_head (Grob*me, Grob *n)
 
   if (Note_head::has_interface (n))
     {
-      Pointer_group_interface::add_element (me, ly_symbol2scm ("heads"), n);
+      Pointer_group_interface::add_grob (me, ly_symbol2scm ("heads"), n);
     }
   else
     {
@@ -380,7 +379,7 @@ Stem::position_noteheads (Grob*me)
     return;
   
   Link_array<Grob> heads =
-    Pointer_group_interface__extract_elements (me, (Grob*)0, "heads");
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "heads");
 
   heads.sort (compare_position);
   Direction dir =get_direction (me);
@@ -434,11 +433,9 @@ Stem::before_line_breaking (SCM smob)
       // suicide ();
     }
   
-  set_spacing_hints (me);
   return SCM_UNSPECIFIED;
 }
 
-
 /*
   ugh.
   When in a beam with tuplet brackets, brew_mol is called early,
@@ -460,31 +457,6 @@ Stem::height (SCM smob, SCM ax)
 }
 
 
-/**
-   set stem directions for hinting the optical spacing correction.
-
-   Modifies DIR_LIST property of the Stem's Paper_column
-
-   TODO: more advanced: supply height of noteheads as well, for more advanced spacing possibilities
- */
-void
-Stem::set_spacing_hints (Grob*me) 
-{
-  if (!invisible_b (me))
-    {
-      SCM scmdir  = gh_int2scm (get_direction (me));
-
-      Item* item = dynamic_cast<Item*> (me);
-      Item * col =  item->column_l ();
-      SCM dirlist =col->get_grob_property ("dir-list");
-      if (scm_c_memq (scmdir, dirlist) == SCM_BOOL_F)
-	{
-	  dirlist = gh_cons (scmdir, dirlist);
-	  col->set_grob_property ("dir-list", dirlist);
-	}
-    }
-}
-
 Molecule
 Stem::flag (Grob*me)
 {
diff --git a/lily/system-start-delimiter-engraver.cc b/lily/system-start-delimiter-engraver.cc
index 1cda41fe53..8f09785c38 100644
--- a/lily/system-start-delimiter-engraver.cc
+++ b/lily/system-start-delimiter-engraver.cc
@@ -39,7 +39,7 @@ System_start_delimiter_engraver::acknowledge_grob (Grob_info inf)
 	don't add as Axis_group_interface::add_element (delim_,),
 	because that would set the parent as well */
 	  
-      Pointer_group_interface::add_element (delim_, ly_symbol2scm ("elements"),  inf.grob_l_);
+      Pointer_group_interface::add_grob (delim_, ly_symbol2scm ("elements"),  inf.grob_l_);
     }
   else if (System_start_delimiter::has_interface (inf.grob_l_))
     {
diff --git a/lily/third-try.cc b/lily/third-try.cc
index bfc1a34ac8..45f356073f 100644
--- a/lily/third-try.cc
+++ b/lily/third-try.cc
@@ -20,10 +20,13 @@
 
     right-neighbors = List of spacing-wish grobs that are close to the
     current column.
-  
- */
 
 
+    left-neighbors = idem
+
+    (TODO: property-doc these!)
+ */
+
 class Third_spacing_spanner
 {
 public:
@@ -86,11 +89,13 @@ loose_column (Grob *l, Grob *c, Grob *r)
     return false;
 
   l_neighbor = l_neighbor->column_l();
-  r_neighbor = r_neighbor->column_l();
+  r_neighbor = dynamic_cast<Item*> (Note_spacing::right_column  (r_neighbor));
 
   if (l == l_neighbor && r == r_neighbor)
     return false;
 
+  if (!l_neighbor || !r_neighbor)
+    return false;
 
   /*
     Only declare loose if the bounds make a little sense.  This means
@@ -149,6 +154,14 @@ Third_spacing_spanner::prune_loose_colunms (Link_array<Grob> *cols)
 	  rns = gh_car (unsmob_grob (rns)->get_grob_property ("right-items"));
 	  c->set_grob_property ("between-cols", gh_cons (lns,
 							 rns));
+
+
+	  /*
+	    TODO: we should have distance constraints for loose
+	    columns anyway, and the placement could be improved. Clefs
+	    easily run into their neigbhors when folded into too
+	    little space.
+	  */
 	}
       else
 	{
@@ -171,14 +184,13 @@ Third_spacing_spanner::set_explicit_neighbor_columns (Link_array<Grob> cols)
       int min_rank = 100000;	// inf.
 
 
-
-      SCM wishes=  cols[i]-> get_grob_property ("spacing-wishes");
+      SCM wishes=  cols[i]->get_grob_property ("spacing-wishes");
       for (SCM s =wishes; gh_pair_p (s); s = gh_cdr (s))
 	{
 	  Item * wish = dynamic_cast<Item*> (unsmob_grob (gh_car (s)));
 
 	  Item * lc = wish->column_l ();
-	  Grob * right = unsmob_grob (wish->get_grob_property ("right-column"));
+	  Grob * right = Note_spacing::right_column (wish);
 
 	  if (!right)
 	    continue;
@@ -356,8 +368,6 @@ Third_spacing_spanner::do_measure (Grob*me, Link_array<Grob> *cols)
 
       SCM seq  = lc->get_grob_property ("right-neighbors");
 
-      Moment dt = Paper_column::when_mom (r) - Paper_column::when_mom (l);
-      
       /*
 	hinterfleisch = hind-meat = amount of space following a note.
 
@@ -367,48 +377,49 @@ Third_spacing_spanner::do_measure (Grob*me, Link_array<Grob> *cols)
 	property SPACING-SEQUENCE.  */
 
       Real stretch_distance = note_space;
-      if (shortest_in_measure <= dt)
-	{
-	  /*
-	    currently SPACING-SEQUENCE is set in
-	    Separating_group_spanner::find_musical_sequences (), which
-	    works neatly for one-voice-per staff, however,
-
-	    it can't find out the actual duration of the notes on a
-	    staff, so when putting tuplets and normal patterns it gets
-	    confused, (ie. believes that < { c8 c8 } { d8 d8 d8 }*2/3
-	    > contains 1/12 notes. ).
 
-	    here we kludge, by checking if the distance we're spacing
-	    for is less than the shortest note.
-
-	    TODO:
+      hinterfleisch = -1.0;
+      Real max_factor = 0.0;
+      for (SCM s = seq; gh_pair_p (s); s = ly_cdr (s))
+	{
+	  Grob * wish = unsmob_grob (gh_car (s));
 
-	    Move SPACING-SEQUENCE detection into a voice
-	    level-engraver --or-- make sure that every column has
-	    access to the note head.
+	  /*
+	    TODO: configgable.
 
+	    TODO: don't do stem-dir correction in polyphonic
+	    stuff. It wastes CPU time.
 	  */
-	  for (SCM s = seq; gh_pair_p (s); s = ly_cdr (s))
+	  if (Note_spacing::has_interface (wish))
 	    {
-	      Grob * wish = unsmob_grob (gh_car (s));
+	      hinterfleisch = hinterfleisch >?
+		( - headwid +
 
-	      // TODO; configgable.
-	      if (Note_spacing::has_interface (wish))
-		{
-		  hinterfleisch += -headwid + Note_spacing::get_spacing (wish);
-		}
+		  (note_space + Note_spacing::get_spacing (wish))
+		  *gh_scm2double (wish->get_grob_property ("space-factor"))
 
-	      // should move into Note_spacing
-	      // hinterfleisch += stem_dir_correction (me, l, r);
+		  + Note_spacing::stem_dir_correction (wish));
 	    }
+	}
+
+      // ? why.
+      if (gh_pair_p (seq))
+	stretch_distance -= headwid;
 
-	  // ? why.
-	  if (gh_pair_p (seq))
-	    stretch_distance -= headwid;
-	}      
+	  /*
+	    something failed, or we get ridiculous close.
+	   */
+      if (hinterfleisch < 0)
+	{
+	  // maybe should issue a programming error.
+	  hinterfleisch = note_space;
+	}
+
+      if (max_factor == 0.0)
+	max_factor = 1.0; 
+      
       Spring s;
-      s.distance_f_ = hinterfleisch;
+      s.distance_f_ = max_factor *  hinterfleisch;
       s.strength_f_ = 1 / stretch_distance;
 
       s.item_l_drul_[LEFT] = l;
diff --git a/lily/tie-column.cc b/lily/tie-column.cc
index 50844a3b1b..fa588acdcf 100644
--- a/lily/tie-column.cc
+++ b/lily/tie-column.cc
@@ -44,7 +44,7 @@ Tie_column::add_tie (Grob*me,Grob *s)
       dynamic_cast<Spanner*> (me)->set_bound (RIGHT, Tie::head (s,RIGHT));
     }
   
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("ties"), s);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("ties"), s);
   s->add_dependency (me);
 }
 
@@ -69,7 +69,7 @@ void
 Tie_column::set_directions (Grob*me)
 {
   Link_array<Grob> ties =
-    Pointer_group_interface__extract_elements (me, (Grob*)0, "ties");
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "ties");
 
   for (int i = ties.size (); i--;)
     if (Directional_element_interface::get (ties[i]))
diff --git a/lily/tie.cc b/lily/tie.cc
index bb011b973d..7ba15e3491 100644
--- a/lily/tie.cc
+++ b/lily/tie.cc
@@ -110,7 +110,7 @@ Tie::get_default_dir (Grob*me)
 SCM
 Tie::get_control_points (SCM smob)
 {  
-  Spanner*me = dynamic_cast<Spanner*> (unsmob_grob (smob));
+  Spanner*me = unsmob_spanner (smob);
   Direction headdir = CENTER; 
   if (head (me,LEFT))
     headdir = LEFT;
diff --git a/lily/timing-engraver.cc b/lily/timing-engraver.cc
index 909039db3a..88a54c93b9 100644
--- a/lily/timing-engraver.cc
+++ b/lily/timing-engraver.cc
@@ -25,7 +25,6 @@ protected:
   
   virtual void start_translation_timestep ();
   virtual void stop_translation_timestep ();
-  virtual void process_music ();
 
 public:
   TRANSLATOR_DECLARATIONS(Timing_engraver);
@@ -81,15 +80,6 @@ Timing_engraver::stop_translation_timestep ()
 }
 
 
-/*
-  ugh. Translator doesn't do process_music ().
- */
-void
-Timing_engraver::process_music ()
-{
-  Timing_translator::process_music ();
-}
-
 ENTER_DESCRIPTION(Timing_engraver,
 /* descr */       " Responsible for synchronizing timing information from staves. 
 Normally in @code{Score}.  In order to create polyrhythmic music,
diff --git a/lily/timing-translator.cc b/lily/timing-translator.cc
index 79b741034c..8158bb1831 100644
--- a/lily/timing-translator.cc
+++ b/lily/timing-translator.cc
@@ -14,39 +14,11 @@
 #include "global-translator.hh"
 #include "multi-measure-rest.hh"
 
-/*
-  TODO: change the rest of lily, so communication with
-  Timing_translator is only done through properties.  This means the
-  class declaration can go here.  */
-bool
-Timing_translator::try_music (Music*r)
-{
-  if (dynamic_cast<Barcheck_req*> (r))
-    {
-      check_ = r;
-      return true;
-    }
-  return false;
-}
 
-void
-Timing_translator::process_music ()
-{
-  if (check_ && measure_position ().main_part_)
-    {
-      check_->origin ()->warning (_f ("barcheck failed at: %s", 
-				      measure_position ().str ()));
-      Moment zero; 
-      
-      if (!to_boolean (get_property ("barCheckNoSynchronize")))
-	daddy_trans_l_->set_property ("measurePosition", zero.smobbed_copy ());
-    }
-}
 
 void
 Timing_translator::stop_translation_timestep ()
 {
-  check_ = 0;
   
   Translator *t = this;
   Global_translator *global_l =0;
@@ -127,7 +99,6 @@ Timing_translator::measure_position () const
 void
 Timing_translator::start_translation_timestep ()
 {
-  check_ = 0;
   Translator *t = this;
   Global_translator *global_l =0;
   do
diff --git a/lily/tuplet-bracket.cc b/lily/tuplet-bracket.cc
index cf26511ffe..efc2e33681 100644
--- a/lily/tuplet-bracket.cc
+++ b/lily/tuplet-bracket.cc
@@ -48,7 +48,7 @@ Tuplet_bracket::brew_molecule (SCM smob)
   Grob *me= unsmob_grob (smob);
   Molecule  mol;
   Link_array<Grob> column_arr=
-    Pointer_group_interface__extract_elements (me, (Grob*)0, "columns");
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "columns");
 
 
   if (!column_arr.size ())
@@ -139,7 +139,7 @@ void
 Tuplet_bracket::calc_position_and_height (Grob*me,Real *offset, Real * dy) 
 {
   Link_array<Grob> column_arr=
-    Pointer_group_interface__extract_elements (me, (Grob*)0, "columns");
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "columns");
 
 
   Grob * commony = me->common_refpoint (me->get_grob_property ("columns"), Y_AXIS);
@@ -220,7 +220,7 @@ void
 Tuplet_bracket::calc_dy (Grob*me,Real * dy)
 {
   Link_array<Grob> column_arr=
-    Pointer_group_interface__extract_elements (me, (Grob*)0, "columns");
+    Pointer_group_interface__extract_grobs (me, (Grob*)0, "columns");
 
   /*
     ugh. refps.
@@ -236,7 +236,7 @@ Tuplet_bracket::after_line_breaking (SCM smob)
 {
   Grob * me = unsmob_grob (smob);
   Link_array<Note_column> column_arr=
-    Pointer_group_interface__extract_elements (me, (Note_column*)0, "columns");
+    Pointer_group_interface__extract_grobs (me, (Note_column*)0, "columns");
 
   if (!column_arr.size ())
     {
@@ -292,7 +292,7 @@ Tuplet_bracket::get_default_dir (Grob*me)
 void
 Tuplet_bracket::add_column (Grob*me, Item*n)
 {
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("columns"), n);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("columns"), n);
   me->add_dependency (n);
 
   add_bound_item (dynamic_cast<Spanner*> (me), n);
diff --git a/lily/volta-spanner.cc b/lily/volta-spanner.cc
index d558d1ee04..bf6805ef56 100644
--- a/lily/volta-spanner.cc
+++ b/lily/volta-spanner.cc
@@ -42,7 +42,7 @@ Volta_spanner::brew_molecule (SCM smob)
 {
   Grob *me = unsmob_grob (smob);
   Link_array<Item> bar_arr
-    = Pointer_group_interface__extract_elements (me, (Item*)0, "bars");
+    = Pointer_group_interface__extract_grobs (me, (Item*)0, "bars");
 
   if (!bar_arr.size ())
     return SCM_EOL;
@@ -117,7 +117,7 @@ Volta_spanner::brew_molecule (SCM smob)
 void
 Volta_spanner::add_bar (Grob *me, Item* b)
 {
-  Pointer_group_interface::add_element (me, ly_symbol2scm ("bars"), b);
+  Pointer_group_interface::add_grob (me, ly_symbol2scm ("bars"), b);
   Side_position_interface::add_support (me,b);
   add_bound_item (dynamic_cast<Spanner*> (me), b); 
 }
diff --git a/lily/warn.cc b/lily/warn.cc
index 1788539e40..1bead33c1d 100644
--- a/lily/warn.cc
+++ b/lily/warn.cc
@@ -9,7 +9,6 @@
 #include "debug.hh"
 #include "my-lily-lexer.hh"
 #include "moment.hh"
-#include "timing-translator.hh"
 #include "source-file.hh"
 #include "source.hh"
 #include "main.hh"
diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly
index 0e1f1e7181..26cd85e811 100644
--- a/ly/engraver-init.ly
+++ b/ly/engraver-init.ly
@@ -21,7 +21,6 @@ StaffContext=\translator {
 	SeparatingGroupSpanner \override #'spacing-procedure
 	  =  #Separating_group_spanner::set_spacing_rods_and_seqs
 
-
 	\consists "Clef_engraver"
 	\consists "Key_engraver"
 	\consists "Time_signature_engraver"
@@ -32,7 +31,7 @@ StaffContext=\translator {
 	\consists "Piano_pedal_engraver"
 	\consists "Instrument_name_engraver"
 	\consists "Grob_pq_engraver"
-	
+
 	\consistsend "Axis_group_engraver"
 	
 	MinimumVerticalExtent = #'(-4 . 4)
diff --git a/scm/grob-description.scm b/scm/grob-description.scm
index 3938da7413..bf5f35f9dc 100644
--- a/scm/grob-description.scm
+++ b/scm/grob-description.scm
@@ -1,4 +1,3 @@
-
 ;;;; grob-description.scm -- part of generated backend documentation
 ;;;;
 ;;;;  source file of the GNU LilyPond music typesetter
@@ -425,8 +424,6 @@
 	
 	(PaperColumn . (
 		(axes 0)
-		(before-grace-spacing-factor . 1.2)
-                (before-musical-spacing-factor . 0.4)
  		(meta . ,(grob-description paper-column-interface axis-group-interface spaceable-element-interface))
 	))
 	(PhrasingSlur . (
@@ -453,8 +450,6 @@
 	
 	(NonMusicalPaperColumn . (
                 (axes 0)
-                (before-musical-spacing-factor . 1.0)
-		(column-space-strength . 2.0)
  		(meta . ,(grob-description paper-column-interface axis-group-interface spaceable-element-interface))
         ))
 
@@ -529,15 +524,13 @@
 		 ))
 	      
 	(SpacingSpanner . (
-		(spacing-procedure . ;; ,Third_spacing_spanner::set_springs
-				        ,Spacing_spanner::set_springs
-				   )
-		(stem-spacing-correction . 0.5)
+		(spacing-procedure .  ,Third_spacing_spanner::set_springs)
 		(grace-space-factor . 0.8)
 
 		;; TODO: change naming -- unintuitive
 		(arithmetic-basicspace . 2.0)
 		(arithmetic-multiplier . ,(* 0.9 1.32))
+
 		;; assume that notes at least this long are present.
 		(maximum-duration-for-spacing . ,(make-moment 1 8))
 		(meta . ,(grob-description  spacing-spanner-interface))
@@ -582,7 +575,8 @@
 	(NoteSpacing . (
 		(X-extent-callback . #f)
 		(Y-extent-callback . #f)
-
+		(stem-spacing-correction . 0.)
+		(space-factor . 1.0)
 		(meta . ,(grob-description note-spacing-interface))
 	))
 
diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm
index 0d018c3d97..9afa070530 100644
--- a/scm/grob-property-description.scm
+++ b/scm/grob-property-description.scm
@@ -49,10 +49,7 @@ This procedure is called (using dependency resolution) after line breaking. Retu
 arrow on the arpeggio squiggly line.")
 (grob-property-description 'attachment pair? "cons of symbols, '(LEFT-TYPE . RIGHT-TYPE), where both types may be alongside-stem, stem, head or loose-end.")
 
-(grob-property-description 'stem-attachment-function procedure? "Where
-does the stem attach to the notehead? Function takes a symbol argument
-being the style. It returns a (X . Y) pair, specifying location in
-terms of note head bounding box.")
+
 (grob-property-description 'attachment-offset pair? "cons of offsets,
 '(LEFT-offset . RIGHT-offset).  This offset is added to the
 attachments to prevent ugly slurs.  [fixme: we need more documentation here].
@@ -285,7 +282,10 @@ reference point.
 (grob-property-description 'slope number? "some kind of slope")
 (grob-property-description 'slope-limit number? "set slope to zero if slope is running away steeper than this.")
 (grob-property-description 'solid boolean? "should porrectus be solidly filled?.")
+
 (grob-property-description 'space-alist list? "Alist of break align spacing tuples. See basic-property.scm")
+(grob-property-description 'space-factor number? "Scale horizontal spacing up by this amount.")
+
 (grob-property-description 'space-function procedure? "function of type multiplicity -> real (in staffspace).")
 (grob-property-description 'spacing-procedure procedure? "procedure
 taking grob as argument. This is called after
@@ -297,7 +297,14 @@ itself.  Return value is ignored.")
 (grob-property-description 'staff-symbol boolean? "the staff symbol grob that we're in.")
 (grob-property-description 'staffline-clearance number? "don't get closer than this to stafflines.")
 (grob-property-description 'stem ly-grob? "pointer to Stem object.")
-(grob-property-description 'stem-direction dir? "up or down?.")
+(grob-property-description 'stem-attachment-function procedure? "Where
+does the stem attach to the notehead? Function takes a symbol argument
+being the style. It returns a (X . Y) pair, specifying location in
+terms of note head bounding box.")
+(grob-property-description 'stem-direction dir? "up or down?.
+
+[docme: why not direction]
+")
 (grob-property-description 'stem-end-position number? "Where does the stem end (the end is opposite to the support-head.")
 (grob-property-description 'stem-length number? "length of stem.")
 (grob-property-description 'stem-shorten list? "shorten stems in forced directions given flag multiplicity.")
diff --git a/stepmake/stepmake/c++-rules.make b/stepmake/stepmake/c++-rules.make
index 78bdfd026c..1696b2e0aa 100644
--- a/stepmake/stepmake/c++-rules.make
+++ b/stepmake/stepmake/c++-rules.make
@@ -14,14 +14,14 @@ $(outdir)/%.lo: $(outdir)/%.cc
 
 $(outdir)/%.cc: %.yy
 	$(BISON) $<
-	@-mv -f parser.tab.c parser.tab.cc  # bison < 1.30
-	mv parser.tab.cc $@
+	@-mv -f $(*F).yy.tab.c $(*F).tab.cc  # bison < 1.30
+	mv $(*F).tab.cc $@
 
 $(outdir)/%.hh: %.yy
 	$(BISON) -d $<
-	@-mv -f parser.tab.h parser.tab.hh  # bison < 1.30
-	mv parser.tab.hh $@
-	rm -f parser.tab.c parser.tab.cc	# if this happens in the wrong order it triggers recompile of the .cc file 
+	@-mv -f $(*F).yy.tab.h $(*F).tab.hh  # bison < 1.30
+	mv $(*F).tab.hh $@
+	rm -f $(*F).tab.c $(*F).tab.cc	# if this happens in the wrong order it triggers recompile of the .cc file 
 
 $(outdir)/%.cc: %.ll
 	$(FLEX) -Cfe -p -p -t $< > $@