table-item: Make caption into table_cell too.
[pspp] / src / output / pivot-output.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2018 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <stdlib.h>
20
21 #include "output/pivot-table.h"
22
23 #include "data/settings.h"
24 #include "libpspp/assertion.h"
25 #include "libpspp/pool.h"
26 #include "output/table.h"
27 #include "output/page-eject-item.h"
28 #include "output/table-item.h"
29 #include "output/text-item.h"
30 #include "output/table-provider.h"
31
32 #include "gl/minmax.h"
33 #include "gl/xalloc.h"
34
35 #define H TABLE_HORZ
36 #define V TABLE_VERT
37
38 static const struct pivot_category *
39 find_category (const struct pivot_dimension *d, int dim_index,
40                const size_t *indexes, int row_ofs)
41 {
42   size_t index = indexes[dim_index];
43   assert (index < d->n_leaves);
44   for (const struct pivot_category *c = d->presentation_leaves[index];
45        c; c = c->parent)
46     {
47       /* A category can covert multiple rows.  Only return the category for its
48          top row. */
49       if (row_ofs == c->extra_depth)
50         return c;
51
52       row_ofs -= 1 + c->extra_depth;
53       if (row_ofs < 0)
54         return NULL;
55     }
56   return NULL;
57 }
58
59 static struct table_area_style *
60 table_area_style_override (struct pool *pool,
61                            const struct table_area_style *in,
62                            const struct cell_style *cell_,
63                            const struct font_style *font_,
64                            bool rotate_label)
65 {
66   const struct cell_style *cell = cell_ ? cell_ : &in->cell_style;
67   const struct font_style *font = font_ ? font_ : &in->font_style;
68
69   struct table_area_style *out = (pool
70                             ? pool_alloc (pool, sizeof *out)
71                             : xmalloc (sizeof *out));
72   *out = (struct table_area_style) {
73     .cell_style.halign = rotate_label ? TABLE_HALIGN_CENTER : cell->halign,
74     .cell_style.valign = rotate_label ? TABLE_VALIGN_CENTER : cell->valign,
75     .cell_style.decimal_offset = cell->decimal_offset,
76     .cell_style.margin[H][0] = cell->margin[H][0],
77     .cell_style.margin[H][1] = cell->margin[H][1],
78     .cell_style.margin[V][0] = cell->margin[V][0],
79     .cell_style.margin[V][1] = cell->margin[V][1],
80     .font_style.fg[0] = font->fg[0],
81     .font_style.fg[1] = font->fg[1],
82     .font_style.bg[0] = font->bg[0],
83     .font_style.bg[1] = font->bg[1],
84     .font_style.typeface = (font->typeface
85                             ? pool_strdup (pool, font->typeface)
86                             : NULL),
87     .font_style.size = font->size,
88     .font_style.bold = font->bold,
89     .font_style.italic = font->italic,
90     .font_style.underline = font->underline,
91     .font_style.markup = font->markup,
92   };
93   return out;
94 }
95
96 static int
97 format_cell (const struct pivot_value *value, int style_idx,
98              enum settings_value_show show_values,
99              enum settings_value_show show_variables,
100              bool rotate_label, struct string *s)
101 {
102   int options = style_idx << TAB_STYLE_SHIFT;
103   if (value)
104     {
105       bool numeric = pivot_value_format_body (value, show_values,
106                                               show_variables, s);
107       if (numeric)
108         options |= TAB_NUMERIC;
109       if (value->font_style && value->font_style->markup)
110         options |= TAB_MARKUP;
111       if (rotate_label)
112         options |= TAB_ROTATE;
113     }
114   return options;
115 }
116
117 static void
118 fill_cell (struct table *t, int x1, int y1, int x2, int y2,
119            const struct table_area_style *style, int style_idx,
120            const struct pivot_value *value, struct footnote **footnotes,
121            enum settings_value_show show_values,
122            enum settings_value_show show_variables,
123            bool rotate_label)
124 {
125   struct string s = DS_EMPTY_INITIALIZER;
126   int options = format_cell (value, style_idx,
127                              show_values, show_variables, rotate_label, &s);
128   table_joint_text (t, x1, y1, x2, y2, options, ds_cstr (&s));
129   ds_destroy (&s);
130
131   if (value)
132     {
133       if (value->cell_style || value->font_style || rotate_label)
134         table_add_style (t, x1, y1,
135                          table_area_style_override (t->container, style,
136                                                     value->cell_style,
137                                                     value->font_style,
138                                                     rotate_label));
139
140       for (size_t i = 0; i < value->n_footnotes; i++)
141         {
142           struct footnote *f = footnotes[value->footnotes[i]->idx];
143           if (f)
144             table_add_footnote (t, x1, y1, f);
145         }
146
147       if (value->n_subscripts)
148         table_add_subscripts (t, x1, y1,
149                               value->subscripts, value->n_subscripts);
150     }
151 }
152
153 static struct table_cell *
154 pivot_value_to_table_cell (const struct pivot_value *value,
155                            const struct table_area_style *style, int style_idx,
156                            struct footnote **footnotes,
157                            enum settings_value_show show_values,
158                            enum settings_value_show show_variables)
159 {
160   if (!value)
161     return NULL;
162
163   struct string s = DS_EMPTY_INITIALIZER;
164   int options = format_cell (value, style_idx,
165                              show_values, show_variables, false, &s);
166
167   struct table_cell *cell = xmalloc (sizeof *cell);
168   *cell = (struct table_cell) {
169     .options = options,
170     .text = ds_steal_cstr (&s),
171     .style = table_area_style_override (
172       NULL, style, value->cell_style, value->font_style, false),
173   };
174
175   if (value->n_subscripts)
176     {
177       cell->subscripts = xnmalloc (value->n_subscripts,
178                                    sizeof *cell->subscripts);
179       cell->n_subscripts = value->n_subscripts;
180       for (size_t i = 0; i < value->n_subscripts; i++)
181         cell->subscripts[i] = xstrdup (value->subscripts[i]);
182     }
183
184   if (value->n_footnotes)
185     {
186       cell->footnotes = xnmalloc (value->n_footnotes, sizeof *cell->footnotes);
187       for (size_t i = 0; i < value->n_footnotes; i++)
188         {
189           struct footnote *f = footnotes[value->footnotes[i]->idx];
190           if (f)
191             cell->footnotes[cell->n_footnotes++] = f;
192         }
193     }
194
195   return cell;
196 }
197
198 static int
199 get_table_rule (const struct table_border_style *styles,
200                 enum pivot_border style_idx)
201 {
202   return styles[style_idx].stroke | (style_idx << TAB_RULE_STYLE_SHIFT);
203 }
204
205 static void
206 draw_line (struct table *t, const struct table_border_style *styles,
207            enum pivot_border style_idx,
208            enum table_axis axis, int a, int b0, int b1)
209 {
210   int rule = get_table_rule (styles, style_idx);
211   if (axis == H)
212     table_hline (t, rule, b0, b1, a);
213   else
214     table_vline (t, rule, a, b0, b1);
215 }
216
217 /* Fills row or column headings into T.
218
219    This function uses terminology and variable names for column headings, but
220    it also applies to row headings because it uses variables for the
221    differences, e.g. when for column headings it would use the H axis, it
222    instead uses 'h', which is set to H for column headings and V for row
223    headings.  */
224 static void
225 compose_headings (struct table *t,
226                   const struct pivot_axis *a_axis, enum table_axis a,
227                   const struct pivot_axis *b_axis,
228                   const struct table_border_style *borders,
229                   enum pivot_border dim_col_horz,
230                   enum pivot_border dim_col_vert,
231                   enum pivot_border cat_col_horz,
232                   enum pivot_border cat_col_vert,
233                   const size_t *column_enumeration, size_t n_columns,
234                   const struct table_area_style *label_style,
235                   int label_style_idx,
236                   const struct table_area_style *corner_style,
237                   struct footnote **footnotes,
238                   enum settings_value_show show_values,
239                   enum settings_value_show show_variables,
240                   bool rotate_inner_labels, bool rotate_outer_labels)
241 {
242   enum table_axis b = !a;
243   int b_size = a_axis->label_depth;
244   int a_ofs = b_axis->label_depth;
245
246   if (!a_axis->n_dimensions || !n_columns || !b_size)
247     return;
248
249   const int stride = MAX (1, a_axis->n_dimensions);
250
251   /* Below, we're going to iterate through the dimensions.  Each dimension
252      occupies one or more rows in the heading.  'top_row' is the top row of
253      these (and 'top_row + d->label_depth - 1' is the bottom row). */
254   int top_row = 0;
255
256   /* We're going to iterate through dimensions and the rows that label them
257      from top to bottom (from outer to inner dimensions).  As we move downward,
258      we start drawing vertical rules to separate categories and groups.  After
259      we start drawing a vertical rule in a particular horizontal position, it
260      continues until the bottom of the heading.  vrules[pos] indicates whether,
261      in our current row, we have already started drawing a vertical rule in
262      horizontal position 'pos'.  (There are n_columns + 1 horizontal positions.
263      We allocate all of them for convenience below but only the inner n_columns
264      - 1 of them really matter.)
265
266      Here's an example that shows how vertical rules continue all the way
267      downward:
268
269      +-----------------------------------------------------+ __
270      |                         bbbb                        |  |
271      +-----------------+-----------------+-----------------+  |dimension "bbbb"
272      |      bbbb1      |      bbbb2      |      bbbb3      | _|
273      +-----------------+-----------------+-----------------+ __
274      |       aaaa      |       aaaa      |       aaaa      |  |
275      +-----+-----+-----+-----+-----+-----+-----+-----+-----+  |dimension "aaaa"
276      |aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3| _|
277      +-----+-----+-----+-----+-----+-----+-----+-----+-----+
278
279      ^     ^     ^     ^     ^     ^     ^     ^     ^     ^
280      |     |     |     |     |     |     |     |     |     |
281      0     1     2     3     4     5     6     7     8     9
282      |___________________vrules[] indexes__________________|
283
284      Our data structures are more naturally iterated from bottom to top (inner
285      to outer dimensions).  A previous version of this code actually worked
286      like that, but it didn't draw all of the vertical lines correctly as shown
287      above.  It ended up rendering the above heading much like shown below,
288      which isn't what users expect.  The "aaaa" label really needs to be shown
289      three times for clarity:
290
291      +-----------------------------------------------------+
292      |                         bbbb                        |
293      +-----------------+-----------------+-----------------+
294      |      bbbb1      |      bbbb2      |      bbbb3      |
295      +-----------------+-----------------+-----------------+
296      |                 |       aaaa      |                 |
297      +-----+-----+-----+-----+-----+-----+-----+-----+-----+
298      |aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3|
299      +-----+-----+-----+-----+-----+-----+-----+-----+-----+
300   */
301   bool *vrules = xzalloc (n_columns + 1);
302   vrules[0] = vrules[n_columns] = true;
303   for (int dim_index = a_axis->n_dimensions; --dim_index >= 0; )
304     {
305       const struct pivot_dimension *d = a_axis->dimensions[dim_index];
306       if (d->hide_all_labels)
307         continue;
308
309       for (int row_ofs = 0; row_ofs < d->label_depth; row_ofs++)
310         {
311           for (size_t x1 = 0; x1 < n_columns;)
312             {
313               const struct pivot_category *c = find_category (
314                 d, dim_index, column_enumeration + x1 * stride,
315                 d->label_depth - row_ofs - 1);
316               if (!c)
317                 {
318                   x1++;
319                   continue;
320                 }
321
322               size_t x2;
323               for (x2 = x1 + 1; x2 < n_columns; x2++)
324                 {
325                   if (vrules[x2])
326                     break;
327                   const struct pivot_category *c2 = find_category (
328                     d, dim_index, column_enumeration + x2 * stride,
329                     d->label_depth - row_ofs - 1);
330                   if (c != c2)
331                     break;
332                 }
333
334               int y1 = top_row + row_ofs;
335               int y2 = top_row + row_ofs + c->extra_depth + 1;
336               bool is_outer_row = y1 == 0;
337               bool is_inner_row = y2 == b_size;
338               if (pivot_category_is_leaf (c) || c->show_label)
339                 {
340                   int bb[TABLE_N_AXES][2];
341                   bb[a][0] = x1 + a_ofs;
342                   bb[a][1] = x2 + a_ofs - 1;
343                   bb[b][0] = y1;
344                   bb[b][1] = y2 - 1;
345                   bool rotate = ((rotate_inner_labels && is_inner_row)
346                                  || (rotate_outer_labels && is_outer_row));
347                   fill_cell (t, bb[H][0], bb[V][0], bb[H][1], bb[V][1],
348                              label_style, label_style_idx, c->name, footnotes,
349                              show_values, show_variables, rotate);
350
351                   /* Draw all the vertical lines in our running example, other
352                      than the far left and far right ones.  Only the ones that
353                      start in the last row of the heading are drawn with the
354                      "category" style, the rest with the "dimension" style,
355                      e.g. only the # below are category style:
356
357                      +-----------------------------------------------------+
358                      |                         bbbb                        |
359                      +-----------------+-----------------+-----------------+
360                      |      bbbb1      |      bbbb2      |      bbbb3      |
361                      +-----------------+-----------------+-----------------+
362                      |       aaaa      |       aaaa      |       aaaa      |
363                      +-----+-----+-----+-----+-----+-----+-----+-----+-----+
364                      |aaaa1#aaaa2#aaaa3|aaaa1#aaaa2#aaaa3|aaaa1#aaaa2#aaaa3|
365                      +-----+-----+-----+-----+-----+-----+-----+-----+-----+
366                   */
367                   enum pivot_border style
368                     = (y1 == b_size - 1 ? cat_col_vert : dim_col_vert);
369                   if (!vrules[x2])
370                     {
371                       draw_line (t, borders, style, b, x2 + a_ofs, y1,
372                                  t->n[b] - 1);
373                       vrules[x2] = true;
374                     }
375                   if (!vrules[x1])
376                     {
377                       draw_line (t, borders, style, b, x1 + a_ofs, y1,
378                                  t->n[b] - 1);
379                       vrules[x1] = true;
380                     }
381                 }
382
383               /* Draws the horizontal lines within a dimension, that is, those
384                  that separate a separating a category (or group) from its
385                  parent group or dimension's label.  Our running example
386                  doesn't have groups but the ==== lines below show the
387                  separators between categories and their dimension label:
388
389                  +-----------------------------------------------------+
390                  |                         bbbb                        |
391                  +=================+=================+=================+
392                  |      bbbb1      |      bbbb2      |      bbbb3      |
393                  +-----------------+-----------------+-----------------+
394                  |       aaaa      |       aaaa      |       aaaa      |
395                  +=====+=====+=====+=====+=====+=====+=====+=====+=====+
396                  |aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3|
397                  +-----+-----+-----+-----+-----+-----+-----+-----+-----+
398               */
399               if (c->parent && c->parent->show_label)
400                 draw_line (t, borders, cat_col_horz, a, y1,
401                            x1 + a_ofs, x2 + a_ofs - 1);
402               x1 = x2;
403             }
404         }
405
406       if (d->root->show_label_in_corner && a_ofs > 0)
407         {
408           int bb[TABLE_N_AXES][2];
409           bb[a][0] = 0;
410           bb[a][1] = a_ofs - 1;
411           bb[b][0] = top_row;
412           bb[b][1] = top_row + d->label_depth - 1;
413           fill_cell (t, bb[H][0], bb[V][0], bb[H][1], bb[V][1],
414                      corner_style, PIVOT_AREA_CORNER, d->root->name, footnotes,
415                      show_values, show_variables, false);
416         }
417
418       /* Draw the horizontal line between dimensions, e.g. the ===== line here:
419
420          +-----------------------------------------------------+ __
421          |                         bbbb                        |  |
422          +-----------------+-----------------+-----------------+  |dim "bbbb"
423          |      bbbb1      |      bbbb2      |      bbbb3      | _|
424          +=================+=================+=================+ __
425          |       aaaa      |       aaaa      |       aaaa      |  |
426          +-----+-----+-----+-----+-----+-----+-----+-----+-----+  |dim "aaaa"
427          |aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3| _|
428          +-----+-----+-----+-----+-----+-----+-----+-----+-----+
429       */
430       if (dim_index != a_axis->n_dimensions - 1)
431         draw_line (t, borders, dim_col_horz, a, top_row, a_ofs,
432                    t->n[a] - 1);
433       top_row += d->label_depth;
434     }
435   free (vrules);
436 }
437
438 static void
439 pivot_table_submit_layer (const struct pivot_table *pt,
440                           const size_t *layer_indexes)
441 {
442   const size_t *pindexes[PIVOT_N_AXES]
443     = { [PIVOT_AXIS_LAYER] = layer_indexes };
444
445   size_t body[TABLE_N_AXES];
446   size_t *column_enumeration = pivot_table_enumerate_axis (
447     pt, PIVOT_AXIS_COLUMN, layer_indexes, pt->look->omit_empty, &body[H]);
448   size_t *row_enumeration = pivot_table_enumerate_axis (
449     pt, PIVOT_AXIS_ROW, layer_indexes, pt->look->omit_empty, &body[V]);
450
451   int stub[TABLE_N_AXES] = {
452     [H] = pt->axes[PIVOT_AXIS_ROW].label_depth,
453     [V] = pt->axes[PIVOT_AXIS_COLUMN].label_depth,
454   };
455   struct table *table = table_create (body[H] + stub[H],
456                                       body[V] + stub[V],
457                                       stub[H], 0, stub[V], 0);
458
459   for (size_t i = 0; i < PIVOT_N_AREAS; i++)
460     table->styles[i] = table_area_style_override (
461       table->container, &pt->look->areas[i], NULL, NULL, false);
462
463   for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
464     {
465       const struct table_border_style *in = &pt->look->borders[i];
466       table->rule_colors[i] = pool_alloc (table->container,
467                                           sizeof *table->rule_colors[i]);
468       struct cell_color *out = table->rule_colors[i];
469       out->alpha = in->color.alpha;
470       out->r = in->color.r;
471       out->g = in->color.g;
472       out->b = in->color.b;
473     }
474
475   struct footnote **footnotes = XCALLOC (pt->n_footnotes,  struct footnote *);
476   for (size_t i = 0; i < pt->n_footnotes; i++)
477     {
478       const struct pivot_footnote *pf = pt->footnotes[i];
479
480       if (!pf->show)
481         continue;
482
483       char *content = pivot_value_to_string (pf->content, pt->show_values,
484                                              pt->show_variables);
485       char *marker = pivot_value_to_string (pf->marker, pt->show_values,
486                                             pt->show_variables);
487       footnotes[i] = table_create_footnote (
488         table, i, content, marker,
489         table_area_style_override (table->container,
490                                    &pt->look->areas[PIVOT_AREA_FOOTER],
491                                    pf->content->cell_style,
492                                    pf->content->font_style,
493                                    false));
494       free (marker);
495       free (content);
496     }
497
498   compose_headings (table,
499                     &pt->axes[PIVOT_AXIS_COLUMN], H, &pt->axes[PIVOT_AXIS_ROW],
500                     pt->look->borders,
501                     PIVOT_BORDER_DIM_COL_HORZ,
502                     PIVOT_BORDER_DIM_COL_VERT,
503                     PIVOT_BORDER_CAT_COL_HORZ,
504                     PIVOT_BORDER_CAT_COL_VERT,
505                     column_enumeration, body[H],
506                     &pt->look->areas[PIVOT_AREA_COLUMN_LABELS],
507                     PIVOT_AREA_COLUMN_LABELS,
508                     &pt->look->areas[PIVOT_AREA_CORNER], footnotes,
509                     pt->show_values, pt->show_variables,
510                     pt->rotate_outer_row_labels, false);
511
512   compose_headings (table,
513                     &pt->axes[PIVOT_AXIS_ROW], V, &pt->axes[PIVOT_AXIS_COLUMN],
514                     pt->look->borders,
515                     PIVOT_BORDER_DIM_ROW_VERT,
516                     PIVOT_BORDER_DIM_ROW_HORZ,
517                     PIVOT_BORDER_CAT_ROW_VERT,
518                     PIVOT_BORDER_CAT_ROW_HORZ,
519                     row_enumeration, body[V],
520                     &pt->look->areas[PIVOT_AREA_ROW_LABELS],
521                     PIVOT_AREA_ROW_LABELS,
522                     &pt->look->areas[PIVOT_AREA_CORNER], footnotes,
523                     pt->show_values, pt->show_variables,
524                     false, pt->rotate_inner_column_labels);
525
526   size_t *dindexes = XCALLOC (pt->n_dimensions, size_t);
527   size_t y = 0;
528   PIVOT_ENUMERATION_FOR_EACH (pindexes[PIVOT_AXIS_ROW], row_enumeration,
529                               &pt->axes[PIVOT_AXIS_ROW])
530     {
531       size_t x = 0;
532       PIVOT_ENUMERATION_FOR_EACH (pindexes[PIVOT_AXIS_COLUMN],
533                                   column_enumeration,
534                                   &pt->axes[PIVOT_AXIS_COLUMN])
535         {
536           pivot_table_convert_indexes_ptod (pt, pindexes, dindexes);
537           const struct pivot_value *value = pivot_table_get (pt, dindexes);
538           fill_cell (table,
539                      x + stub[H], y + stub[V],
540                      x + stub[H], y + stub[V],
541                      &pt->look->areas[PIVOT_AREA_DATA], PIVOT_AREA_DATA,
542                      value, footnotes,
543                      pt->show_values, pt->show_variables, false);
544
545           x++;
546         }
547
548       y++;
549     }
550   free (dindexes);
551
552   if ((pt->corner_text || !pt->look->row_labels_in_corner)
553       && stub[H] && stub[V])
554     fill_cell (table, 0, 0, stub[H] - 1, stub[V] - 1,
555                &pt->look->areas[PIVOT_AREA_CORNER], PIVOT_AREA_CORNER,
556                pt->corner_text, footnotes,
557                pt->show_values, pt->show_variables, false);
558
559   if (table->n[H] && table->n[V])
560     {
561       table_hline (
562         table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_TOP),
563         0, table->n[H] - 1, 0);
564       table_hline (
565         table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_BOTTOM),
566         0, table->n[H] - 1, table->n[V]);
567       table_vline (
568         table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_LEFT),
569         0, 0, table->n[V] - 1);
570       table_vline (
571         table, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_RIGHT),
572         table->n[H], 0, table->n[V] - 1);
573
574       if (stub[V])
575         table_hline (
576           table, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_TOP),
577           0, table->n[H] - 1, stub[V]);
578       if (stub[H])
579         table_vline (
580           table, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_LEFT),
581           stub[H], 0, table->n[V] - 1);
582
583     }
584   free (column_enumeration);
585   free (row_enumeration);
586
587   struct table_item *ti = table_item_create (table);
588
589   if (pt->notes)
590     table_item_set_notes (ti, pt->notes);
591
592   if (pt->title && pt->show_title)
593     {
594       struct table_cell *title = pivot_value_to_table_cell (
595         pt->title, &pt->look->areas[PIVOT_AREA_TITLE], PIVOT_AREA_TITLE,
596         footnotes, pt->show_values, pt->show_variables);
597       table_item_set_title (ti, title);
598       table_cell_destroy (title);
599     }
600
601   const struct pivot_axis *layer_axis = &pt->axes[PIVOT_AXIS_LAYER];
602   struct table_item_layers *layers = NULL;
603   for (size_t i = 0; i < layer_axis->n_dimensions; i++)
604     {
605       const struct pivot_dimension *d = layer_axis->dimensions[i];
606       if (d->n_leaves)
607         {
608           if (!layers)
609             {
610               layers = xzalloc (sizeof *layers);
611               layers->style = table_area_style_override (
612                 NULL, &pt->look->areas[PIVOT_AREA_LAYERS], NULL, NULL, false);
613               layers->layers = xnmalloc (layer_axis->n_dimensions,
614                                          sizeof *layers->layers);
615             }
616
617           const struct pivot_value *name
618             = d->data_leaves[layer_indexes[i]]->name;
619           struct table_item_layer *layer = &layers->layers[layers->n_layers++];
620           struct string s = DS_EMPTY_INITIALIZER;
621           pivot_value_format_body (name, pt->show_values, pt->show_variables,
622                                    &s);
623           layer->content = ds_steal_cstr (&s);
624           layer->n_footnotes = 0;
625           layer->footnotes = xnmalloc (name->n_footnotes,
626                                        sizeof *layer->footnotes);
627           for (size_t i = 0; i < name->n_footnotes; i++)
628             {
629               struct footnote *f = footnotes[name->footnotes[i]->idx];
630               if (f)
631                 layer->footnotes[layer->n_footnotes++] = f;
632             }
633         }
634     }
635   if (layers)
636     {
637       table_item_set_layers (ti, layers);
638       table_item_layers_destroy (layers);
639     }
640
641   if (pt->caption && pt->show_caption)
642     {
643       struct table_cell *caption = pivot_value_to_table_cell (
644         pt->caption, &pt->look->areas[PIVOT_AREA_CAPTION], PIVOT_AREA_CAPTION,
645         footnotes, pt->show_values, pt->show_variables);
646       table_item_set_caption (ti, caption);
647       table_cell_destroy (caption);
648     }
649
650   free (footnotes);
651   ti->pt = pivot_table_ref (pt);
652
653   table_item_submit (ti);
654 }
655
656 void
657 pivot_table_submit (struct pivot_table *pt)
658 {
659   pivot_table_assign_label_depth (CONST_CAST (struct pivot_table *, pt));
660
661   int old_decimal = settings_get_decimal_char (FMT_COMMA);
662   if (pt->decimal == '.' || pt->decimal == ',')
663     settings_set_decimal_char (pt->decimal);
664
665   if (pt->look->print_all_layers)
666     {
667       size_t *layer_indexes;
668
669       PIVOT_AXIS_FOR_EACH (layer_indexes, &pt->axes[PIVOT_AXIS_LAYER])
670         {
671           if (pt->look->paginate_layers)
672             page_eject_item_submit (page_eject_item_create ());
673           pivot_table_submit_layer (pt, layer_indexes);
674         }
675     }
676   else
677     pivot_table_submit_layer (pt, pt->current_layer);
678
679   settings_set_decimal_char (old_decimal);
680
681   pivot_table_unref (pt);
682 }