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