+
+LY_DEFINE (ly_grob_chain_callback, "ly:grob-chain-callback",
+ 3, 0, 0, (SCM grob, SCM proc, SCM sym),
+ "Find the callback that is stored as property"
+ " @var{sym} of grob @var{grob} and chain @var{proc}"
+ " to the head of this, meaning that it is called"
+ " using @var{grob} and the previous callback's result.")
+{
+ Grob *gr = unsmob<Grob> (grob);
+
+ LY_ASSERT_SMOB (Grob, grob, 1);
+ SCM_ASSERT_TYPE (ly_is_procedure (proc) || unsmob<Unpure_pure_container> (proc), proc, SCM_ARG2, __FUNCTION__, "procedure or unpure pure container");
+ LY_ASSERT_TYPE (ly_is_symbol, sym, 3);
+
+ chain_callback (gr, proc, sym);
+ return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_grob_vertical_less_p, "ly:grob-vertical<?",
+ 2, 0, 0, (SCM a, SCM b),
+ "Does @var{a} lie above @var{b} on the page?")
+{
+ LY_ASSERT_SMOB (Grob, a, 1);
+ LY_ASSERT_SMOB (Grob, b, 2);
+
+ Grob *ga = unsmob<Grob> (a);
+ Grob *gb = unsmob<Grob> (b);
+
+ return ly_bool2scm (Grob::vertical_less (ga, gb));
+}
+
+LY_DEFINE (ly_grob_get_vertical_axis_group_index, "ly:grob-get-vertical-axis-group-index",
+ 1, 0, 0, (SCM grob),
+ "Get the index of the vertical axis group the grob @var{grob} belongs to;"
+ " return @code{-1} if none is found.")
+{
+ Grob *gr = unsmob<Grob> (grob);
+
+ LY_ASSERT_SMOB (Grob, grob, 1);
+
+ return scm_from_int (Grob::get_vertical_axis_group_index (gr));
+}
+
+LY_DEFINE (ly_grob_spanned_rank_interval, "ly:grob-spanned-rank-interval",
+ 1, 0, 0, (SCM grob),
+ "Returns a pair with the @code{rank} of the furthest left"
+ " column and the @code{rank} of the furthest right column"
+ " spanned by @code{grob}.")
+{
+ Grob *gr = unsmob<Grob> (grob);
+
+ LY_ASSERT_SMOB (Grob, grob, 1);
+
+ Interval_t<int> iv = gr->spanned_rank_interval ();
+
+ return scm_cons (scm_from_int(iv[LEFT]), scm_from_int(iv[RIGHT]));
+}