+static struct table *
+pivot_output_title (const struct pivot_table *pt)
+{
+ if (!pt->title || !pt->show_title)
+ return NULL;
+ struct table *title = create_aux_table (pt, 1, 1, PIVOT_AREA_TITLE);
+ fill_cell (title, 0, 0, PIVOT_AREA_TITLE, pt->title, false);
+ return title;
+}
+
+static int
+pivot_count_layers (const struct pivot_table *pt)
+{
+ const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
+ int n_layers = 0;
+ for (size_t i = 0; i < layer_axis->n_dimensions; i++)
+ {
+ const struct pivot_dimension *d = layer_axis->dimensions[i];
+ if (d->n_leaves)
+ n_layers++;
+ }
+ return n_layers;
+}
+
+static void
+put_layers (struct table *t, const struct pivot_table *pt,
+ const size_t *layer_indexes, int x1, int y1 UNUSED, int x2, int y2)
+{
+ assert (y1 + pivot_count_layers (pt) - 1 == y2);
+ const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
+ for (size_t i = 0; i < layer_axis->n_dimensions; i++)
+ {
+ const struct pivot_dimension *d = layer_axis->dimensions[i];
+ if (!d->n_leaves)
+ continue;
+
+ struct string s = DS_EMPTY_INITIALIZER;
+ pivot_value_format (d->data_leaves[layer_indexes[i]]->name, pt, &s);
+ int y = y2 - i;
+ fill_cell_owned (t, x1, y, x2, y, PIVOT_AREA_LAYERS, &s, false);
+ }
+}
+
+static struct table *
+pivot_output_layers (const struct pivot_table *pt, const size_t *layer_indexes)
+{
+ int n_layers = pivot_count_layers (pt);
+ if (!n_layers)
+ return NULL;
+
+ struct table *layers = create_aux_table (pt, 1, n_layers, PIVOT_AREA_LAYERS);
+ put_layers (layers, pt, layer_indexes, 0, 0, 0, n_layers - 1);
+ return layers;
+}
+
+static struct table *
+pivot_output_caption (const struct pivot_table *pt)
+{
+ if (!pt->caption || !pt->show_caption)
+ return NULL;
+
+ struct table *caption = create_aux_table (pt, 1, 1, PIVOT_AREA_CAPTION);
+ fill_cell (caption, 0, 0, PIVOT_AREA_CAPTION, pt->caption, false);
+ return caption;
+}
+
+static void
+put_footnotes (struct table *t, const struct pivot_table *pt,
+ struct pivot_footnote **f, size_t nf,
+ int x1, int x2, int y1)
+{
+ for (size_t i = 0; i < nf; i++)
+ {
+ struct string s = DS_EMPTY_INITIALIZER;
+ pivot_footnote_format_marker (f[i], pt, &s);
+ ds_put_cstr (&s, ". ");
+ pivot_value_format (f[i]->content, pt, &s);
+ int y = y1 + i;
+ fill_cell_owned (t, x1, y, x2, y, PIVOT_AREA_FOOTER, &s, false);
+ }
+}
+
+static struct table *
+pivot_output_footnotes (const struct pivot_table *pt,
+ struct pivot_footnote **f, size_t nf)
+{
+ if (!nf)
+ return NULL;
+
+ struct table *footnotes = create_aux_table (pt, 1, nf, PIVOT_AREA_FOOTER);
+ put_footnotes (footnotes, pt, f, nf, 0, 0, 0);
+ return footnotes;
+}
+