96821170eff043db82a47e88004d19f2ba84747c
[pspp] / src / output / pivot-table.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2017, 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 "output/pivot-table.h"
20
21 #include <stdlib.h>
22
23 #include "data/data-out.h"
24 #include "data/settings.h"
25 #include "data/value.h"
26 #include "data/variable.h"
27 #include "libpspp/hash-functions.h"
28 #include "libpspp/i18n.h"
29
30 #include "gl/c-ctype.h"
31 #include "gl/intprops.h"
32 #include "gl/minmax.h"
33 #include "gl/xalloc.h"
34 #include "gl/xmemdup0.h"
35 #include "gl/xsize.h"
36
37 #include "gettext.h"
38 #define _(msgid) gettext (msgid)
39 #define N_(msgid) msgid
40
41 static const struct fmt_spec *pivot_table_get_format (
42   const struct pivot_table *, const char *s);
43 \f
44 /* Pivot table display styling. */
45
46 /* Returns the name of AREA. */
47 const char *
48 pivot_area_to_string (enum pivot_area area)
49 {
50   switch (area)
51     {
52     case PIVOT_AREA_TITLE: return "title";
53     case PIVOT_AREA_CAPTION: return "caption";
54     case PIVOT_AREA_FOOTER: return "footer";
55     case PIVOT_AREA_CORNER: return "corner";
56     case PIVOT_AREA_COLUMN_LABELS: return "column labels";
57     case PIVOT_AREA_ROW_LABELS: return "row labels";
58     case PIVOT_AREA_DATA: return "data";
59     case PIVOT_AREA_LAYERS: return "layers";
60     case PIVOT_N_AREAS: default: return "**error**";
61     }
62 }
63
64 /* Returns the name of BORDER. */
65 const char *
66 pivot_border_to_string (enum pivot_border border)
67 {
68   switch (border)
69     {
70     case PIVOT_BORDER_TITLE:
71       return "title";
72
73     case PIVOT_BORDER_OUTER_LEFT:
74       return "left outer frame";
75     case PIVOT_BORDER_OUTER_TOP:
76       return "top outer frame";
77     case PIVOT_BORDER_OUTER_RIGHT:
78       return "right outer frame";
79     case PIVOT_BORDER_OUTER_BOTTOM:
80       return "bottom outer frame";
81
82     case PIVOT_BORDER_INNER_LEFT:
83       return "left inner frame";
84     case PIVOT_BORDER_INNER_TOP:
85       return "top inner frame";
86     case PIVOT_BORDER_INNER_RIGHT:
87       return "right inner frame";
88     case PIVOT_BORDER_INNER_BOTTOM:
89       return "bottom inner frame";
90
91     case PIVOT_BORDER_DATA_LEFT:
92       return "data area left";
93     case PIVOT_BORDER_DATA_TOP:
94       return "data area top";
95
96     case PIVOT_BORDER_DIM_ROW_HORZ:
97       return "row label horizontal dimension border";
98     case PIVOT_BORDER_DIM_ROW_VERT:
99       return "row label vertical dimension border";
100     case PIVOT_BORDER_DIM_COL_HORZ:
101       return "column label horizontal dimension border";
102     case PIVOT_BORDER_DIM_COL_VERT:
103       return "column label vertical dimension border";
104
105     case PIVOT_BORDER_CAT_ROW_HORZ:
106       return "row label horizontal category border";
107     case PIVOT_BORDER_CAT_ROW_VERT:
108       return "row label vertical category border";
109     case PIVOT_BORDER_CAT_COL_HORZ:
110       return "column label horizontal category border";
111     case PIVOT_BORDER_CAT_COL_VERT:
112       return "column label vertical category border";
113
114     case PIVOT_N_BORDERS:
115     default:
116       return "**error**";
117     }
118 }
119
120 void
121 pivot_table_sizing_uninit (struct pivot_table_sizing *sizing)
122 {
123   if (sizing)
124     {
125       free (sizing->widths);
126       free (sizing->breaks);
127       free (sizing->keeps);
128     }
129 }
130 \f
131 /* Axes. */
132
133 /* Returns the name of AXIS_TYPE. */
134 const char *
135 pivot_axis_type_to_string (enum pivot_axis_type axis_type)
136 {
137   switch (axis_type)
138     {
139     case PIVOT_AXIS_LAYER:
140       return "layer";
141
142     case PIVOT_AXIS_ROW:
143       return "row";
144
145     case PIVOT_AXIS_COLUMN:
146       return "column";
147
148     default:
149       return "<error>";
150     }
151 }
152
153 static enum pivot_axis_type
154 pivot_axis_type_transpose (enum pivot_axis_type axis_type)
155 {
156   assert (axis_type == PIVOT_AXIS_ROW || axis_type == PIVOT_AXIS_COLUMN);
157   return (axis_type == PIVOT_AXIS_ROW ? PIVOT_AXIS_COLUMN : PIVOT_AXIS_ROW);
158 }
159
160 /* Implementation of PIVOT_AXIS_FOR_EACH. */
161 size_t *
162 pivot_axis_iterator_next (size_t *indexes, const struct pivot_axis *axis)
163 {
164   if (!indexes)
165     {
166       if (axis->n_dimensions)
167         for (size_t i = 0; i < axis->n_dimensions; i++)
168           if (axis->dimensions[i]->n_leaves == 0)
169             return NULL;
170
171       return xcalloc (axis->n_dimensions, sizeof *indexes);
172     }
173
174   for (size_t i = 0; i < axis->n_dimensions; i++)
175     {
176       const struct pivot_dimension *d = axis->dimensions[i];
177       if (++indexes[i] < d->n_leaves)
178         return indexes;
179
180       indexes[i] = 0;
181     }
182
183   free (indexes);
184   return NULL;
185 }
186 \f
187 /* Dimensions. */
188
189 static void
190 pivot_category_set_rc (struct pivot_category *category, const char *s)
191 {
192   const struct fmt_spec *format = pivot_table_get_format (
193     category->dimension->table, s);
194   if (format)
195     category->format = *format;
196 }
197
198 static void
199 pivot_category_create_leaves_valist (struct pivot_category *parent,
200                                      va_list args)
201 {
202   const char *s;
203   while ((s = va_arg (args, const char *)))
204     {
205       if (!strncmp (s, "RC_", 3))
206         {
207           assert (parent->n_subs);
208           pivot_category_set_rc (parent->subs[parent->n_subs - 1], s);
209         }
210       else
211         pivot_category_create_leaf (parent, pivot_value_new_text (s));
212     }
213 }
214
215 /* Creates a new dimension with the given NAME in TABLE and returns it.  The
216    dimension is added to axis AXIS_TYPE, becoming the outermost dimension on
217    that axis.
218
219    NAME should be a translatable name, but not actually translated yet,
220    e.g. enclosed in N_().  To use a different kind of value for a name, use
221    pivot_dimension_create__() instead.
222
223    The optional varargs parameters may be used to add an initial set of
224    categories to the dimension.  Each string should be a translatable category
225    name, but not actually translated yet, e.g. enclosed in N_().  Each string
226    may optionally be followod by a PIVOT_RC_* string that specifies the default
227    numeric format for cells in this category. */
228 struct pivot_dimension * SENTINEL (0)
229 (pivot_dimension_create) (struct pivot_table *table,
230                           enum pivot_axis_type axis_type,
231                           const char *name, ...)
232 {
233   struct pivot_dimension *d = pivot_dimension_create__ (
234     table, axis_type, pivot_value_new_text (name));
235
236   va_list args;
237   va_start (args, name);
238   pivot_category_create_leaves_valist (d->root, args);
239   va_end (args);
240
241   return d;
242 }
243
244 /* Creates a new dimension with the given NAME in TABLE and returns it.  The
245    dimension is added to axis AXIS_TYPE, becoming the outermost dimension on
246    that axis. */
247 struct pivot_dimension *
248 pivot_dimension_create__ (struct pivot_table *table,
249                           enum pivot_axis_type axis_type,
250                           struct pivot_value *name)
251 {
252   assert (pivot_table_is_empty (table));
253
254   struct pivot_dimension *d = xmalloc (sizeof *d);
255   *d = (struct pivot_dimension) {
256     .table = table,
257     .axis_type = axis_type,
258     .level = table->axes[axis_type].n_dimensions,
259     .top_index = table->n_dimensions,
260     .root = xmalloc (sizeof *d->root),
261   };
262
263   struct pivot_category *root = d->root;
264   *root = (struct pivot_category) {
265     .name = name,
266     .parent = NULL,
267     .dimension = d,
268     .show_label = false,
269     .data_index = SIZE_MAX,
270     .presentation_index = SIZE_MAX,
271   };
272
273   table->dimensions = xrealloc (
274     table->dimensions, (table->n_dimensions + 1) * sizeof *table->dimensions);
275   table->dimensions[table->n_dimensions++] = d;
276
277   struct pivot_axis *axis = &table->axes[axis_type];
278   axis->dimensions = xrealloc (
279     axis->dimensions, (axis->n_dimensions + 1) * sizeof *axis->dimensions);
280   axis->dimensions[axis->n_dimensions++] = d;
281
282   /* XXX extent and label_depth need to be calculated later. */
283
284   return d;
285 }
286
287 void
288 pivot_dimension_destroy (struct pivot_dimension *d)
289 {
290   if (!d)
291     return;
292
293   pivot_category_destroy (d->root);
294   free (d->data_leaves);
295   free (d->presentation_leaves);
296   free (d);
297 }
298
299 /* Returns the first leaf node in an in-order traversal that is a child of
300    CAT. */
301 static const struct pivot_category * UNUSED
302 pivot_category_first_leaf (const struct pivot_category *cat)
303 {
304   if (pivot_category_is_leaf (cat))
305     return cat;
306
307   for (size_t i = 0; i < cat->n_subs; i++)
308     {
309       const struct pivot_category *first
310         = pivot_category_first_leaf (cat->subs[i]);
311       if (first)
312         return first;
313     }
314
315   return NULL;
316 }
317
318 /* Returns the next leaf node in an in-order traversal starting at CAT, which
319    must be a leaf. */
320 static const struct pivot_category * UNUSED
321 pivot_category_next_leaf (const struct pivot_category *cat)
322 {
323   assert (pivot_category_is_leaf (cat));
324
325   for (;;)
326     {
327       const struct pivot_category *parent = cat->parent;
328       if (!parent)
329         return NULL;
330       for (size_t i = cat->group_index + 1; i < parent->n_subs; i++)
331         {
332           const struct pivot_category *next
333             = pivot_category_first_leaf (parent->subs[i]);
334           if (next)
335             return next;
336         }
337
338       cat = cat->parent;
339     }
340 }
341
342 static void
343 pivot_category_add_child (struct pivot_category *child)
344 {
345   struct pivot_category *parent = child->parent;
346
347   assert (pivot_category_is_group (parent));
348   if (parent->n_subs >= parent->allocated_subs)
349     parent->subs = x2nrealloc (parent->subs, &parent->allocated_subs,
350                                sizeof *parent->subs);
351   parent->subs[parent->n_subs++] = child;
352 }
353
354 /* Adds leaf categories as a child of PARENT.  To create top-level categories
355    within dimension 'd', pass 'd->root' for PARENT.
356
357    Each of the varargs parameters should be a string, each of which should be a
358    translatable category name, but not actually translated yet, e.g. enclosed
359    in N_().  Each string may optionally be followod by a PIVOT_RC_* string that
360    specifies the default numeric format for cells in this category.
361
362    Returns the category index, which is just a 0-based array index, for the
363    first new category.
364
365    Leaves have to be created in in-order, that is, don't create a group and add
366    some leaves, then add leaves outside the group and try to add more leaves
367    inside it. */
368 int SENTINEL (0)
369 (pivot_category_create_leaves) (struct pivot_category *parent, ...)
370 {
371   int retval = parent->dimension->n_leaves;
372
373   va_list args;
374   va_start (args, parent);
375   pivot_category_create_leaves_valist (parent, args);
376   va_end (args);
377
378   return retval;
379 }
380
381 /* Creates a new leaf category with the given NAME as a child of PARENT.  To
382    create a top-level category within dimension 'd', pass 'd->root' for PARENT.
383    Returns the category index, which is just a 0-based array index, for the new
384    category.
385
386    Leaves have to be created in in-order, that is, don't create a group and add
387    some leaves, then add leaves outside the group and try to add more leaves
388    inside it. */
389 int
390 pivot_category_create_leaf (struct pivot_category *parent,
391                             struct pivot_value *name)
392 {
393   return pivot_category_create_leaf_rc (parent, name, NULL);
394 }
395
396 /* Creates a new leaf category with the given NAME as a child of PARENT.  To
397    create a top-level category within dimension 'd', pass 'd->root' for PARENT.
398    Returns the category index, which is just a 0-based array index, for the new
399    category.
400
401    If RC is nonnull and the name of a result category, the category is assigned
402    that result category.
403
404    Leaves have to be created in in-order, that is, don't create a group and add
405    some leaves, then add leaves outside the group and try to add more leaves
406    inside it. */
407 int
408 pivot_category_create_leaf_rc (struct pivot_category *parent,
409                                struct pivot_value *name, const char *rc)
410 {
411   struct pivot_dimension *d = parent->dimension;
412
413   struct pivot_category *leaf = xmalloc (sizeof *leaf);
414   *leaf = (struct pivot_category) {
415     .name = name,
416     .parent = parent,
417     .dimension = d,
418     .group_index = parent->n_subs,
419     .data_index = d->n_leaves,
420     .presentation_index = d->n_leaves,
421   };
422
423   if (d->n_leaves >= d->allocated_leaves)
424     {
425       d->data_leaves = x2nrealloc (d->data_leaves, &d->allocated_leaves,
426                                    sizeof *d->data_leaves);
427       d->presentation_leaves = xrealloc (
428         d->presentation_leaves,
429         d->allocated_leaves * sizeof *d->presentation_leaves);
430     }
431
432   d->data_leaves[d->n_leaves] = leaf;
433   d->presentation_leaves[d->n_leaves] = leaf;
434   d->n_leaves++;
435
436   pivot_category_add_child (leaf);
437
438   /* Make sure that the new child is the last in in-order. */
439   assert (!pivot_category_next_leaf (leaf));
440
441   pivot_category_set_rc (leaf, rc);
442
443   return leaf->data_index;
444 }
445
446 /* Adds a new category group named NAME as a child of PARENT.  To create a
447    top-level group within dimension 'd', pass 'd->root' for PARENT.
448
449    NAME should be a translatable name, but not actually translated yet,
450    e.g. enclosed in N_().  To use a different kind of value for a name, use
451    pivot_category_create_group__() instead.
452
453    The optional varargs parameters may be used to add an initial set of
454    categories to the group.  Each string should be a translatable category
455    name, but not actually translated yet, e.g. enclosed in N_().  Each string
456    may optionally be followod by a PIVOT_RC_* string that specifies the default
457    numeric format for cells in this category.
458
459    Returns the new group. */
460 struct pivot_category * SENTINEL (0)
461 (pivot_category_create_group) (struct pivot_category *parent,
462                                const char *name, ...)
463 {
464   struct pivot_category *group = pivot_category_create_group__ (
465     parent, pivot_value_new_text (name));
466
467   va_list args;
468   va_start (args, name);
469   pivot_category_create_leaves_valist (group, args);
470   va_end (args);
471
472   return group;
473 }
474
475 /* Adds a new category group named NAME as a child of PARENT.  To create a
476    top-level group within dimension 'd', pass 'd->root' for PARENT.  Returns
477    the new group. */
478 struct pivot_category *
479 pivot_category_create_group__ (struct pivot_category *parent,
480                                struct pivot_value *name)
481 {
482   struct pivot_dimension *d = parent->dimension;
483
484   struct pivot_category *group = xmalloc (sizeof *group);
485   *group = (struct pivot_category) {
486     .name = name,
487     .parent = parent,
488     .dimension = d,
489     .show_label = true,
490     .group_index = parent->n_subs,
491     .data_index = SIZE_MAX,
492     .presentation_index = SIZE_MAX,
493   };
494
495   pivot_category_add_child (group);
496
497   return group;
498 }
499
500 void
501 pivot_category_destroy (struct pivot_category *c)
502 {
503   if (!c)
504     return;
505
506   pivot_value_destroy (c->name);
507   for (size_t i = 0; i < c->n_subs; i++)
508     pivot_category_destroy (c->subs[i]);
509   free (c->subs);
510   free (c);
511 }
512 \f
513 /* Result classes.
514
515    These are usually the easiest way to control the formatting of numeric data
516    in a pivot table.  See pivot_dimension_create() for an explanation of their
517    use.  */
518 struct result_class
519   {
520     const char *name;           /* "RC_*". */
521     struct fmt_spec format;
522   };
523
524 /* Formats for most of the result classes. */
525 static struct result_class result_classes[] =
526   {
527     { PIVOT_RC_INTEGER,      { FMT_F,   40, 0 } },
528     { PIVOT_RC_PERCENT,      { FMT_PCT, 40, 1 } },
529     { PIVOT_RC_CORRELATION,  { FMT_F,   40, 3 } },
530     { PIVOT_RC_SIGNIFICANCE, { FMT_F,   40, 3 } },
531     { PIVOT_RC_RESIDUAL,     { FMT_F,   40, 2 } },
532     { PIVOT_RC_COUNT,        { 0, 0, 0 } },
533     { PIVOT_RC_OTHER,        { 0, 0, 0 } },
534   };
535
536 /* Has PIVOT_RC_COUNT been overridden by the user? */
537 static bool overridden_count_format;
538
539 static struct result_class *
540 pivot_result_class_find (const char *s)
541 {
542   for (size_t i = 0; i < sizeof result_classes / sizeof *result_classes; i++)
543     if (!strcmp (s, result_classes[i].name))
544       return &result_classes[i];
545   return NULL;
546 }
547
548 static const struct fmt_spec *
549 pivot_table_get_format (const struct pivot_table *table, const char *s)
550 {
551   if (!s)
552     return NULL;
553   else if (!strcmp (s, PIVOT_RC_OTHER))
554     return settings_get_format ();
555   else if (!strcmp (s, PIVOT_RC_COUNT) && !overridden_count_format)
556     return &table->weight_format;
557   else
558     {
559       const struct result_class *rc = pivot_result_class_find (s);
560       return rc ? &rc->format : NULL;
561     }
562 }
563
564 /* Sets the format specification for the result class named S (which should not
565    include the RC_ prefix) to *FORMAT.  Returns true if successful, false if S
566    does not name a known result class. */
567 bool
568 pivot_result_class_change (const char *s_, const struct fmt_spec *format)
569 {
570   char *s = xasprintf ("RC_%s", s_);
571   struct result_class *rc = pivot_result_class_find (s);
572   if (rc)
573     {
574       rc->format = *format;
575       if (!strcmp (s, PIVOT_RC_COUNT))
576         overridden_count_format = true;
577     }
578   free (s);
579
580   return rc != NULL;
581 }
582 \f
583 /* One piece of data within a pivot table. */
584 struct pivot_cell
585   {
586     struct hmap_node hmap_node; /* In struct pivot_table's 'cells' hmap. */
587     struct pivot_value *value;
588     unsigned int idx[];         /* One index per table dimension. */
589   };
590
591 /* Pivot tables. */
592
593 /* Creates and returns a new pivot table with the given TITLE.  TITLE should be
594    a text string marked for translation but not actually translated yet,
595    e.g. N_("Descriptive Statistics").
596
597    Operations commonly performed on the new pivot_table:
598
599    - If empty rows or columns should not be displayed, set ->omit_empty to
600      true.
601
602    - Set the format to use for "count" values with pivot_table_set_weight_var()
603      or pivot_table_set_weight_format().
604
605    This function is a shortcut for pivot_table_create__() for the most common
606    case.  Use pivot_table_create__() directly if the title should be some kind
607    of value other than an ordinary text string.
608
609    See the large comment at the top of pivot-table.h for general advice on
610    creating pivot tables. */
611 struct pivot_table *
612 pivot_table_create (const char *title)
613 {
614   return pivot_table_create__ (pivot_value_new_text (title));
615 }
616
617 /* Creates and returns a new pivot table with the given TITLE.
618
619    Operations commonly performed on the new pivot_table:
620
621    - If empty rows or columns should not be displayed, set ->omit_empty to
622      true.
623
624    - Set the format to use for "count" values with pivot_table_set_weight_var()
625      or pivot_table_set_weight_format().
626
627    See the large comment at the top of pivot-table.h for general advice on
628    creating pivot tables. */
629 struct pivot_table *
630 pivot_table_create__ (struct pivot_value *title)
631 {
632   struct pivot_table *table = xzalloc (sizeof *table);
633   table->weight_format = (struct fmt_spec) { FMT_F, 40, 0 };
634   table->title = title;
635
636   /* Set default area styles. */
637 #define STYLE(BOLD, H, V, L, R, T, B) {                         \
638     .cell_style = {                                             \
639       .halign = TABLE_HALIGN_##H,                               \
640       .valign = TABLE_VALIGN_##V,                               \
641       .margin = { [TABLE_HORZ][0] = L, [TABLE_HORZ][1] = R,     \
642                   [TABLE_VERT][0] = T, [TABLE_VERT][1] = B },   \
643     },                                                          \
644       .font_style = {                                           \
645       .bold = BOLD,                                             \
646       .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK},  \
647       .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE},  \
648     },                                                          \
649          }
650   static const struct area_style default_area_styles[PIVOT_N_AREAS] = {
651     [PIVOT_AREA_TITLE]         = STYLE( true, CENTER, CENTER,  8,11,1,8),
652     [PIVOT_AREA_CAPTION]       = STYLE(false, LEFT,   TOP,     8,11,1,1),
653     [PIVOT_AREA_FOOTER]        = STYLE(false, LEFT,   TOP,    11, 8,2,3),
654     [PIVOT_AREA_CORNER]        = STYLE(false, LEFT,   BOTTOM,  8,11,1,1),
655     [PIVOT_AREA_COLUMN_LABELS] = STYLE(false, CENTER, BOTTOM,  8,11,1,3),
656     [PIVOT_AREA_ROW_LABELS]    = STYLE(false, LEFT,   TOP,     8,11,1,3),
657     [PIVOT_AREA_DATA]          = STYLE(false, MIXED,  TOP,     8,11,1,1),
658     [PIVOT_AREA_LAYERS]        = STYLE(false, LEFT,   BOTTOM,  8,11,1,3),
659     };
660 #undef STYLE
661   for (size_t i = 0; i < PIVOT_N_AREAS; i++)
662     table->areas[i] = default_area_styles[i];
663
664   /* Set default border styles. */
665   static const enum table_stroke default_strokes[PIVOT_N_BORDERS] = {
666     [PIVOT_BORDER_TITLE]        = TABLE_STROKE_NONE,
667     [PIVOT_BORDER_OUTER_LEFT]   = TABLE_STROKE_NONE,
668     [PIVOT_BORDER_OUTER_TOP]    = TABLE_STROKE_NONE,
669     [PIVOT_BORDER_OUTER_RIGHT]  = TABLE_STROKE_NONE,
670     [PIVOT_BORDER_OUTER_BOTTOM] = TABLE_STROKE_NONE,
671     [PIVOT_BORDER_INNER_LEFT]   = TABLE_STROKE_THICK,
672     [PIVOT_BORDER_INNER_TOP]    = TABLE_STROKE_THICK,
673     [PIVOT_BORDER_INNER_RIGHT]  = TABLE_STROKE_THICK,
674     [PIVOT_BORDER_INNER_BOTTOM] = TABLE_STROKE_THICK,
675     [PIVOT_BORDER_DATA_LEFT]    = TABLE_STROKE_THICK,
676     [PIVOT_BORDER_DATA_TOP]     = TABLE_STROKE_THICK,
677     [PIVOT_BORDER_DIM_ROW_HORZ] = TABLE_STROKE_SOLID,
678     [PIVOT_BORDER_DIM_ROW_VERT] = TABLE_STROKE_NONE,
679     [PIVOT_BORDER_DIM_COL_HORZ] = TABLE_STROKE_SOLID,
680     [PIVOT_BORDER_DIM_COL_VERT] = TABLE_STROKE_SOLID,
681     [PIVOT_BORDER_CAT_ROW_HORZ] = TABLE_STROKE_NONE,
682     [PIVOT_BORDER_CAT_ROW_VERT] = TABLE_STROKE_NONE,
683     [PIVOT_BORDER_CAT_COL_HORZ] = TABLE_STROKE_SOLID,
684     [PIVOT_BORDER_CAT_COL_VERT] = TABLE_STROKE_SOLID,
685   };
686   for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
687     table->borders[i] = (struct table_border_style) {
688       .stroke = default_strokes[i],
689       .color = CELL_COLOR_BLACK,
690     };
691
692   table->row_labels_in_corner = true;
693   hmap_init (&table->cells);
694
695   return table;
696 }
697
698 /* Creates and returns a new pivot table with the given TITLE and a single cell
699    with the given CONTENT. */
700 struct pivot_table *
701 pivot_table_create_for_text (struct pivot_value *title,
702                              struct pivot_value *content)
703 {
704   struct pivot_table *table = pivot_table_create__ (title);
705
706   struct pivot_dimension *d = pivot_dimension_create (
707     table, PIVOT_AXIS_ROW, N_("Error"));
708   d->hide_all_labels = true;
709   pivot_category_create_leaf (d->root, pivot_value_new_text ("null"));
710
711   pivot_table_put1 (table, 0, content);
712
713   return table;
714 }
715
716 /* Destroys TABLE and frees everything it points to. */
717 void
718 pivot_table_destroy (struct pivot_table *table)
719 {
720   if (!table)
721     return;
722
723   free (table->current_layer);
724   free (table->table_look);
725
726   for (int i = 0; i < TABLE_N_AXES; i++)
727     pivot_table_sizing_uninit (&table->sizing[i]);
728
729   free (table->continuation);
730
731   for (int i = 0; i < sizeof table->ccs / sizeof *table->ccs; i++)
732     free (table->ccs[i]);
733
734   free (table->command_local);
735   free (table->command_c);
736   free (table->language);
737   free (table->locale);
738
739   free (table->dataset);
740   free (table->datafile);
741
742   for (size_t i = 0; i < table->n_footnotes; i++)
743     pivot_footnote_destroy (table->footnotes[i]);
744   free (table->footnotes);
745
746   pivot_value_destroy (table->title);
747   pivot_value_destroy (table->subtype);
748   pivot_value_destroy (table->corner_text);
749   pivot_value_destroy (table->caption);
750
751   for (size_t i = 0; i < PIVOT_N_AREAS; i++)
752     area_style_uninit (&table->areas[i]);
753
754   for (size_t i = 0; i < table->n_dimensions; i++)
755     pivot_dimension_destroy (table->dimensions[i]);
756   free (table->dimensions);
757
758   for (size_t i = 0; i < PIVOT_N_AXES; i++)
759     free (table->axes[i].dimensions);
760
761   struct pivot_cell *cell, *next_cell;
762   HMAP_FOR_EACH_SAFE (cell, next_cell, struct pivot_cell, hmap_node,
763                       &table->cells)
764     {
765       hmap_delete (&table->cells, &cell->hmap_node);
766       pivot_value_destroy (cell->value);
767       free (cell);
768     }
769   hmap_destroy (&table->cells);
770
771   free (table);
772 }
773
774 /* Sets the format used for PIVOT_RC_COUNT cells to the one used for variable
775    WV, which should be the weight variable for the dictionary whose data or
776    statistics are being put into TABLE.
777
778    This has no effect if WV is NULL. */
779 void
780 pivot_table_set_weight_var (struct pivot_table *table,
781                             const struct variable *wv)
782 {
783   if (wv)
784     pivot_table_set_weight_format (table, var_get_print_format (wv));
785 }
786
787 /* Sets the format used for PIVOT_RC_COUNT cells to WFMT, which should be the
788    format for the dictionary whose data or statistics are being put into TABLE.
789
790    This has no effect if WFMT is NULL. */
791 void
792 pivot_table_set_weight_format (struct pivot_table *table,
793                                const struct fmt_spec *wfmt)
794 {
795   if (wfmt)
796     table->weight_format = *wfmt;
797 }
798
799 /* Returns true if TABLE has no cells, false otherwise. */
800 bool
801 pivot_table_is_empty (const struct pivot_table *table)
802 {
803   return hmap_is_empty (&table->cells);
804 }
805
806 static unsigned int
807 pivot_cell_hash_indexes (const size_t *indexes, size_t n_idx)
808 {
809   return hash_bytes (indexes, n_idx * sizeof *indexes, 0);
810 }
811
812 static bool
813 equal_indexes (const size_t *a, const unsigned int *b, size_t n)
814 {
815   for (size_t i = 0; i < n; i++)
816     if (a[i] != b[i])
817       return false;
818
819   return true;
820 }
821
822 static struct pivot_cell *
823 pivot_table_lookup_cell__ (const struct pivot_table *table,
824                             const size_t *dindexes, unsigned int hash)
825 {
826   struct pivot_cell *cell;
827   HMAP_FOR_EACH_WITH_HASH (cell, struct pivot_cell, hmap_node, hash,
828                            &table->cells)
829     if (equal_indexes (dindexes, cell->idx, table->n_dimensions))
830       return cell;
831   return false;
832 }
833
834 static struct pivot_cell *
835 pivot_cell_allocate (size_t n_idx)
836 {
837   struct pivot_cell *cell UNUSED;
838   return xmalloc (sizeof *cell + n_idx * sizeof *cell->idx);
839 }
840
841 static struct pivot_cell *
842 pivot_table_insert_cell (struct pivot_table *table, const size_t *dindexes)
843 {
844   unsigned int hash = pivot_cell_hash_indexes (dindexes, table->n_dimensions);
845   struct pivot_cell *cell = pivot_table_lookup_cell__ (table, dindexes, hash);
846   if (!cell)
847     {
848       cell = pivot_cell_allocate (table->n_dimensions);
849       for (size_t i = 0; i < table->n_dimensions; i++)
850         cell->idx[i] = dindexes[i];
851       cell->value = NULL;
852       hmap_insert (&table->cells, &cell->hmap_node, hash);
853     }
854   return cell;
855 }
856
857 /* Puts VALUE in the cell in TABLE whose indexes are given by the N indexes in
858    DINDEXES.  N must be the number of dimensions in TABLE.  Takes ownership of
859    VALUE.
860
861    If VALUE is a numeric value without a specified format, this function checks
862    each of the categories designated by DINDEXES[] and takes the format from
863    the first category with a result class.  If none has a result class, uses
864    the overall default numeric format. */
865 void
866 pivot_table_put (struct pivot_table *table, const size_t *dindexes, size_t n,
867                  struct pivot_value *value)
868 {
869   assert (n == table->n_dimensions);
870
871   if (value->type == PIVOT_VALUE_NUMERIC && !value->numeric.format.w)
872     {
873       for (size_t i = 0; i < table->n_dimensions; i++)
874         {
875           const struct pivot_dimension *d = table->dimensions[i];
876           if (dindexes[i] < d->n_leaves)
877             {
878               const struct pivot_category *c = d->data_leaves[dindexes[i]];
879               if (c->format.w)
880                 {
881                   value->numeric.format = c->format;
882                   goto done;
883                 }
884             }
885         }
886       value->numeric.format = *settings_get_format ();
887
888     done:;
889     }
890
891   struct pivot_cell *cell = pivot_table_insert_cell (table, dindexes);
892   pivot_value_destroy (cell->value);
893   cell->value = value;
894 }
895
896 /* Puts VALUE in the cell in TABLE with index IDX1.  TABLE must have 1
897    dimension.  Takes ownership of VALUE.  */
898 void
899 pivot_table_put1 (struct pivot_table *table, size_t idx1,
900                   struct pivot_value *value)
901 {
902   size_t dindexes[] = { idx1 };
903   pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
904 }
905
906 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2).  TABLE must have 2
907    dimensions.  Takes ownership of VALUE.  */
908 void
909 pivot_table_put2 (struct pivot_table *table, size_t idx1, size_t idx2,
910                   struct pivot_value *value)
911 {
912   size_t dindexes[] = { idx1, idx2 };
913   pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
914 }
915
916 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2, IDX3).  TABLE must
917    have 3 dimensions.  Takes ownership of VALUE.  */
918 void
919 pivot_table_put3 (struct pivot_table *table, size_t idx1, size_t idx2,
920                   size_t idx3, struct pivot_value *value)
921 {
922   size_t dindexes[] = { idx1, idx2, idx3 };
923   pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
924 }
925
926 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2, IDX3, IDX4).  TABLE
927    must have 4 dimensions.  Takes ownership of VALUE.  */
928 void
929 pivot_table_put4 (struct pivot_table *table, size_t idx1, size_t idx2,
930                   size_t idx3, size_t idx4, struct pivot_value *value)
931 {
932   size_t dindexes[] = { idx1, idx2, idx3, idx4 };
933   pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
934 }
935
936 /* Creates and returns a new footnote in TABLE with the given CONTENT and an
937    automatically assigned marker.
938
939    The footnote will only appear in output if it is referenced.  Use
940    pivot_value_add_footnote() to add a reference to the footnote. */
941 struct pivot_footnote *
942 pivot_table_create_footnote (struct pivot_table *table,
943                              struct pivot_value *content)
944 {
945   return pivot_table_create_footnote__ (table, table->n_footnotes,
946                                         NULL, content);
947 }
948
949 static struct pivot_value *
950 pivot_make_default_footnote_marker (int idx, bool show_numeric_markers)
951 {
952   char text[INT_BUFSIZE_BOUND (size_t)];
953   if (show_numeric_markers)
954     snprintf (text, sizeof text, "%d", idx + 1);
955   else
956     str_format_26adic (idx + 1, false, text, sizeof text);
957   return pivot_value_new_user_text (text, -1);
958 }
959
960 /* Creates or modifies a footnote in TABLE with 0-based number IDX.  If MARKER
961    is nonnull, sets the footnote's marker; if CONTENT is nonnull, sets the
962    footnote's content. */
963 struct pivot_footnote *
964 pivot_table_create_footnote__ (struct pivot_table *table, size_t idx,
965                                struct pivot_value *marker,
966                                struct pivot_value *content)
967 {
968   if (idx >= table->n_footnotes)
969     {
970       while (idx >= table->allocated_footnotes)
971         table->footnotes = x2nrealloc (table->footnotes,
972                                        &table->allocated_footnotes,
973                                        sizeof *table->footnotes);
974       while (idx >= table->n_footnotes)
975         {
976           struct pivot_footnote *f = xmalloc (sizeof *f);
977           f->idx = table->n_footnotes;
978           f->marker = pivot_make_default_footnote_marker (
979             f->idx, table->show_numeric_markers);
980           f->content = NULL;
981
982           table->footnotes[table->n_footnotes++] = f;
983         }
984     }
985
986   struct pivot_footnote *f = table->footnotes[idx];
987   if (marker)
988     {
989       pivot_value_destroy (f->marker);
990       f->marker = marker;
991     }
992   if (content)
993     {
994       pivot_value_destroy (f->content);
995       f->content = content;
996     }
997   return f;
998 }
999
1000 /* Frees the data owned by F. */
1001 void
1002 pivot_footnote_destroy (struct pivot_footnote *f)
1003 {
1004   if (f)
1005     {
1006       pivot_value_destroy (f->content);
1007       pivot_value_destroy (f->marker);
1008       free (f);
1009     }
1010 }
1011
1012 /* Converts per-axis presentation-order indexes, given in PINDEXES, into data
1013    indexes for each dimension in TABLE in DINDEXES[]. */
1014 void
1015 pivot_table_convert_indexes_ptod (const struct pivot_table *table,
1016                                   const size_t *pindexes[PIVOT_N_AXES],
1017                                   size_t dindexes[/* table->n_dimensions */])
1018 {
1019   for (size_t i = 0; i < PIVOT_N_AXES; i++)
1020     {
1021       const struct pivot_axis *axis = &table->axes[i];
1022
1023       for (size_t j = 0; j < axis->n_dimensions; j++)
1024         {
1025           const struct pivot_dimension *d = axis->dimensions[j];
1026           dindexes[d->top_index]
1027             = d->presentation_leaves[pindexes[i][j]]->data_index;
1028         }
1029     }
1030 }
1031
1032 size_t *
1033 pivot_table_enumerate_axis (const struct pivot_table *table,
1034                             enum pivot_axis_type axis_type,
1035                             const size_t *layer_indexes, bool omit_empty,
1036                             size_t *n)
1037 {
1038   const struct pivot_axis *axis = &table->axes[axis_type];
1039   if (!axis->n_dimensions)
1040     {
1041       size_t *enumeration = xnmalloc (2, sizeof *enumeration);
1042       enumeration[0] = 0;
1043       enumeration[1] = SIZE_MAX;
1044       if (n)
1045         *n = 1;
1046       return enumeration;
1047     }
1048   else if (!axis->extent)
1049     {
1050       size_t *enumeration = xmalloc (sizeof *enumeration);
1051       *enumeration = SIZE_MAX;
1052       if (n)
1053         *n = 0;
1054       return enumeration;
1055     }
1056
1057   size_t *enumeration = xnmalloc (xsum (xtimes (axis->extent,
1058                                                 axis->n_dimensions), 1),
1059                                   sizeof *enumeration);
1060   size_t *p = enumeration;
1061   size_t *dindexes = xcalloc (table->n_dimensions, sizeof *dindexes);
1062
1063   size_t *axis_indexes;
1064   PIVOT_AXIS_FOR_EACH (axis_indexes, axis)
1065     {
1066       if (omit_empty)
1067         {
1068           enum pivot_axis_type axis2_type
1069             = pivot_axis_type_transpose (axis_type);
1070
1071           size_t *axis2_indexes;
1072           PIVOT_AXIS_FOR_EACH (axis2_indexes, &table->axes[axis2_type])
1073             {
1074               const size_t *pindexes[PIVOT_N_AXES];
1075               pindexes[PIVOT_AXIS_LAYER] = layer_indexes;
1076               pindexes[axis_type] = axis_indexes;
1077               pindexes[axis2_type] = axis2_indexes;
1078               pivot_table_convert_indexes_ptod (table, pindexes, dindexes);
1079               if (pivot_table_get (table, dindexes))
1080                 goto found;
1081             }
1082           continue;
1083
1084         found:
1085           free (axis2_indexes);
1086         }
1087
1088       memcpy (p, axis_indexes, axis->n_dimensions * sizeof *p);
1089       p += axis->n_dimensions;
1090     }
1091   *p = SIZE_MAX;
1092   if (n)
1093     *n = (p - enumeration) / axis->n_dimensions;
1094
1095   free (dindexes);
1096   return enumeration;
1097 }
1098
1099 static const struct pivot_cell *
1100 pivot_table_lookup_cell (const struct pivot_table *table,
1101                           const size_t *dindexes)
1102 {
1103   unsigned int hash = pivot_cell_hash_indexes (dindexes, table->n_dimensions);
1104   return pivot_table_lookup_cell__ (table, dindexes, hash);
1105 }
1106
1107 const struct pivot_value *
1108 pivot_table_get (const struct pivot_table *table, const size_t *dindexes)
1109 {
1110   const struct pivot_cell *cell = pivot_table_lookup_cell (table, dindexes);
1111   return cell ? cell->value : NULL;
1112 }
1113
1114 struct pivot_value *
1115 pivot_table_get_rw (struct pivot_table *table, const size_t *dindexes)
1116 {
1117   struct pivot_cell *cell = pivot_table_insert_cell (table, dindexes);
1118   if (!cell->value)
1119     cell->value = pivot_value_new_user_text ("", -1);
1120   return cell->value;
1121 }
1122
1123 static void
1124 distribute_extra_depth (struct pivot_category *category, size_t extra_depth)
1125 {
1126   if (pivot_category_is_group (category) && category->n_subs)
1127     for (size_t i = 0; i < category->n_subs; i++)
1128       distribute_extra_depth (category->subs[i], extra_depth);
1129   else
1130     category->extra_depth += extra_depth;
1131 }
1132
1133 static void
1134 pivot_category_assign_label_depth (struct pivot_category *category,
1135                                    bool dimension_labels_in_corner)
1136 {
1137   category->extra_depth = 0;
1138
1139   if (pivot_category_is_group (category))
1140     {
1141       size_t depth = 0;
1142       for (size_t i = 0; i < category->n_subs; i++)
1143         {
1144           pivot_category_assign_label_depth (category->subs[i], false);
1145           depth = MAX (depth, category->subs[i]->label_depth);
1146         }
1147
1148       for (size_t i = 0; i < category->n_subs; i++)
1149         {
1150           struct pivot_category *sub = category->subs[i];
1151
1152           size_t extra_depth = depth - sub->label_depth;
1153           if (extra_depth)
1154             distribute_extra_depth (sub, extra_depth);
1155
1156           sub->label_depth = depth;
1157         }
1158
1159       category->show_label_in_corner = (category->show_label
1160                                         && dimension_labels_in_corner);
1161       category->label_depth
1162         = (category->show_label && !category->show_label_in_corner
1163            ? depth + 1 : depth);
1164     }
1165   else
1166     category->label_depth = 1;
1167 }
1168
1169 static bool
1170 pivot_axis_assign_label_depth (struct pivot_table *table,
1171                              enum pivot_axis_type axis_type,
1172                              bool dimension_labels_in_corner)
1173 {
1174   struct pivot_axis *axis = &table->axes[axis_type];
1175   bool any_label_shown_in_corner = false;
1176   axis->label_depth = 0;
1177   axis->extent = 1;
1178   for (size_t i = 0; i < axis->n_dimensions; i++)
1179     {
1180       struct pivot_dimension *d = axis->dimensions[i];
1181       pivot_category_assign_label_depth (d->root, dimension_labels_in_corner);
1182       d->label_depth = d->hide_all_labels ? 0 : d->root->label_depth;
1183       axis->label_depth += d->label_depth;
1184       axis->extent *= d->n_leaves;
1185
1186       if (d->root->show_label_in_corner)
1187         any_label_shown_in_corner = true;
1188     }
1189   return any_label_shown_in_corner;
1190 }
1191
1192 void
1193 pivot_table_assign_label_depth (struct pivot_table *table)
1194 {
1195   pivot_axis_assign_label_depth (table, PIVOT_AXIS_COLUMN, false);
1196   if (pivot_axis_assign_label_depth (
1197         table, PIVOT_AXIS_ROW, (table->row_labels_in_corner
1198                                 && !table->corner_text))
1199       && table->axes[PIVOT_AXIS_COLUMN].label_depth == 0)
1200     table->axes[PIVOT_AXIS_COLUMN].label_depth = 1;
1201   pivot_axis_assign_label_depth (table, PIVOT_AXIS_LAYER, false);
1202 }
1203
1204 void
1205 pivot_table_submit (struct pivot_table *pt)
1206 {
1207   pivot_table_assign_label_depth (CONST_CAST (struct pivot_table *, pt));
1208   table_item_submit (table_item_create (pt));
1209 \f
1210   static void
1211 indent (int indentation)
1212 {
1213   for (int i = 0; i < indentation * 2; i++)
1214     putchar (' ');
1215 }
1216
1217 static void
1218 pivot_value_dump (const struct pivot_value *value)
1219 {
1220   char *s = pivot_value_to_string (value, SETTINGS_VALUE_SHOW_DEFAULT,
1221                                    SETTINGS_VALUE_SHOW_DEFAULT);
1222   fputs (s, stdout);
1223   free (s);
1224 }
1225
1226 static void
1227 pivot_table_dump_value (const struct pivot_value *value, const char *name,
1228                       int indentation)
1229 {
1230   if (value)
1231     {
1232       indent (indentation);
1233       printf ("%s: ", name);
1234       pivot_value_dump (value);
1235       putchar ('\n');
1236     }
1237 }
1238
1239 static void
1240 pivot_table_dump_string (const char *string, const char *name, int indentation)
1241 {
1242   if (string)
1243     {
1244       indent (indentation);
1245       printf ("%s: %s\n", name, string);
1246     }
1247 }
1248
1249 static void
1250 pivot_category_dump (const struct pivot_category *c, int indentation)
1251 {
1252   indent (indentation);
1253   printf ("%s \"", pivot_category_is_leaf (c) ? "leaf" : "group");
1254   pivot_value_dump (c->name);
1255   printf ("\" ");
1256
1257   if (pivot_category_is_leaf (c))
1258     printf ("data_index=%zu\n", c->data_index);
1259   else
1260     {
1261       printf (" (label %s)", c->show_label ? "shown" : "hidden");
1262       printf ("\n");
1263
1264       for (size_t i = 0; i < c->n_subs; i++)
1265         pivot_category_dump (c->subs[i], indentation + 1);
1266     }
1267 }
1268
1269 void
1270 pivot_dimension_dump (const struct pivot_dimension *d, int indentation)
1271 {
1272   indent (indentation);
1273   printf ("%s dimension %zu (where 0=innermost), label_depth=%d:\n",
1274           pivot_axis_type_to_string (d->axis_type), d->level, d->label_depth);
1275
1276   pivot_category_dump (d->root, indentation + 1);
1277 }
1278
1279 static void
1280 area_style_dump (enum pivot_area area, const struct area_style *a,
1281                  int indentation)
1282 {
1283   indent (indentation);
1284   printf ("%s: ", pivot_area_to_string (area));
1285   font_style_dump (&a->font_style);
1286   putchar (' ');
1287   cell_style_dump (&a->cell_style);
1288   putchar ('\n');
1289 }
1290
1291 static void
1292 table_border_style_dump (enum pivot_border border,
1293                          const struct table_border_style *b, int indentation)
1294 {
1295   indent (indentation);
1296   printf ("%s: %s ", pivot_border_to_string (border),
1297           table_stroke_to_string (b->stroke));
1298   cell_color_dump (&b->color);
1299   putchar ('\n');
1300 }
1301
1302 static char ***
1303 compose_headings (const struct pivot_axis *axis,
1304                   const size_t *column_enumeration,
1305                   enum settings_value_show show_values,
1306                   enum settings_value_show show_variables)
1307 {
1308   if (!axis->n_dimensions || !axis->extent || !axis->label_depth)
1309     return NULL;
1310
1311   char ***headings = xnmalloc (axis->label_depth, sizeof *headings);
1312   for (size_t i = 0; i < axis->label_depth; i++)
1313     headings[i] = xcalloc (axis->extent, sizeof **headings);
1314
1315   const size_t *indexes;
1316   size_t column = 0;
1317   PIVOT_ENUMERATION_FOR_EACH (indexes, column_enumeration, axis)
1318     {
1319       int row = axis->label_depth - 1;
1320       for (int dim_index = 0; dim_index < axis->n_dimensions; dim_index++)
1321         {
1322           const struct pivot_dimension *d = axis->dimensions[dim_index];
1323           if (d->hide_all_labels)
1324             continue;
1325           for (const struct pivot_category *c
1326                  = d->presentation_leaves[indexes[dim_index]];
1327                c;
1328                c = c->parent)
1329             {
1330               if (pivot_category_is_leaf (c) || (c->show_label
1331                                                  && !c->show_label_in_corner))
1332                 {
1333                   headings[row][column] = pivot_value_to_string (
1334                     c->name, show_values, show_variables);
1335                   if (!*headings[row][column])
1336                     headings[row][column] = xstrdup ("<blank>");
1337                   row--;
1338                 }
1339             }
1340         }
1341       column++;
1342     }
1343
1344   return headings;
1345 }
1346
1347 void
1348 pivot_table_dump (const struct pivot_table *table, int indentation)
1349 {
1350   if (!table)
1351     return;
1352
1353   int old_decimal = settings_get_decimal_char (FMT_COMMA);
1354   if (table->decimal == '.' || table->decimal == ',')
1355     settings_set_decimal_char (table->decimal);
1356
1357   pivot_table_dump_value (table->title, "title", indentation);
1358   pivot_table_dump_string (table->command_c, "command", indentation);
1359   pivot_table_dump_string (table->dataset, "dataset", indentation);
1360   pivot_table_dump_string (table->datafile, "datafile", indentation);
1361   pivot_table_dump_string (table->notes, "notes", indentation);
1362   pivot_table_dump_string (table->table_look, "table-look", indentation);
1363   if (table->date)
1364     {
1365       indent (indentation);
1366       printf ("date: %s", ctime (&table->date)); /* XXX thread unsafe */
1367     }
1368
1369   indent (indentation);
1370   printf ("areas:\n");
1371   for (enum pivot_area area = 0; area < PIVOT_N_AREAS; area++)
1372     area_style_dump (area, &table->areas[area], indentation + 1);
1373
1374   indent (indentation);
1375   printf ("borders:\n");
1376   for (enum pivot_border border = 0; border < PIVOT_N_BORDERS; border++)
1377     table_border_style_dump (border, &table->borders[border], indentation + 1);
1378
1379   for (size_t i = 0; i < table->n_dimensions; i++)
1380     pivot_dimension_dump (table->dimensions[i], indentation);
1381
1382   /* Presentation and data indexes. */
1383   size_t *dindexes = xcalloc (table->n_dimensions, sizeof *dindexes);
1384
1385   const struct pivot_axis *layer_axis = &table->axes[PIVOT_AXIS_LAYER];
1386   if (layer_axis->n_dimensions)
1387     {
1388       indent (indentation);
1389       printf ("current layer:");
1390
1391       for (size_t i = 0; i < layer_axis->n_dimensions; i++)
1392         {
1393           const struct pivot_dimension *d = layer_axis->dimensions[i];
1394           char *name = pivot_value_to_string (d->root->name,
1395                                               table->show_values,
1396                                               table->show_variables);
1397           char *value = pivot_value_to_string (
1398             d->data_leaves[table->current_layer[i]]->name,
1399             table->show_values, table->show_variables);
1400           printf (" %s=%s", name, value);
1401           free (value);
1402           free (name);
1403         }
1404
1405       putchar ('\n');
1406     }
1407
1408   size_t *layer_indexes;
1409   size_t layer_iteration = 0;
1410   PIVOT_AXIS_FOR_EACH (layer_indexes, &table->axes[PIVOT_AXIS_LAYER])
1411     {
1412       indent (indentation);
1413       printf ("layer %zu:", layer_iteration++);
1414
1415       const struct pivot_axis *layer_axis = &table->axes[PIVOT_AXIS_LAYER];
1416       for (size_t i = 0; i < layer_axis->n_dimensions; i++)
1417         {
1418           const struct pivot_dimension *d = layer_axis->dimensions[i];
1419
1420           fputs (i == 0 ? " " : ", ", stdout);
1421           pivot_value_dump (d->root->name);
1422           fputs (" =", stdout);
1423
1424           struct pivot_value **names = xnmalloc (layer_axis->label_depth,
1425                                                sizeof *names);
1426           size_t n_names = 0;
1427           for (const struct pivot_category *c
1428                  = d->presentation_leaves[layer_indexes[i]];
1429                c;
1430                c = c->parent)
1431             {
1432               if (pivot_category_is_leaf (c) || c->show_label)
1433                 names[n_names++] = c->name;
1434             }
1435
1436           for (size_t i = n_names; i-- > 0; )
1437             {
1438               putchar (' ');
1439               pivot_value_dump (names[i]);
1440             }
1441           free (names);
1442         }
1443       putchar ('\n');
1444
1445       size_t *column_enumeration = pivot_table_enumerate_axis (
1446         table, PIVOT_AXIS_COLUMN, layer_indexes, table->omit_empty, NULL);
1447       size_t *row_enumeration = pivot_table_enumerate_axis (
1448         table, PIVOT_AXIS_ROW, layer_indexes, table->omit_empty, NULL);
1449
1450       char ***column_headings = compose_headings (
1451         &table->axes[PIVOT_AXIS_COLUMN], column_enumeration,
1452         table->show_values, table->show_variables);
1453       for (size_t y = 0; y < table->axes[PIVOT_AXIS_COLUMN].label_depth; y++)
1454         {
1455           indent (indentation + 1);
1456           for (size_t x = 0; x < table->axes[PIVOT_AXIS_COLUMN].extent; x++)
1457             {
1458               if (x)
1459                 fputs ("; ", stdout);
1460               if (column_headings[y][x])
1461                 fputs (column_headings[y][x], stdout);
1462             }
1463           putchar ('\n');
1464         }
1465
1466       indent (indentation + 1);
1467       printf ("-----------------------------------------------\n");
1468
1469       char ***row_headings = compose_headings (
1470         &table->axes[PIVOT_AXIS_ROW], row_enumeration,
1471         table->show_values, table->show_variables);
1472
1473       size_t x = 0;
1474       const size_t *pindexes[PIVOT_N_AXES]
1475         = { [PIVOT_AXIS_LAYER] = layer_indexes };
1476       PIVOT_ENUMERATION_FOR_EACH (pindexes[PIVOT_AXIS_ROW], row_enumeration,
1477                                   &table->axes[PIVOT_AXIS_ROW])
1478         {
1479           indent (indentation + 1);
1480
1481           size_t i = 0;
1482           for (size_t y = 0; y < table->axes[PIVOT_AXIS_ROW].label_depth; y++)
1483             {
1484               if (i++)
1485                 fputs ("; ", stdout);
1486               if (row_headings[y][x])
1487                 fputs (row_headings[y][x], stdout);
1488             }
1489
1490           printf (" | ");
1491
1492           i = 0;
1493           PIVOT_ENUMERATION_FOR_EACH (pindexes[PIVOT_AXIS_COLUMN],
1494                                       column_enumeration,
1495                                       &table->axes[PIVOT_AXIS_COLUMN])
1496             {
1497               if (i++)
1498                 printf ("; ");
1499
1500               pivot_table_convert_indexes_ptod (table, pindexes, dindexes);
1501               const struct pivot_value *value = pivot_table_get (
1502                 table, dindexes);
1503               if (value)
1504                 pivot_value_dump (value);
1505             }
1506           printf ("\n");
1507
1508           x++;
1509         }
1510
1511       free (column_enumeration);
1512       free (row_enumeration);
1513     }
1514
1515   pivot_table_dump_value (table->caption, "caption", indentation);
1516
1517   for (size_t i = 0; i < table->n_footnotes; i++)
1518     {
1519       const struct pivot_footnote *f = table->footnotes[i];
1520       indent (indentation);
1521       putchar ('[');
1522       if (f->marker)
1523         pivot_value_dump (f->marker);
1524       else
1525         printf ("%zu", f->idx);
1526       putchar (']');
1527       pivot_value_dump (f->content);
1528       putchar ('\n');
1529     }
1530
1531   settings_set_decimal_char (old_decimal);
1532 }
1533 \f
1534 static const char *
1535 consume_int (const char *p, size_t *n)
1536 {
1537   *n = 0;
1538   while (c_isdigit (*p))
1539     *n = *n * 10 + (*p++ - '0');
1540   return p;
1541 }
1542
1543 static size_t
1544 pivot_format_inner_template (struct string *out, const char *template,
1545                              char escape,
1546                              struct pivot_value **values, size_t n_values,
1547                              enum settings_value_show show_values,
1548                              enum settings_value_show show_variables)
1549 {
1550   size_t args_consumed = 0;
1551   while (*template && *template != ':')
1552     {
1553       if (*template == '\\' && template[1])
1554         {
1555           ds_put_byte (out, template[1] == 'n' ? '\n' : template[1]);
1556           template += 2;
1557         }
1558       else if (*template == escape)
1559         {
1560           size_t index;
1561           template = consume_int (template + 1, &index);
1562           if (index >= 1 && index <= n_values)
1563             {
1564               pivot_value_format (values[index - 1], show_values,
1565                                   show_variables, out);
1566               args_consumed = MAX (args_consumed, index);
1567             }
1568         }
1569       else
1570         ds_put_byte (out, *template++);
1571     }
1572   return args_consumed;
1573 }
1574
1575 static const char *
1576 pivot_extract_inner_template (const char *template, const char **p)
1577 {
1578   *p = template;
1579
1580   for (;;)
1581     {
1582       if (*template == '\\' && template[1] != '\0')
1583         template += 2;
1584       else if (*template == ':')
1585         return template + 1;
1586       else if (*template == '\0')
1587         return template;
1588       else
1589         template++;
1590     }
1591 }
1592
1593 static void
1594 pivot_format_template (struct string *out, const char *template,
1595                        const struct pivot_argument *args, size_t n_args,
1596                        enum settings_value_show show_values,
1597                        enum settings_value_show show_variables)
1598 {
1599   while (*template)
1600     {
1601       if (*template == '\\' && template[1] != '\0')
1602         {
1603           ds_put_byte (out, template[1] == 'n' ? '\n' : template[1]);
1604           template += 2;
1605         }
1606       else if (*template == '^')
1607         {
1608           size_t index;
1609           template = consume_int (template + 1, &index);
1610           if (index >= 1 && index <= n_args && args[index - 1].n > 0)
1611             pivot_value_format (args[index - 1].values[0],
1612                                 show_values, show_variables, out);
1613         }
1614       else if (*template == '[')
1615         {
1616           const char *tmpl[2];
1617           template = pivot_extract_inner_template (template + 1, &tmpl[0]);
1618           template = pivot_extract_inner_template (template, &tmpl[1]);
1619           template += *template == ']';
1620
1621           size_t index;
1622           template = consume_int (template, &index);
1623           if (index < 1 || index > n_args)
1624             continue;
1625
1626           const struct pivot_argument *arg = &args[index - 1];
1627           size_t left = arg->n;
1628           while (left)
1629             {
1630               struct pivot_value **values = arg->values + (arg->n - left);
1631               int tmpl_idx = left == arg->n && *tmpl[0] != ':' ? 0 : 1;
1632               char escape = "%^"[tmpl_idx];
1633               size_t used = pivot_format_inner_template (
1634                 out, tmpl[tmpl_idx], escape, values, left,
1635                 show_values, show_variables);
1636               if (!used || used > left)
1637                 break;
1638               left -= used;
1639             }
1640         }
1641       else
1642         ds_put_byte (out, *template++);
1643     }
1644 }
1645
1646 static enum settings_value_show
1647 interpret_show (enum settings_value_show global_show,
1648                 enum settings_value_show table_show,
1649                 enum settings_value_show value_show,
1650                 bool has_label)
1651 {
1652   return (!has_label ? SETTINGS_VALUE_SHOW_VALUE
1653           : value_show != SETTINGS_VALUE_SHOW_DEFAULT ? value_show
1654           : table_show != SETTINGS_VALUE_SHOW_DEFAULT ? table_show
1655           : global_show);
1656 }
1657
1658 /* Appends a text representation of the body of VALUE to OUT.  SHOW_VALUES and
1659    SHOW_VARIABLES control whether variable and value labels are included.
1660
1661    The "body" omits subscripts and superscripts and footnotes. */
1662 bool
1663 pivot_value_format_body (const struct pivot_value *value,
1664                          enum settings_value_show show_values,
1665                          enum settings_value_show show_variables,
1666                          struct string *out)
1667 {
1668   enum settings_value_show show;
1669   bool numeric = false;
1670
1671   switch (value->type)
1672     {
1673     case PIVOT_VALUE_NUMERIC:
1674       show = interpret_show (settings_get_show_values (),
1675                              show_values,
1676                              value->numeric.show,
1677                              value->numeric.value_label != NULL);
1678       if (show & SETTINGS_VALUE_SHOW_VALUE)
1679         {
1680           char *s = data_out (&(union value) { .f = value->numeric.x },
1681                               "UTF-8", &value->numeric.format);
1682           ds_put_cstr (out, s + strspn (s, " "));
1683           free (s);
1684         }
1685       if (show & SETTINGS_VALUE_SHOW_LABEL)
1686         {
1687           if (show & SETTINGS_VALUE_SHOW_VALUE)
1688             ds_put_byte (out, ' ');
1689           ds_put_cstr (out, value->numeric.value_label);
1690         }
1691       numeric = !(show & SETTINGS_VALUE_SHOW_LABEL);
1692       break;
1693
1694     case PIVOT_VALUE_STRING:
1695       show = interpret_show (settings_get_show_values (),
1696                              show_values,
1697                              value->string.show,
1698                              value->string.value_label != NULL);
1699       if (show & SETTINGS_VALUE_SHOW_VALUE)
1700         {
1701           if (value->string.hex)
1702             {
1703               for (const uint8_t *p = CHAR_CAST (uint8_t *, value->string.s);
1704                    *p; p++)
1705                 ds_put_format (out, "%02X", *p);
1706             }
1707           else
1708             ds_put_cstr (out, value->string.s);
1709         }
1710       if (show & SETTINGS_VALUE_SHOW_LABEL)
1711         {
1712           if (show & SETTINGS_VALUE_SHOW_VALUE)
1713             ds_put_byte (out, ' ');
1714           ds_put_cstr (out, value->string.value_label);
1715         }
1716       break;
1717
1718     case PIVOT_VALUE_VARIABLE:
1719       show = interpret_show (settings_get_show_variables (),
1720                              show_variables,
1721                              value->variable.show,
1722                              value->variable.var_label != NULL);
1723       if (show & SETTINGS_VALUE_SHOW_VALUE)
1724         ds_put_cstr (out, value->variable.var_name);
1725       if (show & SETTINGS_VALUE_SHOW_LABEL)
1726         {
1727           if (show & SETTINGS_VALUE_SHOW_VALUE)
1728             ds_put_byte (out, ' ');
1729           ds_put_cstr (out, value->variable.var_label);
1730         }
1731       break;
1732
1733     case PIVOT_VALUE_TEXT:
1734       ds_put_cstr (out, value->text.local);
1735       break;
1736
1737     case PIVOT_VALUE_TEMPLATE:
1738       pivot_format_template (out, value->template.s, value->template.args,
1739                              value->template.n_args, show_values,
1740                              show_variables);
1741       break;
1742     }
1743
1744   return numeric;
1745 }
1746
1747 /* Appends a text representation of VALUE to OUT.  SHOW_VALUES and
1748    SHOW_VARIABLES control whether variable and value labels are included.
1749
1750    Subscripts and superscripts and footnotes are included. */
1751 void
1752 pivot_value_format (const struct pivot_value *value,
1753                     enum settings_value_show show_values,
1754                     enum settings_value_show show_variables,
1755                     struct string *out)
1756 {
1757   pivot_value_format_body ( value, show_values, show_variables, out);
1758
1759   if (value->subscript)
1760     ds_put_format (out, "_%s", value->subscript);
1761
1762   if (value->superscript)
1763     ds_put_format (out, "^%s", value->superscript);
1764
1765   for (size_t i = 0; i < value->n_footnotes; i++)
1766     {
1767       ds_put_byte (out, '^');
1768       pivot_value_format (value->footnotes[i]->marker,
1769                           show_values, show_variables, out);
1770     }
1771 }
1772
1773 /* Returns a text representation of VALUE.  The caller must free the string,
1774    with free(). */
1775 char *
1776 pivot_value_to_string (const struct pivot_value *value,
1777                        enum settings_value_show show_values,
1778                        enum settings_value_show show_variables)
1779 {
1780   struct string s = DS_EMPTY_INITIALIZER;
1781   pivot_value_format (value, show_values, show_variables, &s);
1782   return ds_steal_cstr (&s);
1783 }
1784
1785 /* Frees the data owned by V. */
1786 void
1787 pivot_value_destroy (struct pivot_value *value)
1788 {
1789   if (value)
1790     {
1791       font_style_uninit (value->font_style);
1792       free (value->font_style);
1793       free (value->cell_style);
1794       /* Do not free the elements of footnotes because VALUE does not own
1795          them. */
1796       free (value->footnotes);
1797
1798       switch (value->type)
1799         {
1800         case PIVOT_VALUE_NUMERIC:
1801           free (value->numeric.var_name);
1802           free (value->numeric.value_label);
1803           break;
1804
1805         case PIVOT_VALUE_STRING:
1806           free (value->string.s);
1807           free (value->string.var_name);
1808           free (value->string.value_label);
1809           break;
1810
1811         case PIVOT_VALUE_VARIABLE:
1812           free (value->variable.var_name);
1813           free (value->variable.var_label);
1814           break;
1815
1816         case PIVOT_VALUE_TEXT:
1817           free (value->text.local);
1818           if (value->text.c != value->text.local)
1819             free (value->text.c);
1820           if (value->text.id != value->text.local
1821               && value->text.id != value->text.c)
1822             free (value->text.id);
1823           break;
1824
1825         case PIVOT_VALUE_TEMPLATE:
1826           free (value->template.s);
1827           for (size_t i = 0; i < value->template.n_args; i++)
1828             pivot_argument_uninit (&value->template.args[i]);
1829           free (value->template.args);
1830           break;
1831         }
1832       free (value);
1833     }
1834 }
1835
1836 /* Sets AREA to the style to use for VALUE, with defaults coming from
1837    DEFAULT_STYLE for the parts of the style that VALUE doesn't override. */
1838 void
1839 pivot_value_get_style (struct pivot_value *value,
1840                        const struct area_style *default_style,
1841                        struct area_style *area)
1842 {
1843   font_style_copy (&area->font_style, (value->font_style
1844                                        ? value->font_style
1845                                        : &default_style->font_style));
1846   area->cell_style = (value->cell_style
1847                       ? *value->cell_style
1848                       : default_style->cell_style);
1849 }
1850
1851 /* Copies AREA into VALUE's style. */
1852 void
1853 pivot_value_set_style (struct pivot_value *value,
1854                        const struct area_style *area)
1855 {
1856   if (value->font_style)
1857     font_style_uninit (value->font_style);
1858   else
1859     value->font_style = xmalloc (sizeof *value->font_style);
1860   font_style_copy (value->font_style, &area->font_style);
1861
1862   if (!value->cell_style)
1863     value->cell_style = xmalloc (sizeof *value->cell_style);
1864   *value->cell_style = area->cell_style;
1865 }
1866
1867 /* Frees the data owned by ARG (but not ARG itself). */
1868 void
1869 pivot_argument_uninit (struct pivot_argument *arg)
1870 {
1871   if (arg)
1872     {
1873       for (size_t i = 0; i < arg->n; i++)
1874         pivot_value_destroy (arg->values[i]);
1875       free (arg->values);
1876     }
1877 }
1878
1879 struct pivot_value *
1880 pivot_value_new_user_text_nocopy (char *text)
1881 {
1882   struct pivot_value *value = xmalloc (sizeof *value);
1883   *value = (struct pivot_value) {
1884     .type = PIVOT_VALUE_TEXT,
1885     .text = {
1886       .local = text,
1887       .c = text,
1888       .id = text,
1889       .user_provided = true,
1890     }
1891   };
1892   return value;
1893 }
1894
1895 struct pivot_value *
1896 pivot_value_new_user_text (const char *text, size_t length)
1897 {
1898   return pivot_value_new_user_text_nocopy (
1899     xmemdup0 (text, length != SIZE_MAX ? length : strlen (text)));
1900 }
1901
1902 /* TEXT should be a translatable string, but not actually translated yet,
1903    e.g. enclosed in N_(). */
1904 struct pivot_value *
1905 pivot_value_new_text (const char *text)
1906 {
1907   char *c = xstrdup (text);
1908   char *local = xstrdup (gettext (c));
1909
1910   struct pivot_value *value = xmalloc (sizeof *value);
1911   *value = (struct pivot_value) {
1912     .type = PIVOT_VALUE_TEXT,
1913     .text = {
1914       .local = local,
1915       .c = c,
1916       .id = c,
1917       .user_provided = false,
1918     }
1919   };
1920   return value;
1921 }
1922
1923 /* FORMAT should be a translatable string, but not actually translated yet,
1924    e.g. enclosed in N_(). */
1925 struct pivot_value * PRINTF_FORMAT (1, 2)
1926 pivot_value_new_text_format (const char *format, ...)
1927 {
1928   va_list args;
1929   va_start (args, format);
1930   char *c = xvasprintf (format, args);
1931   va_end (args);
1932
1933   va_start (args, format);
1934   char *local = xvasprintf (gettext (format), args);
1935   va_end (args);
1936
1937   struct pivot_value *value = xmalloc (sizeof *value);
1938   *value = (struct pivot_value) {
1939     .type = PIVOT_VALUE_TEXT,
1940     .text = {
1941       .local = local,
1942       .c = c,
1943       .id = xstrdup (c),
1944       .user_provided = false,
1945     }
1946   };
1947   return value;
1948 }
1949
1950 static char *
1951 xstrdup_if_nonempty (const char *s)
1952 {
1953   return s && s[0] ? xstrdup (s) : NULL;
1954 }
1955
1956 /* Returns a new pivot_value that represents X.
1957
1958    The format to use for X is unspecified.  Usually the easiest way to specify
1959    a format is through assigning a result class to one of the categories that
1960    the pivot_value will end up in.  If that is not suitable, then the caller
1961    can use pivot_value_set_rc() or assign directly to value->numeric.format. */
1962 struct pivot_value *
1963 pivot_value_new_number (double x)
1964 {
1965   struct pivot_value *value = xmalloc (sizeof *value);
1966   *value = (struct pivot_value) {
1967     .type = PIVOT_VALUE_NUMERIC,
1968     .numeric = { .x = x, },
1969   };
1970   return value;
1971 }
1972
1973 /* Returns a new pivot_value that represents X, formatted as an integer. */
1974 struct pivot_value *
1975 pivot_value_new_integer (double x)
1976 {
1977   struct pivot_value *value = pivot_value_new_number (x);
1978   value->numeric.format = (struct fmt_spec) { FMT_F, 40, 0 };
1979   return value;
1980 }
1981
1982 /* Returns a new pivot_value that represents VALUE, formatted as for
1983    VARIABLE. */
1984 struct pivot_value *
1985 pivot_value_new_var_value (const struct variable *variable,
1986                            const union value *value)
1987 {
1988   struct pivot_value *pv = pivot_value_new_value (
1989     value, var_get_width (variable), var_get_print_format (variable),
1990     var_get_encoding (variable));
1991
1992   char *var_name = xstrdup (var_get_name (variable));
1993   if (var_is_alpha (variable))
1994     pv->string.var_name = var_name;
1995   else
1996     pv->numeric.var_name = var_name;
1997
1998   const char *label = var_lookup_value_label (variable, value);
1999   if (label)
2000     {
2001       if (var_is_alpha (variable))
2002         pv->string.value_label = xstrdup (label);
2003       else
2004         pv->numeric.value_label = xstrdup (label);
2005     }
2006
2007   return pv;
2008 }
2009
2010 /* Returns a new pivot_value that represents VALUE, with the given WIDTH,
2011    formatted with FORMAT.  For a string value, ENCODING must be its character
2012    encoding. */
2013 struct pivot_value *
2014 pivot_value_new_value (const union value *value, int width,
2015                        const struct fmt_spec *format, const char *encoding)
2016 {
2017   struct pivot_value *pv = xzalloc (sizeof *pv);
2018   if (width > 0)
2019     {
2020       char *s = recode_string (UTF8, encoding,
2021                                CHAR_CAST (char *, value_str (value, width)),
2022                                width);
2023       size_t n = strlen (s);
2024       while (n > 0 && s[n - 1] == ' ')
2025         s[--n] = '\0';
2026
2027       pv->type = PIVOT_VALUE_STRING;
2028       pv->string.s = s;
2029       pv->string.hex = format->type == FMT_AHEX;
2030     }
2031   else
2032     {
2033       pv->type = PIVOT_VALUE_NUMERIC;
2034       pv->numeric.x = value->f;
2035       pv->numeric.format = *format;
2036     }
2037
2038   return pv;
2039 }
2040
2041 /* Returns a new pivot_value for VARIABLE. */
2042 struct pivot_value *
2043 pivot_value_new_variable (const struct variable *variable)
2044 {
2045   struct pivot_value *value = xmalloc (sizeof *value);
2046   *value = (struct pivot_value) {
2047     .type = PIVOT_VALUE_VARIABLE,
2048     .variable = {
2049       .var_name = xstrdup (var_get_name (variable)),
2050       .var_label = xstrdup_if_nonempty (var_get_label (variable)),
2051     },
2052   };
2053   return value;
2054 }
2055
2056 /* Attaches a reference to FOOTNOTE to V. */
2057 void
2058 pivot_value_add_footnote (struct pivot_value *v,
2059                           struct pivot_footnote *footnote)
2060 {
2061   v->footnotes = xrealloc (v->footnotes,
2062                            (v->n_footnotes + 1) * sizeof *v->footnotes);
2063   v->footnotes[v->n_footnotes++] = footnote;
2064 }
2065
2066 /* If VALUE is a numeric value, and RC is a result class such as
2067    PIVOT_RC_COUNT, changes VALUE's format to the result class's. */
2068 void
2069 pivot_value_set_rc (struct pivot_table *table, struct pivot_value *value,
2070                     const char *rc)
2071 {
2072   if (value->type == PIVOT_VALUE_NUMERIC)
2073     {
2074       const struct fmt_spec *f = pivot_table_get_format (table, rc);
2075       if (f)
2076         value->numeric.format = *f;
2077     }
2078 }
2079