+/****************************************************************/
+
+/*
+ TODO: should a add penalty for widely varying spring forces (caused
+ by constraints, eg.
+
+
+ . =====
+ . | |
+ .o|o|x ##x
+ .
+
+ The ## forces the notes apart; we shouldn't allow the O's to touch
+ this closely.
+*/
+
+struct Rod_description
+{
+ vsize r_;
+ Real dist_;
+
+ bool operator< (const Rod_description r)
+ {
+ return r_ < r.r_;
+ }
+
+ Rod_description ()
+ {
+ r_ = 0;
+ dist_ = 0;
+ }
+
+ Rod_description (vsize r, Real d)
+ {
+ r_ = r;
+ dist_ = d;
+ }
+};
+
+struct Column_description
+{
+ vector<Rod_description> rods_;
+ vector<Rod_description> end_rods_; /* use these if they end at the last column of the line */
+ Real ideal_;
+ Real inverse_hooke_;
+ Real end_ideal_;
+ Real end_inverse_hooke_;
+ SCM break_permission_;
+ Interval keep_inside_line_;
+
+ Column_description ()
+ {
+ ideal_ = 0;
+ inverse_hooke_ = 0;
+ end_ideal_ = 0;
+ end_inverse_hooke_ = 0;
+ break_permission_ = SCM_EOL;
+ }
+};
+
+static bool
+is_loose (Grob *g)
+{
+ return (scm_is_pair (g->get_object ("between-cols")));
+}
+
+static Grob*
+maybe_find_prebroken_piece (Grob *g, Direction d)
+{
+ Grob *ret = dynamic_cast<Item*> (g)->find_prebroken_piece (d);
+ if (ret)
+ return ret;
+ return g;
+}
+
+static Grob*
+next_spaceable_column (vector<Grob*> const &list, vsize starting)
+{
+ for (vsize i = starting+1; i < list.size (); i++)
+ if (!is_loose (list[i]))
+ return list[i];
+ return 0;
+}
+
+static Column_description
+get_column_description (vector<Grob*> const &cols, vsize col_index, bool line_starter)
+{
+ Grob *col = cols[col_index];
+ if (line_starter)
+ col = maybe_find_prebroken_piece (col, RIGHT);
+
+ Column_description description;
+ Grob *next_col = next_spaceable_column (cols, col_index);
+ if (next_col)
+ Spaceable_grob::get_spring (col, next_col, &description.ideal_, &description.inverse_hooke_);
+ Grob *end_col = dynamic_cast<Item*> (cols[col_index+1])->find_prebroken_piece (LEFT);
+ if (end_col)
+ Spaceable_grob::get_spring (col, end_col, &description.end_ideal_, &description.end_inverse_hooke_);
+
+ for (SCM s = Spaceable_grob::get_minimum_distances (col);
+ scm_is_pair (s); s = scm_cdr (s))
+ {
+ Grob *other = unsmob_grob (scm_caar (s));
+ vsize j = binary_search (cols, other, Paper_column::less_than, col_index);
+ if (j != VPOS)