1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2009, 2011, 2014, 2016 Free Software Foundation, Inc.
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.
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.
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/>. */
19 #include "output/table.h"
20 #include "output/table-provider.h"
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 #include "output/table.h"
34 #include "output/text-item.h"
36 #include "gl/xalloc.h"
38 /* Increases TABLE's reference count, indicating that it has an additional
39 owner. An table that is shared among multiple owners must not be
42 table_ref (const struct table *table_)
44 struct table *table = CONST_CAST (struct table *, table_);
49 /* Decreases TABLE's reference count, indicating that it has one fewer owner.
50 If TABLE no longer has any owners, it is freed. */
52 table_unref (struct table *table)
56 assert (table->ref_cnt > 0);
57 if (--table->ref_cnt == 0)
58 pool_destroy (table->container);
62 /* Returns true if TABLE has more than one owner. A table item that is shared
63 among multiple owners must not be modified. */
65 table_is_shared (const struct table *table)
67 return table->ref_cnt > 1;
71 area_style_clone (struct pool *pool, const struct area_style *old)
73 struct area_style *new = pool_malloc (pool, sizeof *new);
75 if (new->font_style.typeface)
76 new->font_style.typeface = pool_strdup (pool, new->font_style.typeface);
81 area_style_free (struct area_style *style)
85 free (style->font_style.typeface);
91 table_cell_format_footnote_markers (const struct table_cell *cell,
94 for (size_t i = 0; i < cell->n_footnotes; i++)
98 ds_put_cstr (s, cell->footnotes[i]->marker);
102 static const struct footnote **
103 add_footnotes (const struct footnote **refs, size_t n_refs,
104 const struct footnote **footnotes, size_t *allocated, size_t *n)
106 for (size_t i = 0; i < n_refs; i++)
108 const struct footnote *f = refs[i];
109 if (f->idx >= *allocated)
111 size_t new_allocated = (f->idx + 1) * 2;
112 footnotes = xrealloc (footnotes, new_allocated * sizeof *footnotes);
113 while (*allocated < new_allocated)
114 footnotes[(*allocated)++] = NULL;
116 footnotes[f->idx] = f;
124 table_collect_footnotes (const struct table_item *item,
125 const struct footnote ***footnotesp)
127 const struct footnote **footnotes = NULL;
128 size_t allocated = 0;
131 struct table *t = item->table;
132 for (int y = 0; y < table_nr (t); y++)
134 struct table_cell cell;
135 for (int x = 0; x < table_nc (t); x = cell.d[TABLE_HORZ][1])
137 table_get_cell (t, x, y, &cell);
139 if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
140 footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
141 footnotes, &allocated, &n);
145 const struct table_item_text *title = table_item_get_title (item);
147 footnotes = add_footnotes (title->footnotes, title->n_footnotes,
148 footnotes, &allocated, &n);
150 const struct table_item_layers *layers = table_item_get_layers (item);
153 for (size_t i = 0; i < layers->n_layers; i++)
154 footnotes = add_footnotes (layers->layers[i].footnotes,
155 layers->layers[i].n_footnotes,
156 footnotes, &allocated, &n);
159 const struct table_item_text *caption = table_item_get_caption (item);
161 footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
162 footnotes, &allocated, &n);
164 size_t n_nonnull = 0;
165 for (size_t i = 0; i < n; i++)
167 footnotes[n_nonnull++] = footnotes[i];
169 *footnotesp = footnotes;
173 /* Returns a table that contains a single cell, whose contents are the
174 left-aligned TEXT. */
176 table_from_string (const char *text)
178 struct table *t = table_create (1, 1, 0, 0, 0, 0);
179 table_text (t, 0, 0, TAB_LEFT, text);
184 table_halign_to_string (enum table_halign halign)
188 case TABLE_HALIGN_LEFT: return "left";
189 case TABLE_HALIGN_CENTER: return "center";
190 case TABLE_HALIGN_RIGHT: return "right";
191 case TABLE_HALIGN_DECIMAL: return "decimal";
192 case TABLE_HALIGN_MIXED: return "mixed";
193 default: return "**error**";
198 table_valign_to_string (enum table_valign valign)
202 case TABLE_VALIGN_TOP: return "top";
203 case TABLE_VALIGN_CENTER: return "center";
204 case TABLE_VALIGN_BOTTOM: return "bottom";
205 default: return "**error**";
210 table_halign_interpret (enum table_halign halign, bool numeric)
214 case TABLE_HALIGN_LEFT:
215 case TABLE_HALIGN_CENTER:
216 case TABLE_HALIGN_RIGHT:
219 case TABLE_HALIGN_MIXED:
220 return numeric ? TABLE_HALIGN_RIGHT : TABLE_HALIGN_LEFT;
222 case TABLE_HALIGN_DECIMAL:
223 return TABLE_HALIGN_DECIMAL;
231 font_style_copy (struct pool *container,
232 struct font_style *dst, const struct font_style *src)
236 dst->typeface = pool_strdup (container, dst->typeface);
240 font_style_uninit (struct font_style *font)
243 free (font->typeface);
247 area_style_copy (struct pool *container,
248 struct area_style *dst, const struct area_style *src)
250 font_style_copy (container, &dst->font_style, &src->font_style);
251 dst->cell_style = src->cell_style;
255 area_style_uninit (struct area_style *area)
258 font_style_uninit (&area->font_style);
262 table_stroke_to_string (enum table_stroke stroke)
266 case TABLE_STROKE_NONE: return "none";
267 case TABLE_STROKE_SOLID: return "solid";
268 case TABLE_STROKE_DASHED: return "dashed";
269 case TABLE_STROKE_THICK: return "thick";
270 case TABLE_STROKE_THIN: return "thin";
271 case TABLE_STROKE_DOUBLE: return "double";
278 cell_color_dump (const struct cell_color *c)
281 printf ("rgba(%d, %d, %d, %d)", c->r, c->g, c->b, c->alpha);
283 printf ("#%02"PRIx8"%02"PRIx8"%02"PRIx8, c->r, c->g, c->b);
287 font_style_dump (const struct font_style *f)
289 printf ("%s %dpx ", f->typeface, f->size);
290 cell_color_dump (&f->fg[0]);
292 cell_color_dump (&f->bg[0]);
293 if (!cell_color_equal (&f->fg[0], &f->fg[1])
294 || !cell_color_equal (&f->bg[0], &f->bg[1]))
297 cell_color_dump (&f->fg[1]);
299 cell_color_dump (&f->bg[1]);
302 fputs (" bold", stdout);
304 fputs (" italic", stdout);
306 fputs (" underline", stdout);
310 cell_style_dump (const struct cell_style *c)
312 fputs (table_halign_to_string (c->halign), stdout);
313 if (c->halign == TABLE_HALIGN_DECIMAL)
314 printf ("(%.2gpx)", c->decimal_offset);
315 printf (" %s", table_valign_to_string (c->valign));
316 printf (" %d,%d,%d,%dpx",
317 c->margin[TABLE_HORZ][0], c->margin[TABLE_HORZ][1],
318 c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);
322 static const bool debugging = true;
325 struct table_joined_cell
327 int d[TABLE_N_AXES][2]; /* Table region, same as struct table_cell. */
331 const struct footnote **footnotes;
333 const struct area_style *style;
336 /* Creates and returns a new table with NC columns and NR rows and initially no
337 header rows or columns.
339 Sets the number of header rows on each side of TABLE to HL on the
340 left, HR on the right, HT on the top, HB on the bottom. Header rows
341 are repeated when a table is broken across multiple columns or
344 The table's cells are initially empty. */
346 table_create (int nc, int nr, int hl, int hr, int ht, int hb)
350 t = pool_create_container (struct table, container);
351 t->n[TABLE_HORZ] = nc;
352 t->n[TABLE_VERT] = nr;
353 t->h[TABLE_HORZ][0] = hl;
354 t->h[TABLE_HORZ][1] = hr;
355 t->h[TABLE_VERT][0] = ht;
356 t->h[TABLE_VERT][1] = hb;
359 t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
360 t->ct = pool_calloc (t->container, nr * nc, sizeof *t->ct);
362 t->rh = pool_nmalloc (t->container, nc, nr + 1);
363 memset (t->rh, TAL_0, nc * (nr + 1));
365 t->rv = pool_nmalloc (t->container, nr, nc + 1);
366 memset (t->rv, TAL_0, nr * (nc + 1));
368 memset (t->styles, 0, sizeof t->styles);
369 memset (t->rule_colors, 0, sizeof t->rule_colors);
376 /* Draws a vertical line to the left of cells at horizontal position X
377 from Y1 to Y2 inclusive in style STYLE, if style is not -1. */
379 table_vline (struct table *t, int style, int x, int y1, int y2)
383 if (x < 0 || x > table_nc (t)
384 || y1 < 0 || y1 >= table_nr (t)
385 || y2 < 0 || y2 >= table_nr (t))
387 printf ("bad vline: x=%d y=(%d,%d) in table size (%d,%d)\n",
388 x, y1, y2, table_nc (t), table_nr (t));
394 assert (x <= table_nc (t));
397 assert (y2 <= table_nr (t));
402 for (y = y1; y <= y2; y++)
403 t->rv[x + (table_nc (t) + 1) * y] = style;
407 /* Draws a horizontal line above cells at vertical position Y from X1
408 to X2 inclusive in style STYLE, if style is not -1. */
410 table_hline (struct table *t, int style, int x1, int x2, int y)
414 if (y < 0 || y > table_nr (t)
415 || x1 < 0 || x1 >= table_nc (t)
416 || x2 < 0 || x2 >= table_nc (t))
418 printf ("bad hline: x=(%d,%d) y=%d in table size (%d,%d)\n",
419 x1, x2, y, table_nc (t), table_nr (t));
425 assert (y <= table_nr (t));
428 assert (x2 < table_nc (t));
433 for (x = x1; x <= x2; x++)
434 t->rh[x + table_nc (t) * y] = style;
438 /* Draws a box around cells (X1,Y1)-(X2,Y2) inclusive with horizontal
439 lines of style F_H and vertical lines of style F_V. Fills the
440 interior of the box with horizontal lines of style I_H and vertical
441 lines of style I_V. Any of the line styles may be -1 to avoid
442 drawing those lines. This is distinct from 0, which draws a null
445 table_box (struct table *t, int f_h, int f_v, int i_h, int i_v,
446 int x1, int y1, int x2, int y2)
450 if (x1 < 0 || x1 >= table_nc (t)
451 || x2 < 0 || x2 >= table_nc (t)
452 || y1 < 0 || y1 >= table_nr (t)
453 || y2 < 0 || y2 >= table_nr (t))
455 printf ("bad box: (%d,%d)-(%d,%d) in table size (%d,%d)\n",
456 x1, y1, x2, y2, table_nc (t), table_nr (t));
465 assert (x2 < table_nc (t));
466 assert (y2 < table_nr (t));
471 for (x = x1; x <= x2; x++)
473 t->rh[x + table_nc (t) * y1] = f_h;
474 t->rh[x + table_nc (t) * (y2 + 1)] = f_h;
480 for (y = y1; y <= y2; y++)
482 t->rv[x1 + (table_nc (t) + 1) * y] = f_v;
483 t->rv[(x2 + 1) + (table_nc (t) + 1) * y] = f_v;
491 for (y = y1 + 1; y <= y2; y++)
495 for (x = x1; x <= x2; x++)
496 t->rh[x + table_nc (t) * y] = i_h;
503 for (x = x1 + 1; x <= x2; x++)
507 for (y = y1; y <= y2; y++)
508 t->rv[x + (table_nc (t) + 1) * y] = i_v;
516 do_table_text (struct table *table, int c, int r, unsigned opt, char *text)
520 assert (c < table_nc (table));
521 assert (r < table_nr (table));
525 if (c < 0 || r < 0 || c >= table_nc (table) || r >= table_nr (table))
527 printf ("table_text(): bad cell (%d,%d) in table size (%d,%d)\n",
528 c, r, table_nc (table), table_nr (table));
533 table->cc[c + r * table_nc (table)] = text;
534 table->ct[c + r * table_nc (table)] = opt;
537 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
540 table_text (struct table *table, int c, int r, unsigned opt,
543 do_table_text (table, c, r, opt, pool_strdup (table->container, text));
546 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
547 FORMAT, which is formatted as if passed to printf. */
549 table_text_format (struct table *table, int c, int r, unsigned opt,
550 const char *format, ...)
554 va_start (args, format);
555 do_table_text (table, c, r, opt,
556 pool_vasprintf (table->container, format, args));
560 static struct table_joined_cell *
561 add_joined_cell (struct table *table, int x1, int y1, int x2, int y2,
564 struct table_joined_cell *j;
570 assert (y2 < table_nr (table));
571 assert (x2 < table_nc (table));
575 if (x1 < 0 || x1 >= table_nc (table)
576 || y1 < 0 || y1 >= table_nr (table)
577 || x2 < x1 || x2 >= table_nc (table)
578 || y2 < y1 || y2 >= table_nr (table))
580 printf ("table_joint_text(): bad cell "
581 "(%d,%d)-(%d,%d) in table size (%d,%d)\n",
582 x1, y1, x2, y2, table_nc (table), table_nr (table));
587 table_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2);
589 j = pool_alloc (table->container, sizeof *j);
590 j->d[TABLE_HORZ][0] = x1;
591 j->d[TABLE_VERT][0] = y1;
592 j->d[TABLE_HORZ][1] = ++x2;
593 j->d[TABLE_VERT][1] = ++y2;
599 void **cc = &table->cc[x1 + y1 * table_nc (table)];
600 unsigned short *ct = &table->ct[x1 + y1 * table_nc (table)];
601 const int ofs = table_nc (table) - (x2 - x1);
605 for (y = y1; y < y2; y++)
609 for (x = x1; x < x2; x++)
612 *ct++ = opt | TAB_JOIN;
623 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
624 options OPT to have text value TEXT. */
626 table_joint_text (struct table *table, int x1, int y1, int x2, int y2,
627 unsigned opt, const char *text)
629 char *s = pool_strdup (table->container, text);
630 if (x1 == x2 && y1 == y2)
631 do_table_text (table, x1, y1, opt, s);
633 add_joined_cell (table, x1, y1, x2, y2, opt)->text = s;
637 table_create_footnote (struct table *table, size_t idx, const char *content,
638 const char *marker, struct area_style *style)
640 struct footnote *f = pool_alloc (table->container, sizeof *f);
642 f->content = pool_strdup (table->container, content);
643 f->marker = pool_strdup (table->container, marker);
649 table_add_footnote (struct table *table, int x, int y,
650 const struct footnote *f)
652 int index = x + y * table_nc (table);
653 unsigned short opt = table->ct[index];
654 struct table_joined_cell *j;
657 j = table->cc[index];
660 char *text = table->cc[index];
662 j = add_joined_cell (table, x, y, x, y, table->ct[index]);
663 j->text = text ? text : xstrdup ("");
666 j->footnotes = pool_realloc (table->container, j->footnotes,
667 (j->n_footnotes + 1) * sizeof *j->footnotes);
669 j->footnotes[j->n_footnotes++] = f;
673 table_add_style (struct table *table, int x, int y,
674 const struct area_style *style)
676 int index = x + y * table_nc (table);
677 unsigned short opt = table->ct[index];
678 struct table_joined_cell *j;
681 j = table->cc[index];
684 char *text = table->cc[index];
686 j = add_joined_cell (table, x, y, x, y, table->ct[index]);
687 j->text = text ? text : xstrdup ("");
694 table_cell_is_empty (const struct table *table, int c, int r)
696 return table->cc[c + r * table_nc (table)] == NULL;
701 /* Writes STRING to the output. OPTIONS may be any valid combination of TAB_*
704 This function is obsolete. Please do not add new uses of it. Instead, use
705 a text_item (see output/text-item.h). */
707 table_output_text (int options UNUSED, const char *string)
709 text_item_submit (text_item_create (TEXT_ITEM_LOG, string));
712 /* Same as table_output_text(), but FORMAT is passed through printf-like
713 formatting before output. */
715 table_output_text_format (int options, const char *format, ...)
720 va_start (args, format);
721 text = xvasprintf (format, args);
724 table_output_text (options, text);
729 /* Initializes CELL with the contents of the table cell at column X and row Y
730 within TABLE. When CELL is no longer needed, the caller is responsible for
731 freeing it by calling table_cell_free(CELL).
733 The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
735 table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
737 assert (x >= 0 && x < t->n[TABLE_HORZ]);
738 assert (y >= 0 && y < t->n[TABLE_VERT]);
740 int index = x + y * table_nc (t);
741 unsigned short opt = t->ct[index];
742 const void *cc = t->cc[index];
745 cell->n_footnotes = 0;
747 int style_idx = (opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT;
748 const struct area_style *style = t->styles[style_idx];
753 static const struct area_style styles[3][3] = {
754 #define S(H,V) [H][V] = { AREA_STYLE_INITIALIZER__, \
755 .cell_style.halign = H, \
756 .cell_style.valign = V }
757 S(TABLE_HALIGN_LEFT, TABLE_VALIGN_TOP),
758 S(TABLE_HALIGN_LEFT, TABLE_VALIGN_CENTER),
759 S(TABLE_HALIGN_LEFT, TABLE_VALIGN_BOTTOM),
760 S(TABLE_HALIGN_CENTER, TABLE_VALIGN_TOP),
761 S(TABLE_HALIGN_CENTER, TABLE_VALIGN_CENTER),
762 S(TABLE_HALIGN_CENTER, TABLE_VALIGN_BOTTOM),
763 S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_TOP),
764 S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_CENTER),
765 S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_BOTTOM),
768 enum table_halign halign
769 = ((opt & TAB_HALIGN) == TAB_LEFT ? TABLE_HALIGN_LEFT
770 : (opt & TAB_HALIGN) == TAB_CENTER ? TABLE_HALIGN_CENTER
771 : TABLE_HALIGN_RIGHT);
772 enum table_valign valign
773 = ((opt & TAB_VALIGN) == TAB_TOP ? TABLE_VALIGN_TOP
774 : (opt & TAB_VALIGN) == TAB_MIDDLE ? TABLE_VALIGN_CENTER
775 : TABLE_VALIGN_BOTTOM);
777 cell->style = &styles[halign][valign];
782 const struct table_joined_cell *jc = cc;
783 cell->text = jc->text;
785 cell->footnotes = jc->footnotes;
786 cell->n_footnotes = jc->n_footnotes;
788 cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
789 cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
790 cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0];
791 cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1];
794 cell->style = jc->style;
798 cell->d[TABLE_HORZ][0] = x;
799 cell->d[TABLE_HORZ][1] = x + 1;
800 cell->d[TABLE_VERT][0] = y;
801 cell->d[TABLE_VERT][1] = y + 1;
802 cell->text = CONST_CAST (char *, cc ? cc : "");
806 /* Returns one of the TAL_* enumeration constants (declared in output/table.h)
807 representing a rule running alongside one of the cells in TABLE.
809 Suppose NC is the number of columns in TABLE and NR is the number of rows.
810 Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR. If (X,Y) =
811 (0,0), the return value is the rule that runs vertically on the left side of
812 cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
813 cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
816 The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
817 within a 7x7 table. The '|' characters at the intersection of the X labels
818 and Y labels show the rule whose style would be returned by calling
819 table_get_rule with those X and Y values:
822 +--+--+--+--+--+--+--+
824 +--+--+--+--+--+--+--+
826 +--+--+--+--+--+--+--+
828 +--+--+--+--+--+--+--+
830 +--+--+--+--+--+--+--+
832 +--+--+--+--+--+--+--+
834 +--+--+--+--+--+--+--+
836 +--+--+--+--+--+--+--+
838 Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR. If
839 (X,Y) = (0,0), the return value is the rule that runs horizontally above
840 the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
841 between that cell and cell (0,1); and so on, up to (0,NR), which runs
842 horizontally below cell (0,NR-1). */
844 table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
845 struct cell_color *color)
847 assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
848 assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
850 uint8_t raw = (axis == TABLE_VERT
851 ? table->rh[x + table_nc (table) * y]
852 : table->rv[x + (table_nc (table) + 1) * y]);
853 struct cell_color *p = table->rule_colors[(raw & TAB_RULE_STYLE_MASK)
854 >> TAB_RULE_STYLE_SHIFT];
855 *color = p ? *p : (struct cell_color) CELL_COLOR_BLACK;
856 return (raw & TAB_RULE_TYPE_MASK) >> TAB_RULE_TYPE_SHIFT;