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/tab.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 = tab_create (1, 1, 0, 0, 0, 0);
179 tab_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 font_style *dst, const struct font_style *src)
235 dst->typeface = xstrdup (dst->typeface);
239 font_style_uninit (struct font_style *font)
242 free (font->typeface);
246 area_style_copy (struct area_style *dst, const struct area_style *src)
248 font_style_copy (&dst->font_style, &src->font_style);
249 dst->cell_style = src->cell_style;
253 area_style_uninit (struct area_style *area)
256 font_style_uninit (&area->font_style);
260 table_stroke_to_string (enum table_stroke stroke)
264 case TABLE_STROKE_NONE: return "none";
265 case TABLE_STROKE_SOLID: return "solid";
266 case TABLE_STROKE_DASHED: return "dashed";
267 case TABLE_STROKE_THICK: return "thick";
268 case TABLE_STROKE_THIN: return "thin";
269 case TABLE_STROKE_DOUBLE: return "double";
276 cell_color_dump (const struct cell_color *c)
279 printf ("rgba(%d, %d, %d, %d)", c->r, c->g, c->b, c->alpha);
281 printf ("#%02"PRIx8"%02"PRIx8"%02"PRIx8, c->r, c->g, c->b);
285 font_style_dump (const struct font_style *f)
287 printf ("%s %dpx ", f->typeface, f->size);
288 cell_color_dump (&f->fg[0]);
290 cell_color_dump (&f->bg[0]);
291 if (!cell_color_equal (&f->fg[0], &f->fg[1])
292 || !cell_color_equal (&f->bg[0], &f->bg[1]))
295 cell_color_dump (&f->fg[1]);
297 cell_color_dump (&f->bg[1]);
300 fputs (" bold", stdout);
302 fputs (" italic", stdout);
304 fputs (" underline", stdout);
308 cell_style_dump (const struct cell_style *c)
310 fputs (table_halign_to_string (c->halign), stdout);
311 if (c->halign == TABLE_HALIGN_DECIMAL)
312 printf ("(%.2gpx)", c->decimal_offset);
313 printf (" %s", table_valign_to_string (c->valign));
314 printf (" %d,%d,%d,%dpx",
315 c->margin[TABLE_HORZ][0], c->margin[TABLE_HORZ][1],
316 c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);
320 static const bool debugging = true;
323 struct tab_joined_cell
325 int d[TABLE_N_AXES][2]; /* Table region, same as struct table_cell. */
329 const struct footnote **footnotes;
331 const struct area_style *style;
334 /* Creates and returns a new table with NC columns and NR rows and initially no
335 header rows or columns.
337 Sets the number of header rows on each side of TABLE to HL on the
338 left, HR on the right, HT on the top, HB on the bottom. Header rows
339 are repeated when a table is broken across multiple columns or
342 The table's cells are initially empty. */
344 tab_create (int nc, int nr, int hl, int hr, int ht, int hb)
348 t = pool_create_container (struct table, container);
349 t->n[TABLE_HORZ] = nc;
350 t->n[TABLE_VERT] = nr;
351 t->h[TABLE_HORZ][0] = hl;
352 t->h[TABLE_HORZ][1] = hr;
353 t->h[TABLE_VERT][0] = ht;
354 t->h[TABLE_VERT][1] = hb;
357 t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
358 t->ct = pool_calloc (t->container, nr * nc, sizeof *t->ct);
360 t->rh = pool_nmalloc (t->container, nc, nr + 1);
361 memset (t->rh, TAL_0, nc * (nr + 1));
363 t->rv = pool_nmalloc (t->container, nr, nc + 1);
364 memset (t->rv, TAL_0, nr * (nc + 1));
366 memset (t->styles, 0, sizeof t->styles);
367 memset (t->rule_colors, 0, sizeof t->rule_colors);
374 /* Draws a vertical line to the left of cells at horizontal position X
375 from Y1 to Y2 inclusive in style STYLE, if style is not -1. */
377 tab_vline (struct table *t, int style, int x, int y1, int y2)
381 if (x < 0 || x > table_nc (t)
382 || y1 < 0 || y1 >= table_nr (t)
383 || y2 < 0 || y2 >= table_nr (t))
385 printf ("bad vline: x=%d y=(%d,%d) in table size (%d,%d)\n",
386 x, y1, y2, table_nc (t), table_nr (t));
392 assert (x <= table_nc (t));
395 assert (y2 <= table_nr (t));
400 for (y = y1; y <= y2; y++)
401 t->rv[x + (table_nc (t) + 1) * y] = style;
405 /* Draws a horizontal line above cells at vertical position Y from X1
406 to X2 inclusive in style STYLE, if style is not -1. */
408 tab_hline (struct table *t, int style, int x1, int x2, int y)
412 if (y < 0 || y > table_nr (t)
413 || x1 < 0 || x1 >= table_nc (t)
414 || x2 < 0 || x2 >= table_nc (t))
416 printf ("bad hline: x=(%d,%d) y=%d in table size (%d,%d)\n",
417 x1, x2, y, table_nc (t), table_nr (t));
423 assert (y <= table_nr (t));
426 assert (x2 < table_nc (t));
431 for (x = x1; x <= x2; x++)
432 t->rh[x + table_nc (t) * y] = style;
436 /* Draws a box around cells (X1,Y1)-(X2,Y2) inclusive with horizontal
437 lines of style F_H and vertical lines of style F_V. Fills the
438 interior of the box with horizontal lines of style I_H and vertical
439 lines of style I_V. Any of the line styles may be -1 to avoid
440 drawing those lines. This is distinct from 0, which draws a null
443 tab_box (struct table *t, int f_h, int f_v, int i_h, int i_v,
444 int x1, int y1, int x2, int y2)
448 if (x1 < 0 || x1 >= table_nc (t)
449 || x2 < 0 || x2 >= table_nc (t)
450 || y1 < 0 || y1 >= table_nr (t)
451 || y2 < 0 || y2 >= table_nr (t))
453 printf ("bad box: (%d,%d)-(%d,%d) in table size (%d,%d)\n",
454 x1, y1, x2, y2, table_nc (t), table_nr (t));
463 assert (x2 < table_nc (t));
464 assert (y2 < table_nr (t));
469 for (x = x1; x <= x2; x++)
471 t->rh[x + table_nc (t) * y1] = f_h;
472 t->rh[x + table_nc (t) * (y2 + 1)] = f_h;
478 for (y = y1; y <= y2; y++)
480 t->rv[x1 + (table_nc (t) + 1) * y] = f_v;
481 t->rv[(x2 + 1) + (table_nc (t) + 1) * y] = f_v;
489 for (y = y1 + 1; y <= y2; y++)
493 for (x = x1; x <= x2; x++)
494 t->rh[x + table_nc (t) * y] = i_h;
501 for (x = x1 + 1; x <= x2; x++)
505 for (y = y1; y <= y2; y++)
506 t->rv[x + (table_nc (t) + 1) * y] = i_v;
514 do_tab_text (struct table *table, int c, int r, unsigned opt, char *text)
518 assert (c < table_nc (table));
519 assert (r < table_nr (table));
523 if (c < 0 || r < 0 || c >= table_nc (table) || r >= table_nr (table))
525 printf ("tab_text(): bad cell (%d,%d) in table size (%d,%d)\n",
526 c, r, table_nc (table), table_nr (table));
531 table->cc[c + r * table_nc (table)] = text;
532 table->ct[c + r * table_nc (table)] = opt;
535 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
538 tab_text (struct table *table, int c, int r, unsigned opt,
541 do_tab_text (table, c, r, opt, pool_strdup (table->container, text));
544 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
545 FORMAT, which is formatted as if passed to printf. */
547 tab_text_format (struct table *table, int c, int r, unsigned opt,
548 const char *format, ...)
552 va_start (args, format);
553 do_tab_text (table, c, r, opt,
554 pool_vasprintf (table->container, format, args));
558 static struct tab_joined_cell *
559 add_joined_cell (struct table *table, int x1, int y1, int x2, int y2,
562 struct tab_joined_cell *j;
568 assert (y2 < table_nr (table));
569 assert (x2 < table_nc (table));
573 if (x1 < 0 || x1 >= table_nc (table)
574 || y1 < 0 || y1 >= table_nr (table)
575 || x2 < x1 || x2 >= table_nc (table)
576 || y2 < y1 || y2 >= table_nr (table))
578 printf ("tab_joint_text(): bad cell "
579 "(%d,%d)-(%d,%d) in table size (%d,%d)\n",
580 x1, y1, x2, y2, table_nc (table), table_nr (table));
585 tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2);
587 j = pool_alloc (table->container, sizeof *j);
588 j->d[TABLE_HORZ][0] = x1;
589 j->d[TABLE_VERT][0] = y1;
590 j->d[TABLE_HORZ][1] = ++x2;
591 j->d[TABLE_VERT][1] = ++y2;
597 void **cc = &table->cc[x1 + y1 * table_nc (table)];
598 unsigned short *ct = &table->ct[x1 + y1 * table_nc (table)];
599 const int ofs = table_nc (table) - (x2 - x1);
603 for (y = y1; y < y2; y++)
607 for (x = x1; x < x2; x++)
610 *ct++ = opt | TAB_JOIN;
621 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
622 options OPT to have text value TEXT. */
624 tab_joint_text (struct table *table, int x1, int y1, int x2, int y2,
625 unsigned opt, const char *text)
627 char *s = pool_strdup (table->container, text);
628 if (x1 == x2 && y1 == y2)
629 do_tab_text (table, x1, y1, opt, s);
631 add_joined_cell (table, x1, y1, x2, y2, opt)->text = s;
635 tab_create_footnote (struct table *table, size_t idx, const char *content,
636 const char *marker, struct area_style *style)
638 struct footnote *f = pool_alloc (table->container, sizeof *f);
640 f->content = pool_strdup (table->container, content);
641 f->marker = pool_strdup (table->container, marker);
647 tab_add_footnote (struct table *table, int x, int y,
648 const struct footnote *f)
650 int index = x + y * table_nc (table);
651 unsigned short opt = table->ct[index];
652 struct tab_joined_cell *j;
655 j = table->cc[index];
658 char *text = table->cc[index];
660 j = add_joined_cell (table, x, y, x, y, table->ct[index]);
661 j->text = text ? text : xstrdup ("");
664 j->footnotes = pool_realloc (table->container, j->footnotes,
665 (j->n_footnotes + 1) * sizeof *j->footnotes);
667 j->footnotes[j->n_footnotes++] = f;
671 tab_add_style (struct table *table, int x, int y,
672 const struct area_style *style)
674 int index = x + y * table_nc (table);
675 unsigned short opt = table->ct[index];
676 struct tab_joined_cell *j;
679 j = table->cc[index];
682 char *text = table->cc[index];
684 j = add_joined_cell (table, x, y, x, y, table->ct[index]);
685 j->text = text ? text : xstrdup ("");
692 tab_cell_is_empty (const struct table *table, int c, int r)
694 return table->cc[c + r * table_nc (table)] == NULL;
699 /* Writes STRING to the output. OPTIONS may be any valid combination of TAB_*
702 This function is obsolete. Please do not add new uses of it. Instead, use
703 a text_item (see output/text-item.h). */
705 tab_output_text (int options UNUSED, const char *string)
707 text_item_submit (text_item_create (TEXT_ITEM_LOG, string));
710 /* Same as tab_output_text(), but FORMAT is passed through printf-like
711 formatting before output. */
713 tab_output_text_format (int options, const char *format, ...)
718 va_start (args, format);
719 text = xvasprintf (format, args);
722 tab_output_text (options, text);
727 /* Initializes CELL with the contents of the table cell at column X and row Y
728 within TABLE. When CELL is no longer needed, the caller is responsible for
729 freeing it by calling table_cell_free(CELL).
731 The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
733 table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
735 assert (x >= 0 && x < t->n[TABLE_HORZ]);
736 assert (y >= 0 && y < t->n[TABLE_VERT]);
738 int index = x + y * table_nc (t);
739 unsigned short opt = t->ct[index];
740 const void *cc = t->cc[index];
743 cell->n_footnotes = 0;
745 int style_idx = (opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT;
746 const struct area_style *style = t->styles[style_idx];
751 static const struct area_style styles[3][3] = {
752 #define S(H,V) [H][V] = { AREA_STYLE_INITIALIZER__, \
753 .cell_style.halign = H, \
754 .cell_style.valign = V }
755 S(TABLE_HALIGN_LEFT, TABLE_VALIGN_TOP),
756 S(TABLE_HALIGN_LEFT, TABLE_VALIGN_CENTER),
757 S(TABLE_HALIGN_LEFT, TABLE_VALIGN_BOTTOM),
758 S(TABLE_HALIGN_CENTER, TABLE_VALIGN_TOP),
759 S(TABLE_HALIGN_CENTER, TABLE_VALIGN_CENTER),
760 S(TABLE_HALIGN_CENTER, TABLE_VALIGN_BOTTOM),
761 S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_TOP),
762 S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_CENTER),
763 S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_BOTTOM),
766 enum table_halign halign
767 = ((opt & TAB_HALIGN) == TAB_LEFT ? TABLE_HALIGN_LEFT
768 : (opt & TAB_HALIGN) == TAB_CENTER ? TABLE_HALIGN_CENTER
769 : TABLE_HALIGN_RIGHT);
770 enum table_valign valign
771 = ((opt & TAB_VALIGN) == TAB_TOP ? TABLE_VALIGN_TOP
772 : (opt & TAB_VALIGN) == TAB_MIDDLE ? TABLE_VALIGN_CENTER
773 : TABLE_VALIGN_BOTTOM);
775 cell->style = &styles[halign][valign];
780 const struct tab_joined_cell *jc = cc;
781 cell->text = jc->text;
783 cell->footnotes = jc->footnotes;
784 cell->n_footnotes = jc->n_footnotes;
786 cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
787 cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
788 cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0];
789 cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1];
792 cell->style = jc->style;
796 cell->d[TABLE_HORZ][0] = x;
797 cell->d[TABLE_HORZ][1] = x + 1;
798 cell->d[TABLE_VERT][0] = y;
799 cell->d[TABLE_VERT][1] = y + 1;
800 cell->text = CONST_CAST (char *, cc ? cc : "");
804 /* Returns one of the TAL_* enumeration constants (declared in output/table.h)
805 representing a rule running alongside one of the cells in TABLE.
807 Suppose NC is the number of columns in TABLE and NR is the number of rows.
808 Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR. If (X,Y) =
809 (0,0), the return value is the rule that runs vertically on the left side of
810 cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
811 cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
814 The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
815 within a 7x7 table. The '|' characters at the intersection of the X labels
816 and Y labels show the rule whose style would be returned by calling
817 table_get_rule with those X and Y values:
820 +--+--+--+--+--+--+--+
822 +--+--+--+--+--+--+--+
824 +--+--+--+--+--+--+--+
826 +--+--+--+--+--+--+--+
828 +--+--+--+--+--+--+--+
830 +--+--+--+--+--+--+--+
832 +--+--+--+--+--+--+--+
834 +--+--+--+--+--+--+--+
836 Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR. If
837 (X,Y) = (0,0), the return value is the rule that runs horizontally above
838 the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
839 between that cell and cell (0,1); and so on, up to (0,NR), which runs
840 horizontally below cell (0,NR-1). */
842 table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
843 struct cell_color *color)
845 assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
846 assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
848 uint8_t raw = (axis == TABLE_VERT
849 ? table->rh[x + table_nc (table) * y]
850 : table->rv[x + (table_nc (table) + 1) * y]);
851 struct cell_color *p = table->rule_colors[(raw & TAB_RULE_STYLE_MASK)
852 >> TAB_RULE_STYLE_SHIFT];
853 *color = p ? *p : (struct cell_color) CELL_COLOR_BLACK;
854 return (raw & TAB_RULE_TYPE_MASK) >> TAB_RULE_TYPE_SHIFT;