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