+/* Box packing helpers */
+static void clear_old(event_t **list, int n, event_t *cur)
+{
+ for (int i = 0; i < n; i++)
+ if (list[i] && compare(&list[i]->end, &cur->start) < 0)
+ list[i] = NULL;
+}
+
+static int next_free(event_t **list, int n)
+{
+ for (int i = 0; i < n; i++)
+ if (!list[i])
+ return i;
+ return n-1;
+}
+
+static int count_busy(event_t **list, int n)
+{
+ int sum = 0;
+ for (int i = 0; i < n; i++)
+ if (list[i])
+ sum++;
+ return sum;
+}
+
+static int get_ncols(event_t *event, int n)
+{
+ int ncols = 0;
+ event_t *preview[n];
+ memset(preview, 0, sizeof(preview));
+ for (event_t *cur = event; cur; cur = cur->next) {
+ int col = next_free(preview, n);
+ preview[col] = cur;
+ ncols = MAX(ncols, col+1);
+ if (cur->next)
+ clear_old(preview, n, cur->next);
+ if (count_busy(preview, n) == 0)
+ break;
+ }
+ return ncols;
+}
+
+static int get_col(event_t **list, int n, event_t *event, int *ncols)
+{
+ clear_old(list, n, event);
+
+ /* If there are current events, then recalculate
+ * ncols for the next series of events */
+ if (count_busy(list, n) == 0)
+ *ncols = get_ncols(event, n);
+
+ /* Find next open slot */
+ int col = next_free(list, n);
+ list[col] = event;
+ return col;
+}
+