+ }
+
+ if (gh_pair_p (right_neighbors))
+ {
+ cols[i]->set_grob_property ("right-neighbors", right_neighbors);
+ }
+ }
+}
+
+/*
+ Set neighboring columns that have no left/right-neighbor set
+ yet. Only do breakable non-musical columns, and musical columns.
+*/
+void
+Third_spacing_spanner::set_implicit_neighbor_columns (Link_array<Grob> cols)
+{
+ for (int i = 0; i < cols.size (); i++)
+ {
+ Item * it = dynamic_cast<Item*>(cols[i]);
+ if (!Item::breakable_b (it) && !Paper_column::musical_b (it))
+ continue;
+
+ // it->breakable || it->musical
+ SCM ln = cols[i] ->get_grob_property ("left-neighbors");
+ if (!gh_pair_p (ln) && i )
+ {
+ cols[i]->set_grob_property ("left-neighbors", cols[i-1]->self_scm());
+ }
+
+ SCM rn = cols[i] ->get_grob_property ("right-neighbors");
+ if (!gh_pair_p (rn) && i < cols.size () - 1)
+ {
+ cols[i]->set_grob_property ("right-neighbors", cols[i + 1]->self_scm());
+ }
+ }
+}
+
+
+MAKE_SCHEME_CALLBACK (Third_spacing_spanner, set_springs,1);
+SCM
+Third_spacing_spanner::set_springs (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+
+ Link_array<Grob> all (me->pscore_l_->line_l_->column_l_arr ()) ;
+
+ set_explicit_neighbor_columns (all);
+ prune_loose_colunms (&all);
+ set_implicit_neighbor_columns (all);
+
+ int j = 0;
+ for (int i = 1; i < all.size (); i++)
+ {
+ Grob *sc = all[i];
+ if (Item::breakable_b (sc))
+ {
+ Link_array<Grob> measure (all.slice (j, i+1));
+ do_measure (me, &measure);
+ j = i;
+ }
+ }
+
+ return SCM_UNSPECIFIED;
+}
+
+
+void
+Third_spacing_spanner::do_measure (Grob*me, Link_array<Grob> *cols)
+{
+ Moment shortest_in_measure;
+
+ /*
+ space as if this duration is present.
+ */
+ Moment base_shortest_duration = *unsmob_moment (me->get_grob_property ("maximum-duration-for-spacing"));
+ shortest_in_measure.set_infinite (1);
+
+ for (int i =0 ; i < cols->size (); i++)
+ {
+ if (Paper_column::musical_b (cols->elem (i)))
+ {
+ Moment *when = unsmob_moment (cols->elem (i)->get_grob_property ("when"));
+
+ /*
+ ignore grace notes for shortest notes.
+ */
+ if (when && when->grace_part_)
+ continue;
+
+ SCM st = cols->elem (i)->get_grob_property ("shortest-starter-duration");
+ Moment this_shortest = *unsmob_moment (st);
+ shortest_in_measure = shortest_in_measure <? this_shortest;
+ }
+ }
+
+ Array<Spring> springs;
+
+ for (int i= 0; i < cols->size () - 1; i++)
+ {
+ Item * l = dynamic_cast<Item*> (cols->elem (i));
+ Item * r = dynamic_cast<Item*> (cols->elem (i+1));
+
+ Paper_column * lc = dynamic_cast<Paper_column*> (l);
+ Paper_column * rc = dynamic_cast<Paper_column*> (r);
+
+ if (!Paper_column::musical_b (l))
+ {
+ breakable_column_spacing (l, r);
+
+ /*
+
+ The case that the right part is broken as well is rather
+ rare, but it is possible, eg. with a single empty measure,
+ or if one staff finishes a tad earlier than the rest.
+
+ */
+ Item *lb = l->find_prebroken_piece (RIGHT);
+ Item *rb = r->find_prebroken_piece (LEFT);
+
+ if (lb)
+ breakable_column_spacing (lb,r);
+
+ if (rb)
+ breakable_column_spacing (l, rb);
+ if (lb && rb)
+ breakable_column_spacing (lb, rb);
+
+ continue ;
+ }
+
+ Real note_space = note_spacing (me,lc, rc, shortest_in_measure <? base_shortest_duration);
+ Real hinterfleisch = note_space;
+ Real headwid = gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
+
+ 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.
+
+
+ We adjust the space following a note only if the next note
+ happens after the current note (this is set in the grob
+ 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:
+
+ Move SPACING-SEQUENCE detection into a voice
+ level-engraver --or-- make sure that every column has
+ access to the note head.
+
+ */
+ for (SCM s = seq; gh_pair_p (s); s = ly_cdr (s))