Add support for reading and writing SPV files.
[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 = subtype ? pivot_value_new_text (subtype) : NULL;
708   table->command_c = output_get_command_name ();
709
710   table->sizing[TABLE_HORZ].range[0] = 50;
711   table->sizing[TABLE_HORZ].range[1] = 72;
712   table->sizing[TABLE_VERT].range[0] = 36;
713   table->sizing[TABLE_VERT].range[1] = 120;
714
715   for (size_t i = 0; i < PIVOT_N_AREAS; i++)
716     area_style_copy (NULL, &table->areas[i], pivot_area_get_default_style (i));
717
718   /* Set default border styles. */
719   static const enum table_stroke default_strokes[PIVOT_N_BORDERS] = {
720     [PIVOT_BORDER_TITLE]        = TABLE_STROKE_NONE,
721     [PIVOT_BORDER_OUTER_LEFT]   = TABLE_STROKE_NONE,
722     [PIVOT_BORDER_OUTER_TOP]    = TABLE_STROKE_NONE,
723     [PIVOT_BORDER_OUTER_RIGHT]  = TABLE_STROKE_NONE,
724     [PIVOT_BORDER_OUTER_BOTTOM] = TABLE_STROKE_NONE,
725     [PIVOT_BORDER_INNER_LEFT]   = TABLE_STROKE_THICK,
726     [PIVOT_BORDER_INNER_TOP]    = TABLE_STROKE_THICK,
727     [PIVOT_BORDER_INNER_RIGHT]  = TABLE_STROKE_THICK,
728     [PIVOT_BORDER_INNER_BOTTOM] = TABLE_STROKE_THICK,
729     [PIVOT_BORDER_DATA_LEFT]    = TABLE_STROKE_THICK,
730     [PIVOT_BORDER_DATA_TOP]     = TABLE_STROKE_THICK,
731     [PIVOT_BORDER_DIM_ROW_HORZ] = TABLE_STROKE_SOLID,
732     [PIVOT_BORDER_DIM_ROW_VERT] = TABLE_STROKE_NONE,
733     [PIVOT_BORDER_DIM_COL_HORZ] = TABLE_STROKE_SOLID,
734     [PIVOT_BORDER_DIM_COL_VERT] = TABLE_STROKE_SOLID,
735     [PIVOT_BORDER_CAT_ROW_HORZ] = TABLE_STROKE_NONE,
736     [PIVOT_BORDER_CAT_ROW_VERT] = TABLE_STROKE_NONE,
737     [PIVOT_BORDER_CAT_COL_HORZ] = TABLE_STROKE_SOLID,
738     [PIVOT_BORDER_CAT_COL_VERT] = TABLE_STROKE_SOLID,
739   };
740   for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
741     table->borders[i] = (struct table_border_style) {
742       .stroke = default_strokes[i],
743       .color = CELL_COLOR_BLACK,
744     };
745
746   table->row_labels_in_corner = true;
747   hmap_init (&table->cells);
748
749   return table;
750 }
751
752 /* Creates and returns a new pivot table with the given TITLE and a single cell
753    with the given CONTENT.
754
755    This is really just for error handling. */
756 struct pivot_table *
757 pivot_table_create_for_text (struct pivot_value *title,
758                              struct pivot_value *content)
759 {
760   struct pivot_table *table = pivot_table_create__ (title, "Error");
761
762   struct pivot_dimension *d = pivot_dimension_create (
763     table, PIVOT_AXIS_ROW, N_("Error"));
764   d->hide_all_labels = true;
765   pivot_category_create_leaf (d->root, pivot_value_new_text ("null"));
766
767   pivot_table_put1 (table, 0, content);
768
769   return table;
770 }
771
772 /* Increases TABLE's reference count, indicating that it has an additional
773    owner.  A pivot table that is shared among multiple owners must not be
774    modified. */
775 struct pivot_table *
776 pivot_table_ref (const struct pivot_table *table_)
777 {
778   struct pivot_table *table = CONST_CAST (struct pivot_table *, table_);
779   table->ref_cnt++;
780   return table;
781 }
782
783 /* Decreases TABLE's reference count, indicating that it has one fewer owner.
784    If TABLE no longer has any owners, it is freed. */
785 void
786 pivot_table_unref (struct pivot_table *table)
787 {
788   if (!table)
789     return;
790   assert (table->ref_cnt > 0);
791   if (--table->ref_cnt)
792     return;
793
794   free (table->current_layer);
795   free (table->table_look);
796
797   for (int i = 0; i < TABLE_N_AXES; i++)
798     pivot_table_sizing_uninit (&table->sizing[i]);
799
800   free (table->continuation);
801
802   for (int i = 0; i < sizeof table->ccs / sizeof *table->ccs; i++)
803     free (table->ccs[i]);
804
805   free (table->command_local);
806   free (table->command_c);
807   free (table->language);
808   free (table->locale);
809
810   free (table->dataset);
811   free (table->datafile);
812
813   for (size_t i = 0; i < table->n_footnotes; i++)
814     pivot_footnote_destroy (table->footnotes[i]);
815   free (table->footnotes);
816
817   pivot_value_destroy (table->title);
818   pivot_value_destroy (table->subtype);
819   pivot_value_destroy (table->corner_text);
820   pivot_value_destroy (table->caption);
821
822   for (size_t i = 0; i < PIVOT_N_AREAS; i++)
823     area_style_uninit (&table->areas[i]);
824
825   for (size_t i = 0; i < table->n_dimensions; i++)
826     pivot_dimension_destroy (table->dimensions[i]);
827   free (table->dimensions);
828
829   for (size_t i = 0; i < PIVOT_N_AXES; i++)
830     free (table->axes[i].dimensions);
831
832   struct pivot_cell *cell, *next_cell;
833   HMAP_FOR_EACH_SAFE (cell, next_cell, struct pivot_cell, hmap_node,
834                       &table->cells)
835     {
836       hmap_delete (&table->cells, &cell->hmap_node);
837       pivot_value_destroy (cell->value);
838       free (cell);
839     }
840   hmap_destroy (&table->cells);
841
842   free (table);
843 }
844
845 /* Returns true if TABLE has more than one owner.  A pivot table that is shared
846    among multiple owners must not be modified. */
847 bool
848 pivot_table_is_shared (const struct pivot_table *table)
849 {
850   return table->ref_cnt > 1;
851 }
852
853 /* Sets the format used for PIVOT_RC_COUNT cells to the one used for variable
854    WV, which should be the weight variable for the dictionary whose data or
855    statistics are being put into TABLE.
856
857    This has no effect if WV is NULL. */
858 void
859 pivot_table_set_weight_var (struct pivot_table *table,
860                             const struct variable *wv)
861 {
862   if (wv)
863     pivot_table_set_weight_format (table, var_get_print_format (wv));
864 }
865
866 /* Sets the format used for PIVOT_RC_COUNT cells to WFMT, which should be the
867    format for the dictionary whose data or statistics are being put into TABLE.
868
869    This has no effect if WFMT is NULL. */
870 void
871 pivot_table_set_weight_format (struct pivot_table *table,
872                                const struct fmt_spec *wfmt)
873 {
874   if (wfmt)
875     table->weight_format = *wfmt;
876 }
877
878 /* Returns true if TABLE has no cells, false otherwise. */
879 bool
880 pivot_table_is_empty (const struct pivot_table *table)
881 {
882   return hmap_is_empty (&table->cells);
883 }
884
885 static unsigned int
886 pivot_cell_hash_indexes (const size_t *indexes, size_t n_idx)
887 {
888   return hash_bytes (indexes, n_idx * sizeof *indexes, 0);
889 }
890
891 static bool
892 equal_indexes (const size_t *a, const unsigned int *b, size_t n)
893 {
894   for (size_t i = 0; i < n; i++)
895     if (a[i] != b[i])
896       return false;
897
898   return true;
899 }
900
901 static struct pivot_cell *
902 pivot_table_lookup_cell__ (const struct pivot_table *table,
903                             const size_t *dindexes, unsigned int hash)
904 {
905   struct pivot_cell *cell;
906   HMAP_FOR_EACH_WITH_HASH (cell, struct pivot_cell, hmap_node, hash,
907                            &table->cells)
908     if (equal_indexes (dindexes, cell->idx, table->n_dimensions))
909       return cell;
910   return false;
911 }
912
913 static struct pivot_cell *
914 pivot_cell_allocate (size_t n_idx)
915 {
916   struct pivot_cell *cell UNUSED;
917   return xmalloc (sizeof *cell + n_idx * sizeof *cell->idx);
918 }
919
920 static struct pivot_cell *
921 pivot_table_insert_cell (struct pivot_table *table, const size_t *dindexes)
922 {
923   unsigned int hash = pivot_cell_hash_indexes (dindexes, table->n_dimensions);
924   struct pivot_cell *cell = pivot_table_lookup_cell__ (table, dindexes, hash);
925   if (!cell)
926     {
927       cell = pivot_cell_allocate (table->n_dimensions);
928       for (size_t i = 0; i < table->n_dimensions; i++)
929         cell->idx[i] = dindexes[i];
930       cell->value = NULL;
931       hmap_insert (&table->cells, &cell->hmap_node, hash);
932     }
933   return cell;
934 }
935
936 /* Puts VALUE in the cell in TABLE whose indexes are given by the N indexes in
937    DINDEXES.  N must be the number of dimensions in TABLE.  Takes ownership of
938    VALUE.
939
940    If VALUE is a numeric value without a specified format, this function checks
941    each of the categories designated by DINDEXES[] and takes the format from
942    the first category with a result class.  If none has a result class, uses
943    the overall default numeric format. */
944 void
945 pivot_table_put (struct pivot_table *table, const size_t *dindexes, size_t n,
946                  struct pivot_value *value)
947 {
948   assert (n == table->n_dimensions);
949
950   if (value->type == PIVOT_VALUE_NUMERIC && !value->numeric.format.w)
951     {
952       for (size_t i = 0; i < table->n_dimensions; i++)
953         {
954           const struct pivot_dimension *d = table->dimensions[i];
955           if (dindexes[i] < d->n_leaves)
956             {
957               const struct pivot_category *c = d->data_leaves[dindexes[i]];
958               if (c->format.w)
959                 {
960                   value->numeric.format = c->format;
961                   goto done;
962                 }
963             }
964         }
965       value->numeric.format = *settings_get_format ();
966
967     done:;
968     }
969
970   struct pivot_cell *cell = pivot_table_insert_cell (table, dindexes);
971   pivot_value_destroy (cell->value);
972   cell->value = value;
973 }
974
975 /* Puts VALUE in the cell in TABLE with index IDX1.  TABLE must have 1
976    dimension.  Takes ownership of VALUE.  */
977 void
978 pivot_table_put1 (struct pivot_table *table, size_t idx1,
979                   struct pivot_value *value)
980 {
981   size_t dindexes[] = { idx1 };
982   pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
983 }
984
985 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2).  TABLE must have 2
986    dimensions.  Takes ownership of VALUE.  */
987 void
988 pivot_table_put2 (struct pivot_table *table, size_t idx1, size_t idx2,
989                   struct pivot_value *value)
990 {
991   size_t dindexes[] = { idx1, idx2 };
992   pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
993 }
994
995 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2, IDX3).  TABLE must
996    have 3 dimensions.  Takes ownership of VALUE.  */
997 void
998 pivot_table_put3 (struct pivot_table *table, size_t idx1, size_t idx2,
999                   size_t idx3, struct pivot_value *value)
1000 {
1001   size_t dindexes[] = { idx1, idx2, idx3 };
1002   pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
1003 }
1004
1005 /* Puts VALUE in the cell in TABLE with index (IDX1, IDX2, IDX3, IDX4).  TABLE
1006    must have 4 dimensions.  Takes ownership of VALUE.  */
1007 void
1008 pivot_table_put4 (struct pivot_table *table, size_t idx1, size_t idx2,
1009                   size_t idx3, size_t idx4, struct pivot_value *value)
1010 {
1011   size_t dindexes[] = { idx1, idx2, idx3, idx4 };
1012   pivot_table_put (table, dindexes, sizeof dindexes / sizeof *dindexes, value);
1013 }
1014
1015 /* Creates and returns a new footnote in TABLE with the given CONTENT and an
1016    automatically assigned marker.
1017
1018    The footnote will only appear in output if it is referenced.  Use
1019    pivot_value_add_footnote() to add a reference to the footnote. */
1020 struct pivot_footnote *
1021 pivot_table_create_footnote (struct pivot_table *table,
1022                              struct pivot_value *content)
1023 {
1024   return pivot_table_create_footnote__ (table, table->n_footnotes,
1025                                         NULL, content);
1026 }
1027
1028 static struct pivot_value *
1029 pivot_make_default_footnote_marker (int idx, bool show_numeric_markers)
1030 {
1031   char text[INT_BUFSIZE_BOUND (size_t)];
1032   if (show_numeric_markers)
1033     snprintf (text, sizeof text, "%d", idx + 1);
1034   else
1035     str_format_26adic (idx + 1, false, text, sizeof text);
1036   return pivot_value_new_user_text (text, -1);
1037 }
1038
1039 /* Creates or modifies a footnote in TABLE with 0-based number IDX (and creates
1040    all lower indexes as a side effect).  If MARKER is nonnull, sets the
1041    footnote's marker; if CONTENT is nonnull, sets the footnote's content. */
1042 struct pivot_footnote *
1043 pivot_table_create_footnote__ (struct pivot_table *table, size_t idx,
1044                                struct pivot_value *marker,
1045                                struct pivot_value *content)
1046 {
1047   if (idx >= table->n_footnotes)
1048     {
1049       while (idx >= table->allocated_footnotes)
1050         table->footnotes = x2nrealloc (table->footnotes,
1051                                        &table->allocated_footnotes,
1052                                        sizeof *table->footnotes);
1053       while (idx >= table->n_footnotes)
1054         {
1055           struct pivot_footnote *f = xmalloc (sizeof *f);
1056           f->idx = table->n_footnotes;
1057           f->marker = pivot_make_default_footnote_marker (
1058             f->idx, table->show_numeric_markers);
1059           f->content = NULL;
1060           f->show = true;
1061
1062           table->footnotes[table->n_footnotes++] = f;
1063         }
1064     }
1065
1066   struct pivot_footnote *f = table->footnotes[idx];
1067   if (marker)
1068     {
1069       pivot_value_destroy (f->marker);
1070       f->marker = marker;
1071     }
1072   if (content)
1073     {
1074       pivot_value_destroy (f->content);
1075       f->content = content;
1076     }
1077   return f;
1078 }
1079
1080 /* Frees the data owned by F. */
1081 void
1082 pivot_footnote_destroy (struct pivot_footnote *f)
1083 {
1084   if (f)
1085     {
1086       pivot_value_destroy (f->content);
1087       pivot_value_destroy (f->marker);
1088       free (f);
1089     }
1090 }
1091
1092 /* Converts per-axis presentation-order indexes, given in PINDEXES, into data
1093    indexes for each dimension in TABLE in DINDEXES[]. */
1094 void
1095 pivot_table_convert_indexes_ptod (const struct pivot_table *table,
1096                                   const size_t *pindexes[PIVOT_N_AXES],
1097                                   size_t dindexes[/* table->n_dimensions */])
1098 {
1099   for (size_t i = 0; i < PIVOT_N_AXES; i++)
1100     {
1101       const struct pivot_axis *axis = &table->axes[i];
1102
1103       for (size_t j = 0; j < axis->n_dimensions; j++)
1104         {
1105           const struct pivot_dimension *d = axis->dimensions[j];
1106           dindexes[d->top_index]
1107             = d->presentation_leaves[pindexes[i][j]]->data_index;
1108         }
1109     }
1110 }
1111
1112 size_t *
1113 pivot_table_enumerate_axis (const struct pivot_table *table,
1114                             enum pivot_axis_type axis_type,
1115                             const size_t *layer_indexes, bool omit_empty,
1116                             size_t *n)
1117 {
1118   const struct pivot_axis *axis = &table->axes[axis_type];
1119   if (!axis->n_dimensions)
1120     {
1121       size_t *enumeration = xnmalloc (2, sizeof *enumeration);
1122       enumeration[0] = 0;
1123       enumeration[1] = SIZE_MAX;
1124       if (n)
1125         *n = 1;
1126       return enumeration;
1127     }
1128   else if (!axis->extent)
1129     {
1130       size_t *enumeration = xmalloc (sizeof *enumeration);
1131       *enumeration = SIZE_MAX;
1132       if (n)
1133         *n = 0;
1134       return enumeration;
1135     }
1136
1137   size_t *enumeration = xnmalloc (xsum (xtimes (axis->extent,
1138                                                 axis->n_dimensions), 1),
1139                                   sizeof *enumeration);
1140   size_t *p = enumeration;
1141   size_t *dindexes = xcalloc (table->n_dimensions, sizeof *dindexes);
1142
1143   size_t *axis_indexes;
1144   PIVOT_AXIS_FOR_EACH (axis_indexes, axis)
1145     {
1146       if (omit_empty)
1147         {
1148           enum pivot_axis_type axis2_type
1149             = pivot_axis_type_transpose (axis_type);
1150
1151           size_t *axis2_indexes;
1152           PIVOT_AXIS_FOR_EACH (axis2_indexes, &table->axes[axis2_type])
1153             {
1154               const size_t *pindexes[PIVOT_N_AXES];
1155               pindexes[PIVOT_AXIS_LAYER] = layer_indexes;
1156               pindexes[axis_type] = axis_indexes;
1157               pindexes[axis2_type] = axis2_indexes;
1158               pivot_table_convert_indexes_ptod (table, pindexes, dindexes);
1159               if (pivot_table_get (table, dindexes))
1160                 goto found;
1161             }
1162           continue;
1163
1164         found:
1165           free (axis2_indexes);
1166         }
1167
1168       memcpy (p, axis_indexes, axis->n_dimensions * sizeof *p);
1169       p += axis->n_dimensions;
1170     }
1171   *p = SIZE_MAX;
1172   if (n)
1173     *n = (p - enumeration) / axis->n_dimensions;
1174
1175   free (dindexes);
1176   return enumeration;
1177 }
1178
1179 static const struct pivot_cell *
1180 pivot_table_lookup_cell (const struct pivot_table *table,
1181                           const size_t *dindexes)
1182 {
1183   unsigned int hash = pivot_cell_hash_indexes (dindexes, table->n_dimensions);
1184   return pivot_table_lookup_cell__ (table, dindexes, hash);
1185 }
1186
1187 const struct pivot_value *
1188 pivot_table_get (const struct pivot_table *table, const size_t *dindexes)
1189 {
1190   const struct pivot_cell *cell = pivot_table_lookup_cell (table, dindexes);
1191   return cell ? cell->value : NULL;
1192 }
1193
1194 struct pivot_value *
1195 pivot_table_get_rw (struct pivot_table *table, const size_t *dindexes)
1196 {
1197   struct pivot_cell *cell = pivot_table_insert_cell (table, dindexes);
1198   if (!cell->value)
1199     cell->value = pivot_value_new_user_text ("", -1);
1200   return cell->value;
1201 }
1202
1203 static void
1204 distribute_extra_depth (struct pivot_category *category, size_t extra_depth)
1205 {
1206   if (pivot_category_is_group (category) && category->n_subs)
1207     for (size_t i = 0; i < category->n_subs; i++)
1208       distribute_extra_depth (category->subs[i], extra_depth);
1209   else
1210     category->extra_depth += extra_depth;
1211 }
1212
1213 static void
1214 pivot_category_assign_label_depth (struct pivot_category *category,
1215                                    bool dimension_labels_in_corner)
1216 {
1217   category->extra_depth = 0;
1218
1219   if (pivot_category_is_group (category))
1220     {
1221       size_t depth = 0;
1222       for (size_t i = 0; i < category->n_subs; i++)
1223         {
1224           pivot_category_assign_label_depth (category->subs[i], false);
1225           depth = MAX (depth, category->subs[i]->label_depth);
1226         }
1227
1228       for (size_t i = 0; i < category->n_subs; i++)
1229         {
1230           struct pivot_category *sub = category->subs[i];
1231
1232           size_t extra_depth = depth - sub->label_depth;
1233           if (extra_depth)
1234             distribute_extra_depth (sub, extra_depth);
1235
1236           sub->label_depth = depth;
1237         }
1238
1239       category->show_label_in_corner = (category->show_label
1240                                         && dimension_labels_in_corner);
1241       category->label_depth
1242         = (category->show_label && !category->show_label_in_corner
1243            ? depth + 1 : depth);
1244     }
1245   else
1246     category->label_depth = 1;
1247 }
1248
1249 static bool
1250 pivot_axis_assign_label_depth (struct pivot_table *table,
1251                              enum pivot_axis_type axis_type,
1252                              bool dimension_labels_in_corner)
1253 {
1254   struct pivot_axis *axis = &table->axes[axis_type];
1255   bool any_label_shown_in_corner = false;
1256   axis->label_depth = 0;
1257   axis->extent = 1;
1258   for (size_t i = 0; i < axis->n_dimensions; i++)
1259     {
1260       struct pivot_dimension *d = axis->dimensions[i];
1261       pivot_category_assign_label_depth (d->root, dimension_labels_in_corner);
1262       d->label_depth = d->hide_all_labels ? 0 : d->root->label_depth;
1263       axis->label_depth += d->label_depth;
1264       axis->extent *= d->n_leaves;
1265
1266       if (d->root->show_label_in_corner)
1267         any_label_shown_in_corner = true;
1268     }
1269   return any_label_shown_in_corner;
1270 }
1271
1272 void
1273 pivot_table_assign_label_depth (struct pivot_table *table)
1274 {
1275   pivot_axis_assign_label_depth (table, PIVOT_AXIS_COLUMN, false);
1276   if (pivot_axis_assign_label_depth (
1277         table, PIVOT_AXIS_ROW, (table->row_labels_in_corner
1278                                 && !table->corner_text))
1279       && table->axes[PIVOT_AXIS_COLUMN].label_depth == 0)
1280     table->axes[PIVOT_AXIS_COLUMN].label_depth = 1;
1281   pivot_axis_assign_label_depth (table, PIVOT_AXIS_LAYER, false);
1282 }
1283 \f
1284 /* Footnotes. */
1285
1286 \f
1287 \f
1288 static void
1289 indent (int indentation)
1290 {
1291   for (int i = 0; i < indentation * 2; i++)
1292     putchar (' ');
1293 }
1294
1295 static void
1296 pivot_value_dump (const struct pivot_value *value)
1297 {
1298   char *s = pivot_value_to_string (value, SETTINGS_VALUE_SHOW_DEFAULT,
1299                                    SETTINGS_VALUE_SHOW_DEFAULT);
1300   fputs (s, stdout);
1301   free (s);
1302 }
1303
1304 static void
1305 pivot_table_dump_value (const struct pivot_value *value, const char *name,
1306                       int indentation)
1307 {
1308   if (value)
1309     {
1310       indent (indentation);
1311       printf ("%s: ", name);
1312       pivot_value_dump (value);
1313       putchar ('\n');
1314     }
1315 }
1316
1317 static void
1318 pivot_table_dump_string (const char *string, const char *name, int indentation)
1319 {
1320   if (string)
1321     {
1322       indent (indentation);
1323       printf ("%s: %s\n", name, string);
1324     }
1325 }
1326
1327 static void
1328 pivot_category_dump (const struct pivot_category *c, int indentation)
1329 {
1330   indent (indentation);
1331   printf ("%s \"", pivot_category_is_leaf (c) ? "leaf" : "group");
1332   pivot_value_dump (c->name);
1333   printf ("\" ");
1334
1335   if (pivot_category_is_leaf (c))
1336     printf ("data_index=%zu\n", c->data_index);
1337   else
1338     {
1339       printf (" (label %s)", c->show_label ? "shown" : "hidden");
1340       printf ("\n");
1341
1342       for (size_t i = 0; i < c->n_subs; i++)
1343         pivot_category_dump (c->subs[i], indentation + 1);
1344     }
1345 }
1346
1347 void
1348 pivot_dimension_dump (const struct pivot_dimension *d, int indentation)
1349 {
1350   indent (indentation);
1351   printf ("%s dimension %zu (where 0=innermost), label_depth=%d:\n",
1352           pivot_axis_type_to_string (d->axis_type), d->level, d->label_depth);
1353
1354   pivot_category_dump (d->root, indentation + 1);
1355 }
1356
1357 static void
1358 area_style_dump (enum pivot_area area, const struct area_style *a,
1359                  int indentation)
1360 {
1361   indent (indentation);
1362   printf ("%s: ", pivot_area_to_string (area));
1363   font_style_dump (&a->font_style);
1364   putchar (' ');
1365   cell_style_dump (&a->cell_style);
1366   putchar ('\n');
1367 }
1368
1369 static void
1370 table_border_style_dump (enum pivot_border border,
1371                          const struct table_border_style *b, int indentation)
1372 {
1373   indent (indentation);
1374   printf ("%s: %s ", pivot_border_to_string (border),
1375           table_stroke_to_string (b->stroke));
1376   cell_color_dump (&b->color);
1377   putchar ('\n');
1378 }
1379
1380 static char ***
1381 compose_headings (const struct pivot_axis *axis,
1382                   const size_t *column_enumeration,
1383                   enum settings_value_show show_values,
1384                   enum settings_value_show show_variables)
1385 {
1386   if (!axis->n_dimensions || !axis->extent || !axis->label_depth)
1387     return NULL;
1388
1389   char ***headings = xnmalloc (axis->label_depth, sizeof *headings);
1390   for (size_t i = 0; i < axis->label_depth; i++)
1391     headings[i] = xcalloc (axis->extent, sizeof **headings);
1392
1393   const size_t *indexes;
1394   size_t column = 0;
1395   PIVOT_ENUMERATION_FOR_EACH (indexes, column_enumeration, axis)
1396     {
1397       int row = axis->label_depth - 1;
1398       for (int dim_index = 0; dim_index < axis->n_dimensions; dim_index++)
1399         {
1400           const struct pivot_dimension *d = axis->dimensions[dim_index];
1401           if (d->hide_all_labels)
1402             continue;
1403           for (const struct pivot_category *c
1404                  = d->presentation_leaves[indexes[dim_index]];
1405                c;
1406                c = c->parent)
1407             {
1408               if (pivot_category_is_leaf (c) || (c->show_label
1409                                                  && !c->show_label_in_corner))
1410                 {
1411                   headings[row][column] = pivot_value_to_string (
1412                     c->name, show_values, show_variables);
1413                   if (!*headings[row][column])
1414                     headings[row][column] = xstrdup ("<blank>");
1415                   row--;
1416                 }
1417             }
1418         }
1419       column++;
1420     }
1421
1422   return headings;
1423 }
1424
1425 static void
1426 free_headings (const struct pivot_axis *axis, char ***headings)
1427 {
1428   for (size_t i = 0; i < axis->label_depth; i++)
1429     {
1430       for (size_t j = 0; j < axis->extent; j++)
1431         free (headings[i][j]);
1432       free (headings[i]);
1433     }
1434   free (headings);
1435 }
1436
1437 static void
1438 pivot_table_sizing_dump (const char *name, const struct pivot_table_sizing *s,
1439                          int indentation)
1440 {
1441   indent (indentation);
1442   printf ("%ss: min=%d, max=%d\n", name, s->range[0], s->range[1]);
1443   if (s->n_widths)
1444     {
1445       indent (indentation + 1);
1446       printf ("%s widths:", name);
1447       for (size_t i = 0; i < s->n_widths; i++)
1448         printf (" %d", s->widths[i]);
1449       printf ("\n");
1450     }
1451   if (s->n_breaks)
1452     {
1453       indent (indentation + 1);
1454       printf ("break after %ss:", name);
1455       for (size_t i = 0; i < s->n_breaks; i++)
1456         printf (" %zu", s->breaks[i]);
1457       printf ("\n");
1458     }
1459   if (s->n_keeps)
1460     {
1461       indent (indentation + 1);
1462       printf ("keep %ss together:", name);
1463       for (size_t i = 0; i < s->n_keeps; i++)
1464         printf (" [%zu,%zu]",
1465                 s->keeps[i].ofs,
1466                 s->keeps[i].ofs + s->keeps[i].n - 1);
1467       printf ("\n");
1468     }
1469 }
1470
1471 void
1472 pivot_table_dump (const struct pivot_table *table, int indentation)
1473 {
1474   if (!table)
1475     return;
1476
1477   int old_decimal = settings_get_decimal_char (FMT_COMMA);
1478   if (table->decimal == '.' || table->decimal == ',')
1479     settings_set_decimal_char (table->decimal);
1480
1481   pivot_table_dump_value (table->title, "title", indentation);
1482   pivot_table_dump_string (table->command_c, "command", indentation);
1483   pivot_table_dump_string (table->dataset, "dataset", indentation);
1484   pivot_table_dump_string (table->datafile, "datafile", indentation);
1485   pivot_table_dump_string (table->notes, "notes", indentation);
1486   pivot_table_dump_string (table->table_look, "table-look", indentation);
1487   if (table->date)
1488     {
1489       indent (indentation);
1490       char buf[26];
1491       printf ("date: %s", ctime_r (&table->date, buf));
1492     }
1493
1494   indent (indentation);
1495   printf ("sizing:\n");
1496   pivot_table_sizing_dump ("column", &table->sizing[TABLE_HORZ],
1497                            indentation + 1);
1498   pivot_table_sizing_dump ("row", &table->sizing[TABLE_VERT],
1499                            indentation + 1);
1500
1501   indent (indentation);
1502   printf ("areas:\n");
1503   for (enum pivot_area area = 0; area < PIVOT_N_AREAS; area++)
1504     area_style_dump (area, &table->areas[area], indentation + 1);
1505
1506   indent (indentation);
1507   printf ("borders:\n");
1508   for (enum pivot_border border = 0; border < PIVOT_N_BORDERS; border++)
1509     table_border_style_dump (border, &table->borders[border], indentation + 1);
1510
1511   for (size_t i = 0; i < table->n_dimensions; i++)
1512     pivot_dimension_dump (table->dimensions[i], indentation);
1513
1514   /* Presentation and data indexes. */
1515   size_t *dindexes = xcalloc (table->n_dimensions, sizeof *dindexes);
1516
1517   const struct pivot_axis *layer_axis = &table->axes[PIVOT_AXIS_LAYER];
1518   if (layer_axis->n_dimensions)
1519     {
1520       indent (indentation);
1521       printf ("current layer:");
1522
1523       for (size_t i = 0; i < layer_axis->n_dimensions; i++)
1524         {
1525           const struct pivot_dimension *d = layer_axis->dimensions[i];
1526           char *name = pivot_value_to_string (d->root->name,
1527                                               table->show_values,
1528                                               table->show_variables);
1529           char *value = pivot_value_to_string (
1530             d->data_leaves[table->current_layer[i]]->name,
1531             table->show_values, table->show_variables);
1532           printf (" %s=%s", name, value);
1533           free (value);
1534           free (name);
1535         }
1536
1537       putchar ('\n');
1538     }
1539
1540   size_t *layer_indexes;
1541   size_t layer_iteration = 0;
1542   PIVOT_AXIS_FOR_EACH (layer_indexes, &table->axes[PIVOT_AXIS_LAYER])
1543     {
1544       indent (indentation);
1545       printf ("layer %zu:", layer_iteration++);
1546
1547       const struct pivot_axis *layer_axis = &table->axes[PIVOT_AXIS_LAYER];
1548       for (size_t i = 0; i < layer_axis->n_dimensions; i++)
1549         {
1550           const struct pivot_dimension *d = layer_axis->dimensions[i];
1551
1552           fputs (i == 0 ? " " : ", ", stdout);
1553           pivot_value_dump (d->root->name);
1554           fputs (" =", stdout);
1555
1556           struct pivot_value **names = xnmalloc (layer_axis->label_depth,
1557                                                  sizeof *names);
1558           size_t n_names = 0;
1559           for (const struct pivot_category *c
1560                  = d->presentation_leaves[layer_indexes[i]];
1561                c;
1562                c = c->parent)
1563             {
1564               if (pivot_category_is_leaf (c) || c->show_label)
1565                 names[n_names++] = c->name;
1566             }
1567
1568           for (size_t i = n_names; i-- > 0; )
1569             {
1570               putchar (' ');
1571               pivot_value_dump (names[i]);
1572             }
1573           free (names);
1574         }
1575       putchar ('\n');
1576
1577       size_t *column_enumeration = pivot_table_enumerate_axis (
1578         table, PIVOT_AXIS_COLUMN, layer_indexes, table->omit_empty, NULL);
1579       size_t *row_enumeration = pivot_table_enumerate_axis (
1580         table, PIVOT_AXIS_ROW, layer_indexes, table->omit_empty, NULL);
1581
1582       char ***column_headings = compose_headings (
1583         &table->axes[PIVOT_AXIS_COLUMN], column_enumeration,
1584         table->show_values, table->show_variables);
1585       for (size_t y = 0; y < table->axes[PIVOT_AXIS_COLUMN].label_depth; y++)
1586         {
1587           indent (indentation + 1);
1588           for (size_t x = 0; x < table->axes[PIVOT_AXIS_COLUMN].extent; x++)
1589             {
1590               if (x)
1591                 fputs ("; ", stdout);
1592               if (column_headings[y][x])
1593                 fputs (column_headings[y][x], stdout);
1594             }
1595           putchar ('\n');
1596         }
1597       free_headings (&table->axes[PIVOT_AXIS_COLUMN], column_headings);
1598
1599       indent (indentation + 1);
1600       printf ("-----------------------------------------------\n");
1601
1602       char ***row_headings = compose_headings (
1603         &table->axes[PIVOT_AXIS_ROW], row_enumeration,
1604         table->show_values, table->show_variables);
1605
1606       size_t x = 0;
1607       const size_t *pindexes[PIVOT_N_AXES]
1608         = { [PIVOT_AXIS_LAYER] = layer_indexes };
1609       PIVOT_ENUMERATION_FOR_EACH (pindexes[PIVOT_AXIS_ROW], row_enumeration,
1610                                   &table->axes[PIVOT_AXIS_ROW])
1611         {
1612           indent (indentation + 1);
1613
1614           size_t i = 0;
1615           for (size_t y = 0; y < table->axes[PIVOT_AXIS_ROW].label_depth; y++)
1616             {
1617               if (i++)
1618                 fputs ("; ", stdout);
1619               if (row_headings[y][x])
1620                 fputs (row_headings[y][x], stdout);
1621             }
1622
1623           printf (" | ");
1624
1625           i = 0;
1626           PIVOT_ENUMERATION_FOR_EACH (pindexes[PIVOT_AXIS_COLUMN],
1627                                       column_enumeration,
1628                                       &table->axes[PIVOT_AXIS_COLUMN])
1629             {
1630               if (i++)
1631                 printf ("; ");
1632
1633               pivot_table_convert_indexes_ptod (table, pindexes, dindexes);
1634               const struct pivot_value *value = pivot_table_get (
1635                 table, dindexes);
1636               if (value)
1637                 pivot_value_dump (value);
1638             }
1639           printf ("\n");
1640
1641           x++;
1642         }
1643
1644       free (column_enumeration);
1645       free (row_enumeration);
1646       free_headings (&table->axes[PIVOT_AXIS_ROW], row_headings);
1647     }
1648
1649   pivot_table_dump_value (table->caption, "caption", indentation);
1650
1651   for (size_t i = 0; i < table->n_footnotes; i++)
1652     {
1653       const struct pivot_footnote *f = table->footnotes[i];
1654       indent (indentation);
1655       putchar ('[');
1656       if (f->marker)
1657         pivot_value_dump (f->marker);
1658       else
1659         printf ("%zu", f->idx);
1660       putchar (']');
1661       pivot_value_dump (f->content);
1662       putchar ('\n');
1663     }
1664
1665   free (dindexes);
1666   settings_set_decimal_char (old_decimal);
1667 }
1668 \f
1669 static const char *
1670 consume_int (const char *p, size_t *n)
1671 {
1672   *n = 0;
1673   while (c_isdigit (*p))
1674     *n = *n * 10 + (*p++ - '0');
1675   return p;
1676 }
1677
1678 static size_t
1679 pivot_format_inner_template (struct string *out, const char *template,
1680                              char escape,
1681                              struct pivot_value **values, size_t n_values,
1682                              enum settings_value_show show_values,
1683                              enum settings_value_show show_variables)
1684 {
1685   size_t args_consumed = 0;
1686   while (*template && *template != ':')
1687     {
1688       if (*template == '\\' && template[1])
1689         {
1690           ds_put_byte (out, template[1] == 'n' ? '\n' : template[1]);
1691           template += 2;
1692         }
1693       else if (*template == escape)
1694         {
1695           size_t index;
1696           template = consume_int (template + 1, &index);
1697           if (index >= 1 && index <= n_values)
1698             {
1699               pivot_value_format (values[index - 1], show_values,
1700                                   show_variables, out);
1701               args_consumed = MAX (args_consumed, index);
1702             }
1703         }
1704       else
1705         ds_put_byte (out, *template++);
1706     }
1707   return args_consumed;
1708 }
1709
1710 static const char *
1711 pivot_extract_inner_template (const char *template, const char **p)
1712 {
1713   *p = template;
1714
1715   for (;;)
1716     {
1717       if (*template == '\\' && template[1] != '\0')
1718         template += 2;
1719       else if (*template == ':')
1720         return template + 1;
1721       else if (*template == '\0')
1722         return template;
1723       else
1724         template++;
1725     }
1726 }
1727
1728 static void
1729 pivot_format_template (struct string *out, const char *template,
1730                        const struct pivot_argument *args, size_t n_args,
1731                        enum settings_value_show show_values,
1732                        enum settings_value_show show_variables)
1733 {
1734   while (*template)
1735     {
1736       if (*template == '\\' && template[1] != '\0')
1737         {
1738           ds_put_byte (out, template[1] == 'n' ? '\n' : template[1]);
1739           template += 2;
1740         }
1741       else if (*template == '^')
1742         {
1743           size_t index;
1744           template = consume_int (template + 1, &index);
1745           if (index >= 1 && index <= n_args && args[index - 1].n > 0)
1746             pivot_value_format (args[index - 1].values[0],
1747                                 show_values, show_variables, out);
1748         }
1749       else if (*template == '[')
1750         {
1751           const char *tmpl[2];
1752           template = pivot_extract_inner_template (template + 1, &tmpl[0]);
1753           template = pivot_extract_inner_template (template, &tmpl[1]);
1754           template += *template == ']';
1755
1756           size_t index;
1757           template = consume_int (template, &index);
1758           if (index < 1 || index > n_args)
1759             continue;
1760
1761           const struct pivot_argument *arg = &args[index - 1];
1762           size_t left = arg->n;
1763           while (left)
1764             {
1765               struct pivot_value **values = arg->values + (arg->n - left);
1766               int tmpl_idx = left == arg->n && *tmpl[0] != ':' ? 0 : 1;
1767               char escape = "%^"[tmpl_idx];
1768               size_t used = pivot_format_inner_template (
1769                 out, tmpl[tmpl_idx], escape, values, left,
1770                 show_values, show_variables);
1771               if (!used || used > left)
1772                 break;
1773               left -= used;
1774             }
1775         }
1776       else
1777         ds_put_byte (out, *template++);
1778     }
1779 }
1780
1781 static enum settings_value_show
1782 interpret_show (enum settings_value_show global_show,
1783                 enum settings_value_show table_show,
1784                 enum settings_value_show value_show,
1785                 bool has_label)
1786 {
1787   return (!has_label ? SETTINGS_VALUE_SHOW_VALUE
1788           : value_show != SETTINGS_VALUE_SHOW_DEFAULT ? value_show
1789           : table_show != SETTINGS_VALUE_SHOW_DEFAULT ? table_show
1790           : global_show);
1791 }
1792
1793 /* Appends a text representation of the body of VALUE to OUT.  SHOW_VALUES and
1794    SHOW_VARIABLES control whether variable and value labels are included.
1795
1796    The "body" omits subscripts and superscripts and footnotes. */
1797 bool
1798 pivot_value_format_body (const struct pivot_value *value,
1799                          enum settings_value_show show_values,
1800                          enum settings_value_show show_variables,
1801                          struct string *out)
1802 {
1803   enum settings_value_show show;
1804   bool numeric = false;
1805
1806   switch (value->type)
1807     {
1808     case PIVOT_VALUE_NUMERIC:
1809       show = interpret_show (settings_get_show_values (),
1810                              show_values,
1811                              value->numeric.show,
1812                              value->numeric.value_label != NULL);
1813       if (show & SETTINGS_VALUE_SHOW_VALUE)
1814         {
1815           char *s = data_out (&(union value) { .f = value->numeric.x },
1816                               "UTF-8", &value->numeric.format);
1817           ds_put_cstr (out, s + strspn (s, " "));
1818           free (s);
1819         }
1820       if (show & SETTINGS_VALUE_SHOW_LABEL)
1821         {
1822           if (show & SETTINGS_VALUE_SHOW_VALUE)
1823             ds_put_byte (out, ' ');
1824           ds_put_cstr (out, value->numeric.value_label);
1825         }
1826       numeric = !(show & SETTINGS_VALUE_SHOW_LABEL);
1827       break;
1828
1829     case PIVOT_VALUE_STRING:
1830       show = interpret_show (settings_get_show_values (),
1831                              show_values,
1832                              value->string.show,
1833                              value->string.value_label != NULL);
1834       if (show & SETTINGS_VALUE_SHOW_VALUE)
1835         {
1836           if (value->string.hex)
1837             {
1838               for (const uint8_t *p = CHAR_CAST (uint8_t *, value->string.s);
1839                    *p; p++)
1840                 ds_put_format (out, "%02X", *p);
1841             }
1842           else
1843             ds_put_cstr (out, value->string.s);
1844         }
1845       if (show & SETTINGS_VALUE_SHOW_LABEL)
1846         {
1847           if (show & SETTINGS_VALUE_SHOW_VALUE)
1848             ds_put_byte (out, ' ');
1849           ds_put_cstr (out, value->string.value_label);
1850         }
1851       break;
1852
1853     case PIVOT_VALUE_VARIABLE:
1854       show = interpret_show (settings_get_show_variables (),
1855                              show_variables,
1856                              value->variable.show,
1857                              value->variable.var_label != NULL);
1858       if (show & SETTINGS_VALUE_SHOW_VALUE)
1859         ds_put_cstr (out, value->variable.var_name);
1860       if (show & SETTINGS_VALUE_SHOW_LABEL)
1861         {
1862           if (show & SETTINGS_VALUE_SHOW_VALUE)
1863             ds_put_byte (out, ' ');
1864           ds_put_cstr (out, value->variable.var_label);
1865         }
1866       break;
1867
1868     case PIVOT_VALUE_TEXT:
1869       ds_put_cstr (out, value->text.local);
1870       break;
1871
1872     case PIVOT_VALUE_TEMPLATE:
1873       pivot_format_template (out, value->template.local, value->template.args,
1874                              value->template.n_args, show_values,
1875                              show_variables);
1876       break;
1877     }
1878
1879   return numeric;
1880 }
1881
1882 /* Appends a text representation of VALUE to OUT.  SHOW_VALUES and
1883    SHOW_VARIABLES control whether variable and value labels are included.
1884
1885    Subscripts and superscripts and footnotes are included. */
1886 void
1887 pivot_value_format (const struct pivot_value *value,
1888                     enum settings_value_show show_values,
1889                     enum settings_value_show show_variables,
1890                     struct string *out)
1891 {
1892   pivot_value_format_body ( value, show_values, show_variables, out);
1893
1894   if (value->n_subscripts)
1895     {
1896       for (size_t i = 0; i < value->n_subscripts; i++)
1897         ds_put_format (out, "%c%s", i ? ',' : '_', value->subscripts[i]);
1898     }
1899
1900   if (value->superscript)
1901     ds_put_format (out, "^%s", value->superscript);
1902
1903   for (size_t i = 0; i < value->n_footnotes; i++)
1904     {
1905       ds_put_byte (out, '^');
1906       pivot_value_format (value->footnotes[i]->marker,
1907                           show_values, show_variables, out);
1908     }
1909 }
1910
1911 /* Returns a text representation of VALUE.  The caller must free the string,
1912    with free(). */
1913 char *
1914 pivot_value_to_string (const struct pivot_value *value,
1915                        enum settings_value_show show_values,
1916                        enum settings_value_show show_variables)
1917 {
1918   struct string s = DS_EMPTY_INITIALIZER;
1919   pivot_value_format (value, show_values, show_variables, &s);
1920   return ds_steal_cstr (&s);
1921 }
1922
1923 /* Frees the data owned by V. */
1924 void
1925 pivot_value_destroy (struct pivot_value *value)
1926 {
1927   if (value)
1928     {
1929       font_style_uninit (value->font_style);
1930       free (value->font_style);
1931       free (value->cell_style);
1932       /* Do not free the elements of footnotes because VALUE does not own
1933          them. */
1934       free (value->footnotes);
1935
1936       for (size_t i = 0; i < value->n_subscripts; i++)
1937         free (value->subscripts[i]);
1938       free (value->subscripts);
1939
1940       free (value->superscript);
1941
1942       switch (value->type)
1943         {
1944         case PIVOT_VALUE_NUMERIC:
1945           free (value->numeric.var_name);
1946           free (value->numeric.value_label);
1947           break;
1948
1949         case PIVOT_VALUE_STRING:
1950           free (value->string.s);
1951           free (value->string.var_name);
1952           free (value->string.value_label);
1953           break;
1954
1955         case PIVOT_VALUE_VARIABLE:
1956           free (value->variable.var_name);
1957           free (value->variable.var_label);
1958           break;
1959
1960         case PIVOT_VALUE_TEXT:
1961           free (value->text.local);
1962           if (value->text.c != value->text.local)
1963             free (value->text.c);
1964           if (value->text.id != value->text.local
1965               && value->text.id != value->text.c)
1966             free (value->text.id);
1967           break;
1968
1969         case PIVOT_VALUE_TEMPLATE:
1970           free (value->template.local);
1971           if (value->template.id != value->template.local)
1972             free (value->template.id);
1973           for (size_t i = 0; i < value->template.n_args; i++)
1974             pivot_argument_uninit (&value->template.args[i]);
1975           free (value->template.args);
1976           break;
1977         }
1978       free (value);
1979     }
1980 }
1981
1982 /* Sets AREA to the style to use for VALUE, with defaults coming from
1983    DEFAULT_STYLE for the parts of the style that VALUE doesn't override. */
1984 void
1985 pivot_value_get_style (struct pivot_value *value,
1986                        const struct font_style *base_font_style,
1987                        const struct cell_style *base_cell_style,
1988                        struct area_style *area)
1989 {
1990   font_style_copy (NULL, &area->font_style, (value->font_style
1991                                              ? value->font_style
1992                                              : base_font_style));
1993   area->cell_style = *(value->cell_style
1994                        ? value->cell_style
1995                        : base_cell_style);
1996 }
1997
1998 /* Copies AREA into VALUE's style. */
1999 void
2000 pivot_value_set_style (struct pivot_value *value,
2001                        const struct area_style *area)
2002 {
2003   if (value->font_style)
2004     font_style_uninit (value->font_style);
2005   else
2006     value->font_style = xmalloc (sizeof *value->font_style);
2007   font_style_copy (NULL, value->font_style, &area->font_style);
2008
2009   if (!value->cell_style)
2010     value->cell_style = xmalloc (sizeof *value->cell_style);
2011   *value->cell_style = area->cell_style;
2012 }
2013
2014 /* Frees the data owned by ARG (but not ARG itself). */
2015 void
2016 pivot_argument_uninit (struct pivot_argument *arg)
2017 {
2018   if (arg)
2019     {
2020       for (size_t i = 0; i < arg->n; i++)
2021         pivot_value_destroy (arg->values[i]);
2022       free (arg->values);
2023     }
2024 }
2025
2026 /* Creates and returns a new pivot_value whose contents is the null-terminated
2027    string TEXT.  Takes ownership of TEXT.
2028
2029    This function is for text strings provided by the user (with the exception
2030    that pivot_value_new_variable() should be used for variable names).  For
2031    strings that are part of the PSPP user interface, such as names of
2032    procedures, statistics, annotations, error messages, etc., use
2033    pivot_value_new_text(). */
2034 struct pivot_value *
2035 pivot_value_new_user_text_nocopy (char *text)
2036 {
2037   struct pivot_value *value = xmalloc (sizeof *value);
2038   *value = (struct pivot_value) {
2039     .type = PIVOT_VALUE_TEXT,
2040     .text = {
2041       .local = text,
2042       .c = text,
2043       .id = text,
2044       .user_provided = true,
2045     }
2046   };
2047   return value;
2048 }
2049
2050 /* Creates and returns a new pivot_value whose contents is the LENGTH bytes of
2051    TEXT.  Use SIZE_MAX if TEXT is null-teriminated and its length is not known
2052    in advance.
2053
2054    This function is for text strings provided by the user (with the exception
2055    that pivot_value_new_variable() should be used for variable names).  For
2056    strings that are part of the PSPP user interface, such as names of
2057    procedures, statistics, annotations, error messages, etc., use
2058    pivot_value_new_text().j
2059
2060    The caller retains ownership of TEXT.*/
2061 struct pivot_value *
2062 pivot_value_new_user_text (const char *text, size_t length)
2063 {
2064   return pivot_value_new_user_text_nocopy (
2065     xmemdup0 (text, length != SIZE_MAX ? length : strlen (text)));
2066 }
2067
2068 /* Creates and returns new pivot_value whose contents is TEXT, which should be
2069    a translatable string, but not actually translated yet, e.g. enclosed in
2070    N_().  This function is for text strings that are part of the PSPP user
2071    interface, such as names of procedures, statistics, annotations, error
2072    messages, etc.  For strings that come from the user, use
2073    pivot_value_new_user_text(). */
2074 struct pivot_value *
2075 pivot_value_new_text (const char *text)
2076 {
2077   char *c = xstrdup (text);
2078   char *local = xstrdup (gettext (c));
2079
2080   struct pivot_value *value = xmalloc (sizeof *value);
2081   *value = (struct pivot_value) {
2082     .type = PIVOT_VALUE_TEXT,
2083     .text = {
2084       .local = local,
2085       .c = c,
2086       .id = c,
2087       .user_provided = false,
2088     }
2089   };
2090   return value;
2091 }
2092
2093 /* Same as pivot_value_new_text() but its argument is a printf()-like format
2094    string. */
2095 struct pivot_value * PRINTF_FORMAT (1, 2)
2096 pivot_value_new_text_format (const char *format, ...)
2097 {
2098   va_list args;
2099   va_start (args, format);
2100   char *c = xvasprintf (format, args);
2101   va_end (args);
2102
2103   va_start (args, format);
2104   char *local = xvasprintf (gettext (format), args);
2105   va_end (args);
2106
2107   struct pivot_value *value = xmalloc (sizeof *value);
2108   *value = (struct pivot_value) {
2109     .type = PIVOT_VALUE_TEXT,
2110     .text = {
2111       .local = local,
2112       .c = c,
2113       .id = xstrdup (c),
2114       .user_provided = false,
2115     }
2116   };
2117   return value;
2118 }
2119
2120 static char *
2121 xstrdup_if_nonempty (const char *s)
2122 {
2123   return s && s[0] ? xstrdup (s) : NULL;
2124 }
2125
2126 /* Returns a new pivot_value that represents X.
2127
2128    The format to use for X is unspecified.  Usually the easiest way to specify
2129    a format is through assigning a result class to one of the categories that
2130    the pivot_value will end up in.  If that is not suitable, then the caller
2131    can use pivot_value_set_rc() or assign directly to value->numeric.format. */
2132 struct pivot_value *
2133 pivot_value_new_number (double x)
2134 {
2135   struct pivot_value *value = xmalloc (sizeof *value);
2136   *value = (struct pivot_value) {
2137     .type = PIVOT_VALUE_NUMERIC,
2138     .numeric = { .x = x, },
2139   };
2140   return value;
2141 }
2142
2143 /* Returns a new pivot_value that represents X, formatted as an integer. */
2144 struct pivot_value *
2145 pivot_value_new_integer (double x)
2146 {
2147   struct pivot_value *value = pivot_value_new_number (x);
2148   value->numeric.format = (struct fmt_spec) { FMT_F, 40, 0 };
2149   return value;
2150 }
2151
2152 /* Returns a new pivot_value that represents VALUE, formatted as for
2153    VARIABLE. */
2154 struct pivot_value *
2155 pivot_value_new_var_value (const struct variable *variable,
2156                            const union value *value)
2157 {
2158   struct pivot_value *pv = pivot_value_new_value (
2159     value, var_get_width (variable), var_get_print_format (variable),
2160     var_get_encoding (variable));
2161
2162   char *var_name = xstrdup (var_get_name (variable));
2163   if (var_is_alpha (variable))
2164     pv->string.var_name = var_name;
2165   else
2166     pv->numeric.var_name = var_name;
2167
2168   const char *label = var_lookup_value_label (variable, value);
2169   if (label)
2170     {
2171       if (var_is_alpha (variable))
2172         pv->string.value_label = xstrdup (label);
2173       else
2174         pv->numeric.value_label = xstrdup (label);
2175     }
2176
2177   return pv;
2178 }
2179
2180 /* Returns a new pivot_value that represents VALUE, with the given WIDTH,
2181    formatted with FORMAT.  For a string value, ENCODING must be its character
2182    encoding. */
2183 struct pivot_value *
2184 pivot_value_new_value (const union value *value, int width,
2185                        const struct fmt_spec *format, const char *encoding)
2186 {
2187   struct pivot_value *pv = xzalloc (sizeof *pv);
2188   if (width > 0)
2189     {
2190       char *s = recode_string (UTF8, encoding, CHAR_CAST (char *, value->s),
2191                                width);
2192       size_t n = strlen (s);
2193       while (n > 0 && s[n - 1] == ' ')
2194         s[--n] = '\0';
2195
2196       pv->type = PIVOT_VALUE_STRING;
2197       pv->string.s = s;
2198       pv->string.hex = format->type == FMT_AHEX;
2199     }
2200   else
2201     {
2202       pv->type = PIVOT_VALUE_NUMERIC;
2203       pv->numeric.x = value->f;
2204       pv->numeric.format = *format;
2205     }
2206
2207   return pv;
2208 }
2209
2210 /* Returns a new pivot_value for VARIABLE. */
2211 struct pivot_value *
2212 pivot_value_new_variable (const struct variable *variable)
2213 {
2214   struct pivot_value *value = xmalloc (sizeof *value);
2215   *value = (struct pivot_value) {
2216     .type = PIVOT_VALUE_VARIABLE,
2217     .variable = {
2218       .var_name = xstrdup (var_get_name (variable)),
2219       .var_label = xstrdup_if_nonempty (var_get_label (variable)),
2220     },
2221   };
2222   return value;
2223 }
2224
2225 /* Attaches a reference to FOOTNOTE to V. */
2226 void
2227 pivot_value_add_footnote (struct pivot_value *v,
2228                           const struct pivot_footnote *footnote)
2229 {
2230   /* Some legacy tables include numerous duplicate footnotes.  Suppress
2231      them. */
2232   for (size_t i = 0; i < v->n_footnotes; i++)
2233     if (v->footnotes[i] == footnote)
2234       return;
2235
2236   v->footnotes = xrealloc (v->footnotes,
2237                            (v->n_footnotes + 1) * sizeof *v->footnotes);
2238   v->footnotes[v->n_footnotes++] = footnote;
2239 }
2240
2241 /* If VALUE is a numeric value, and RC is a result class such as
2242    PIVOT_RC_COUNT, changes VALUE's format to the result class's. */
2243 void
2244 pivot_value_set_rc (const struct pivot_table *table, struct pivot_value *value,
2245                     const char *rc)
2246 {
2247   if (value->type == PIVOT_VALUE_NUMERIC)
2248     {
2249       const struct fmt_spec *f = pivot_table_get_format (table, rc);
2250       if (f)
2251         value->numeric.format = *f;
2252     }
2253 }
2254