output: Introduce pivot tables.
[pspp] / src / output / table.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009, 2011, 2014, 2016 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/table.h"
20 #include "output/table-provider.h"
21
22 #include <assert.h>
23 #include <inttypes.h>
24 #include <stdlib.h>
25
26 #include "data/format.h"
27 #include "libpspp/assertion.h"
28 #include "libpspp/cast.h"
29 #include "libpspp/compiler.h"
30 #include "libpspp/pool.h"
31 #include "libpspp/str.h"
32 #include "output/table-item.h"
33
34 #include "gl/xalloc.h"
35
36 /* Increases TABLE's reference count, indicating that it has an additional
37    owner.  An table that is shared among multiple owners must not be
38    modified. */
39 struct table *
40 table_ref (const struct table *table_)
41 {
42   struct table *table = CONST_CAST (struct table *, table_);
43   table->ref_cnt++;
44   return table;
45 }
46
47 /* Decreases TABLE's reference count, indicating that it has one fewer owner.
48    If TABLE no longer has any owners, it is freed. */
49 void
50 table_unref (struct table *table)
51 {
52   if (table != NULL)
53     {
54       assert (table->ref_cnt > 0);
55       if (--table->ref_cnt == 0)
56         table->klass->destroy (table);
57     }
58 }
59
60 /* Returns true if TABLE has more than one owner.  A table item that is shared
61    among multiple owners must not be modified. */
62 bool
63 table_is_shared (const struct table *table)
64 {
65   return table->ref_cnt > 1;
66 }
67
68 /* Sets the number of left header columns in TABLE to HL. */
69 void
70 table_set_hl (struct table *table, int hl)
71 {
72   assert (!table_is_shared (table));
73   table->h[TABLE_HORZ][0] = hl;
74 }
75
76 /* Sets the number of right header columns in TABLE to HR. */
77 void
78 table_set_hr (struct table *table, int hr)
79 {
80   assert (!table_is_shared (table));
81   table->h[TABLE_HORZ][1] = hr;
82 }
83
84 /* Sets the number of top header rows in TABLE to HT. */
85 void
86 table_set_ht (struct table *table, int ht)
87 {
88   assert (!table_is_shared (table));
89   table->h[TABLE_VERT][0] = ht;
90 }
91
92 /* Sets the number of top header rows in TABLE to HB. */
93 void
94 table_set_hb (struct table *table, int hb)
95 {
96   assert (!table_is_shared (table));
97   table->h[TABLE_VERT][1] = hb;
98 }
99 \f
100 /* Initializes TABLE as a table of the specified CLASS, initially with a
101    reference count of 1.
102
103    TABLE initially has 0 rows and columns and no headers.  The table
104    implementation should update the numbers of rows and columns.  The table
105    implementation (or its client) may update the header rows and columns.
106
107    A table is an abstract class, that is, a plain struct table is not useful on
108    its own.  Thus, this function is normally called from the initialization
109    function of some subclass of table. */
110 void
111 table_init (struct table *table, const struct table_class *class)
112 {
113   table->klass = class;
114   table->n[TABLE_HORZ] = table->n[TABLE_VERT] = 0;
115   table->h[TABLE_HORZ][0] = table->h[TABLE_HORZ][1] = 0;
116   table->h[TABLE_VERT][0] = table->h[TABLE_VERT][1] = 0;
117   table->ref_cnt = 1;
118 }
119
120 /* Sets the number of columns in TABLE to NC. */
121 void
122 table_set_nc (struct table *table, int nc)
123 {
124   assert (!table_is_shared (table));
125   table->n[TABLE_HORZ] = nc;
126 }
127
128 /* Sets the number of rows in TABLE to NR. */
129 void
130 table_set_nr (struct table *table, int nr)
131 {
132   assert (!table_is_shared (table));
133   table->n[TABLE_VERT] = nr;
134 }
135 \f
136 struct area_style *
137 area_style_clone (struct pool *pool, const struct area_style *old)
138 {
139   struct area_style *new = pool_malloc (pool, sizeof *new);
140   *new = *old;
141   if (new->font_style.typeface)
142     new->font_style.typeface = pool_strdup (pool, new->font_style.typeface);
143   return new;
144 }
145
146 void
147 area_style_free (struct area_style *style)
148 {
149   if (style)
150     {
151       free (style->font_style.typeface);
152       free (style);
153     }
154 }
155
156 /* Initializes CELL with the contents of the table cell at column X and row Y
157    within TABLE.  When CELL is no longer needed, the caller is responsible for
158    freeing it by calling table_cell_free(CELL).
159
160    The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
161 void
162 table_get_cell (const struct table *table, int x, int y,
163                 struct table_cell *cell)
164 {
165   assert (x >= 0 && x < table->n[TABLE_HORZ]);
166   assert (y >= 0 && y < table->n[TABLE_VERT]);
167
168   static const struct area_style default_style = AREA_STYLE_INITIALIZER;
169   cell->style = &default_style;
170
171   table->klass->get_cell (table, x, y, cell);
172 }
173
174 /* Frees CELL, which should have been initialized by calling
175    table_get_cell(). */
176 void
177 table_cell_free (struct table_cell *cell)
178 {
179   if (cell->destructor != NULL)
180     cell->destructor (cell->destructor_aux);
181 }
182
183 /* Returns one of the TAL_* enumeration constants (declared in output/table.h)
184    representing a rule running alongside one of the cells in TABLE.
185
186    Suppose NC is the number of columns in TABLE and NR is the number of rows.
187    Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR.  If (X,Y) =
188    (0,0), the return value is the rule that runs vertically on the left side of
189    cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
190    cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
191    cell (NC-1,0).
192
193    The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
194    within a 7x7 table.  The '|' characters at the intersection of the X labels
195    and Y labels show the rule whose style would be returned by calling
196    table_get_rule with those X and Y values:
197
198                            0  1  2  3  4  5  6  7
199                            +--+--+--+--+--+--+--+
200                          0 |  |  |  |  |  |  |  |
201                            +--+--+--+--+--+--+--+
202                          1 |  |  |  |  |  |  |  |
203                            +--+--+--+--+--+--+--+
204                          2 |  |  |  |  |  |  |  |
205                            +--+--+--+--+--+--+--+
206                          3 |  |  |  |  |  |  |  |
207                            +--+--+--+--+--+--+--+
208                          4 |  |  |  |  |  |  |  |
209                            +--+--+--+--+--+--+--+
210                          5 |  |  |  |  |  |  |  |
211                            +--+--+--+--+--+--+--+
212                          6 |  |  |  |  |  |  |  |
213                            +--+--+--+--+--+--+--+
214
215    Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR.  If
216    (X,Y) = (0,0), the return value is the rule that runs horizontally above
217    the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
218    between that cell and cell (0,1); and so on, up to (0,NR), which runs
219    horizontally below cell (0,NR-1). */
220 int
221 table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
222                 struct cell_color *color)
223 {
224   assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
225   assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
226   *color = (struct cell_color) CELL_COLOR_BLACK;
227   return table->klass->get_rule (table, axis, x, y, color);
228 }
229
230 void
231 table_cell_format_footnote_markers (const struct table_cell *cell,
232                                     struct string *s)
233 {
234   for (size_t i = 0; i < cell->n_footnotes; i++)
235     {
236       if (i)
237         ds_put_byte (s, ',');
238       ds_put_cstr (s, cell->footnotes[i]->marker);
239     }
240 }
241
242 static const struct footnote **
243 add_footnotes (const struct footnote **refs, size_t n_refs,
244                const struct footnote **footnotes, size_t *allocated, size_t *n)
245 {
246   for (size_t i = 0; i < n_refs; i++)
247     {
248       const struct footnote *f = refs[i];
249       if (f->idx >= *allocated)
250         {
251           size_t new_allocated = (f->idx + 1) * 2;
252           footnotes = xrealloc (footnotes, new_allocated * sizeof *footnotes);
253           while (*allocated < new_allocated)
254             footnotes[(*allocated)++] = NULL;
255         }
256       footnotes[f->idx] = f;
257       if (f->idx >= *n)
258         *n = f->idx + 1;
259     }
260   return footnotes;
261 }
262
263 size_t
264 table_collect_footnotes (const struct table_item *item,
265                          const struct footnote ***footnotesp)
266 {
267   const struct footnote **footnotes = NULL;
268   size_t allocated = 0;
269   size_t n = 0;
270
271   struct table *t = item->table;
272   for (int y = 0; y < table_nr (t); y++)
273     {
274       struct table_cell cell;
275       for (int x = 0; x < table_nc (t); x = cell.d[TABLE_HORZ][1])
276         {
277           table_get_cell (t, x, y, &cell);
278
279           if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
280             footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
281                                        footnotes, &allocated, &n);
282           table_cell_free (&cell);
283         }
284     }
285
286   const struct table_item_text *title = table_item_get_title (item);
287   if (title)
288     footnotes = add_footnotes (title->footnotes, title->n_footnotes,
289                                footnotes, &allocated, &n);
290
291   const struct table_item_text *caption = table_item_get_caption (item);
292   if (caption)
293     footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
294                                footnotes, &allocated, &n);
295
296   *footnotesp = footnotes;
297   return n;
298 }
299 \f
300 struct table_unshared
301   {
302     struct table table;
303     struct table *subtable;
304   };
305
306 static const struct table_class table_unshared_class;
307
308 /* Takes ownership of TABLE and returns a table with the same contents but
309    which is guaranteed not to be shared (as returned by table_is_shared()).
310
311    If TABLE is unshared, just returns TABLE.
312
313    The only real use for this function is to create a copy of TABLE in which
314    the headers can be adjusted, which is a pretty specialized use case. */
315 struct table *
316 table_unshare (struct table *table)
317 {
318   if (!table_is_shared (table))
319     return table;
320   else
321     {
322       struct table_unshared *tiu = xmalloc (sizeof *tiu);
323       table_init (&tiu->table, &table_unshared_class);
324       table_set_nc (&tiu->table, table_nc (table));
325       table_set_nr (&tiu->table, table_nr (table));
326       table_set_hl (&tiu->table, table_hl (table));
327       table_set_hr (&tiu->table, table_hr (table));
328       table_set_ht (&tiu->table, table_ht (table));
329       table_set_hb (&tiu->table, table_hb (table));
330       tiu->subtable = table;
331       return &tiu->table;
332     }
333 }
334
335 static struct table_unshared *
336 table_unshared_cast (const struct table *table)
337 {
338   assert (table->klass == &table_unshared_class);
339   return UP_CAST (table, struct table_unshared, table);
340 }
341
342 static void
343 table_unshared_destroy (struct table *tiu_)
344 {
345   struct table_unshared *tiu = table_unshared_cast (tiu_);
346   table_unref (tiu->subtable);
347   free (tiu);
348 }
349
350 static void
351 table_unshared_get_cell (const struct table *tiu_, int x, int y,
352                               struct table_cell *cell)
353 {
354   struct table_unshared *tiu = table_unshared_cast (tiu_);
355   table_get_cell (tiu->subtable, x, y, cell);
356 }
357
358 static int
359 table_unshared_get_rule (const struct table *tiu_,
360                          enum table_axis axis, int x, int y,
361                          struct cell_color *color)
362 {
363   struct table_unshared *tiu = table_unshared_cast (tiu_);
364   return table_get_rule (tiu->subtable, axis, x, y, color);
365 }
366
367 static const struct table_class table_unshared_class =
368   {
369     table_unshared_destroy,
370     table_unshared_get_cell,
371     table_unshared_get_rule,
372     NULL,                       /* paste */
373     NULL,                       /* select */
374   };
375 \f
376 struct table_string
377   {
378     struct table table;
379     char *string;
380     enum table_halign halign;
381   };
382
383 static const struct table_class table_string_class;
384
385 /* Returns a table that contains a single cell, whose contents are S with
386    options OPTIONS (a combination of TAB_* values).  */
387 struct table *
388 table_from_string (enum table_halign halign, const char *s)
389 {
390   struct table_string *ts = xmalloc (sizeof *ts);
391   table_init (&ts->table, &table_string_class);
392   ts->table.n[TABLE_HORZ] = ts->table.n[TABLE_VERT] = 1;
393   ts->string = xstrdup (s);
394   ts->halign = halign;
395   return &ts->table;
396 }
397
398 static struct table_string *
399 table_string_cast (const struct table *table)
400 {
401   assert (table->klass == &table_string_class);
402   return UP_CAST (table, struct table_string, table);
403 }
404
405 static void
406 table_string_destroy (struct table *ts_)
407 {
408   struct table_string *ts = table_string_cast (ts_);
409   free (ts->string);
410   free (ts);
411 }
412
413 static void
414 table_string_get_cell (const struct table *ts_, int x UNUSED, int y UNUSED,
415                        struct table_cell *cell)
416 {
417   static const struct area_style styles[] = {
418 #define S(H) [H] = { AREA_STYLE_INITIALIZER__, .cell_style.halign = H }
419     S(TABLE_HALIGN_LEFT),
420     S(TABLE_HALIGN_CENTER),
421     S(TABLE_HALIGN_RIGHT),
422     S(TABLE_HALIGN_MIXED),
423     S(TABLE_HALIGN_DECIMAL),
424   };
425   struct table_string *ts = table_string_cast (ts_);
426   cell->d[TABLE_HORZ][0] = 0;
427   cell->d[TABLE_HORZ][1] = 1;
428   cell->d[TABLE_VERT][0] = 0;
429   cell->d[TABLE_VERT][1] = 1;
430   cell->options = 0;
431   cell->style = &styles[table_halign_interpret (ts->halign, false)];
432   cell->text = ts->string;
433   cell->n_footnotes = 0;
434   cell->destructor = NULL;
435 }
436
437
438 static int
439 table_string_get_rule (const struct table *ts UNUSED,
440                        enum table_axis axis UNUSED, int x UNUSED, int y UNUSED,
441                        struct cell_color *color UNUSED)
442 {
443   return TAL_0;
444 }
445
446 static const struct table_class table_string_class =
447   {
448     table_string_destroy,
449     table_string_get_cell,
450     table_string_get_rule,
451     NULL,                       /* paste */
452     NULL,                       /* select */
453   };
454 \f
455 const char *
456 table_halign_to_string (enum table_halign halign)
457 {
458   switch (halign)
459     {
460     case TABLE_HALIGN_LEFT: return "left";
461     case TABLE_HALIGN_CENTER: return "center";
462     case TABLE_HALIGN_RIGHT: return "right";
463     case TABLE_HALIGN_DECIMAL: return "decimal";
464     case TABLE_HALIGN_MIXED: return "mixed";
465     default: return "**error**";
466     }
467 }
468
469 const char *
470 table_valign_to_string (enum table_valign valign)
471 {
472   switch (valign)
473     {
474     case TABLE_VALIGN_TOP: return "top";
475     case TABLE_VALIGN_CENTER: return "center";
476     case TABLE_VALIGN_BOTTOM: return "bottom";
477     default: return "**error**";
478     }
479 }
480
481 enum table_halign
482 table_halign_interpret (enum table_halign halign, bool numeric)
483 {
484   switch (halign)
485     {
486     case TABLE_HALIGN_LEFT:
487     case TABLE_HALIGN_CENTER:
488     case TABLE_HALIGN_RIGHT:
489       return halign;
490
491     case TABLE_HALIGN_MIXED:
492       return numeric ? TABLE_HALIGN_RIGHT : TABLE_HALIGN_LEFT;
493
494     case TABLE_HALIGN_DECIMAL:
495       return TABLE_HALIGN_DECIMAL;
496
497     default:
498       NOT_REACHED ();
499     }
500 }
501
502 void
503 font_style_copy (struct font_style *dst, const struct font_style *src)
504 {
505   *dst = *src;
506   if (dst->typeface)
507     dst->typeface = xstrdup (dst->typeface);
508 }
509
510 void
511 font_style_uninit (struct font_style *font)
512 {
513   if (font)
514     free (font->typeface);
515 }
516
517 void
518 area_style_copy (struct area_style *dst, const struct area_style *src)
519 {
520   font_style_copy (&dst->font_style, &src->font_style);
521   dst->cell_style = src->cell_style;
522 }
523
524 void
525 area_style_uninit (struct area_style *area)
526 {
527   if (area)
528     font_style_uninit (&area->font_style);
529 }
530
531 const char *
532 table_stroke_to_string (enum table_stroke stroke)
533 {
534   switch (stroke)
535     {
536     case TABLE_STROKE_NONE: return "none";
537     case TABLE_STROKE_SOLID: return "solid";
538     case TABLE_STROKE_DASHED: return "dashed";
539     case TABLE_STROKE_THICK: return "thick";
540     case TABLE_STROKE_THIN: return "thin";
541     case TABLE_STROKE_DOUBLE: return "double";
542     default:
543       return "**error**";
544     }
545 }
546
547 void
548 cell_color_dump (const struct cell_color *c)
549 {
550   if (c->alpha != 255)
551     printf ("rgba(%d, %d, %d, %d)", c->r, c->g, c->b, c->alpha);
552   else
553     printf ("#%02"PRIx8"%02"PRIx8"%02"PRIx8, c->r, c->g, c->b);
554 }
555
556 void
557 font_style_dump (const struct font_style *f)
558 {
559   printf ("%s %dpx ", f->typeface, f->size);
560   cell_color_dump (&f->fg[0]);
561   putchar ('/');
562   cell_color_dump (&f->bg[0]);
563   if (!cell_color_equal (&f->fg[0], &f->fg[1])
564       || !cell_color_equal (&f->bg[0], &f->bg[1]))
565     {
566       printf (" alt=");
567       cell_color_dump (&f->fg[1]);
568       putchar ('/');
569       cell_color_dump (&f->bg[1]);
570     }
571   if (f->bold)
572     fputs (" bold", stdout);
573   if (f->italic)
574     fputs (" italic", stdout);
575   if (f->underline)
576     fputs (" underline", stdout);
577 }
578
579 void
580 cell_style_dump (const struct cell_style *c)
581 {
582   fputs (table_halign_to_string (c->halign), stdout);
583   if (c->halign == TABLE_HALIGN_DECIMAL)
584     printf ("(%.2gpx)", c->decimal_offset);
585   printf (" %s", table_valign_to_string (c->valign));
586   printf (" %d,%d,%d,%dpx",
587           c->margin[TABLE_HORZ][0], c->margin[TABLE_HORZ][1],
588           c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);
589 }