1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2013, 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/tab.h"
26 #include "data/data-out.h"
27 #include "data/format.h"
28 #include "data/settings.h"
29 #include "data/value.h"
30 #include "data/variable.h"
31 #include "libpspp/assertion.h"
32 #include "libpspp/compiler.h"
33 #include "libpspp/i18n.h"
34 #include "libpspp/misc.h"
35 #include "libpspp/pool.h"
36 #include "output/driver.h"
37 #include "output/table-item.h"
38 #include "output/table-provider.h"
39 #include "output/text-item.h"
41 #include "gl/minmax.h"
42 #include "gl/xalloc.h"
45 #define _(msgid) gettext (msgid)
49 static const bool debugging = true;
51 static const bool debugging = false;
55 #define TAB_JOIN (1u << TAB_FIRST_AVAILABLE)
56 #define TAB_SUBTABLE (1u << (TAB_FIRST_AVAILABLE + 1))
57 #define TAB_BARE (1u << (TAB_FIRST_AVAILABLE + 2))
60 struct tab_joined_cell
62 int d[TABLE_N_AXES][2]; /* Table region, same as struct table_cell. */
66 struct table_item *subtable;
74 static const struct table_class tab_table_class;
76 struct fmt_spec ugly[n_RC] = {
77 {FMT_F, 8, 0}, /* INTEGER */
78 {FMT_F, 8, 3}, /* WEIGHT (ignored) */
79 {FMT_F, 8, 3}, /* PVALUE */
80 {FMT_F, 8, 3} /* OTHER (ignored) */
84 /* Creates and returns a new table with NC columns and NR rows and initially no
85 header rows or columns. The table's cells are initially empty. */
87 tab_create (int nc, int nr)
91 t = pool_create_container (struct tab_table, container);
92 table_init (&t->table, &tab_table_class);
93 table_set_nc (&t->table, nc);
94 table_set_nr (&t->table, nr);
99 t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
100 t->ct = pool_malloc (t->container, nr * nc);
101 memset (t->ct, 0, nc * nr);
103 t->rh = pool_nmalloc (t->container, nc, nr + 1);
104 memset (t->rh, 0, nc * (nr + 1));
106 t->rv = pool_nmalloc (t->container, nr, nc + 1);
107 memset (t->fmtmap, 0, sizeof (*t->fmtmap) * n_RC);
109 memset (t->rv, TAL_GAP, nr * (nc + 1));
111 t->fmtmap[RC_PVALUE] = ugly[RC_PVALUE];
112 t->fmtmap[RC_INTEGER] = ugly[RC_INTEGER];
113 t->fmtmap[RC_OTHER] = *settings_get_format ();
115 t->col_ofs = t->row_ofs = 0;
122 tab_set_format (struct tab_table *t, enum result_class rc,
123 const struct fmt_spec *fmt)
125 t->fmtmap[rc] = *fmt;
129 /* Sets the width and height of a table, in columns and rows,
130 respectively. Use only to reduce the size of a table, since it
131 does not change the amount of allocated memory.
133 This function is obsolete. Please do not add new uses of it. (Instead, use
134 table_select() or one of its helper functions.) */
136 tab_resize (struct tab_table *t, int nc, int nr)
140 assert (nc + t->col_ofs <= t->cf);
141 table_set_nc (&t->table, nc + t->col_ofs);
145 assert (nr + t->row_ofs <= tab_nr (t));
146 table_set_nr (&t->table, nr + t->row_ofs);
150 /* Changes either or both dimensions of a table and reallocates memory as
153 This function is obsolete. Please do not add new uses of it. (Instead, use
154 table_paste() or one of its helper functions to paste multiple tables
155 together into a larger one.) */
157 tab_realloc (struct tab_table *t, int nc, int nr)
164 tab_offset (t, 0, 0);
171 assert (nc == tab_nc (t));
175 int mr1 = MIN (nr, tab_nr (t));
176 int mc1 = MIN (nc, tab_nc (t));
179 unsigned char *new_ct;
182 new_cc = pool_calloc (t->container, nr * nc, sizeof *new_cc);
183 new_ct = pool_malloc (t->container, nr * nc);
184 for (r = 0; r < mr1; r++)
186 memcpy (&new_cc[r * nc], &t->cc[r * tab_nc (t)],
187 mc1 * sizeof *t->cc);
188 memcpy (&new_ct[r * nc], &t->ct[r * tab_nc (t)], mc1);
189 memset (&new_ct[r * nc + tab_nc (t)], 0, nc - tab_nc (t));
191 pool_free (t->container, t->cc);
192 pool_free (t->container, t->ct);
197 else if (nr != tab_nr (t))
199 t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc);
200 t->ct = pool_realloc (t->container, t->ct, nr * nc);
202 t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1);
203 t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1);
207 memset (&t->rh[nc * (tab_nr (t) + 1)], TAL_0,
208 (nr - tab_nr (t)) * nc);
209 memset (&t->rv[(nc + 1) * tab_nr (t)], TAL_GAP,
210 (nr - tab_nr (t)) * (nc + 1));
214 memset (&t->ct[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)));
215 memset (&t->cc[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)) * sizeof *t->cc);
217 table_set_nr (&t->table, nr);
218 table_set_nc (&t->table, nc);
221 tab_offset (t, co, ro);
224 /* Sets the number of header rows on each side of TABLE to L on the
225 left, R on the right, T on the top, B on the bottom. Header rows
226 are repeated when a table is broken across multiple columns or
229 tab_headers (struct tab_table *table, int l, int r, int t, int b)
231 table_set_hl (&table->table, l);
232 table_set_hr (&table->table, r);
233 table_set_ht (&table->table, t);
234 table_set_hb (&table->table, b);
239 /* Draws a vertical line to the left of cells at horizontal position X
240 from Y1 to Y2 inclusive in style STYLE, if style is not -1. */
242 tab_vline (struct tab_table *t, int style, int x, int y1, int y2)
246 if (x + t->col_ofs < 0 || x + t->col_ofs > tab_nc (t)
247 || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
248 || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
250 printf (_("bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in "
251 "table size (%d,%d)\n"),
252 x, t->col_ofs, x + t->col_ofs,
253 y1, t->row_ofs, y1 + t->row_ofs,
254 y2, t->row_ofs, y2 + t->row_ofs, tab_nc (t), tab_nr (t));
264 assert (x <= tab_nc (t));
267 assert (y2 <= tab_nr (t));
272 for (y = y1; y <= y2; y++)
273 t->rv[x + (t->cf + 1) * y] = style;
277 /* Draws a horizontal line above cells at vertical position Y from X1
278 to X2 inclusive in style STYLE, if style is not -1. */
280 tab_hline (struct tab_table *t, int style, int x1, int x2, int y)
284 if (y + t->row_ofs < 0 || y + t->row_ofs > tab_nr (t)
285 || x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
286 || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t))
288 printf (_("bad hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d in "
289 "table size (%d,%d)\n"),
290 x1, t->col_ofs, x1 + t->col_ofs,
291 x2, t->col_ofs, x2 + t->col_ofs,
292 y, t->row_ofs, y + t->row_ofs, tab_nc (t), tab_nr (t));
302 assert (y <= tab_nr (t));
305 assert (x2 < tab_nc (t));
310 for (x = x1; x <= x2; x++)
311 t->rh[x + t->cf * y] = style;
315 /* Draws a box around cells (X1,Y1)-(X2,Y2) inclusive with horizontal
316 lines of style F_H and vertical lines of style F_V. Fills the
317 interior of the box with horizontal lines of style I_H and vertical
318 lines of style I_V. Any of the line styles may be -1 to avoid
319 drawing those lines. This is distinct from 0, which draws a null
322 tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
323 int x1, int y1, int x2, int y2)
327 if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
328 || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t)
329 || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
330 || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
332 printf (_("bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) "
333 "in table size (%d,%d)\n"),
334 x1, t->col_ofs, x1 + t->col_ofs,
335 y1, t->row_ofs, y1 + t->row_ofs,
336 x2, t->col_ofs, x2 + t->col_ofs,
337 y2, t->row_ofs, y2 + t->row_ofs, tab_nc (t), tab_nr (t));
351 assert (x2 < tab_nc (t));
352 assert (y2 < tab_nr (t));
357 for (x = x1; x <= x2; x++)
359 t->rh[x + t->cf * y1] = f_h;
360 t->rh[x + t->cf * (y2 + 1)] = f_h;
366 for (y = y1; y <= y2; y++)
368 t->rv[x1 + (t->cf + 1) * y] = f_v;
369 t->rv[(x2 + 1) + (t->cf + 1) * y] = f_v;
377 for (y = y1 + 1; y <= y2; y++)
381 for (x = x1; x <= x2; x++)
382 t->rh[x + t->cf * y] = i_h;
389 for (x = x1 + 1; x <= x2; x++)
393 for (y = y1; y <= y2; y++)
394 t->rv[x + (t->cf + 1) * y] = i_v;
401 /* Sets cell (C,R) in TABLE, with options OPT, to have a value taken
402 from V, displayed with format spec F. */
404 tab_value (struct tab_table *table, int c, int r, unsigned char opt,
405 const union value *v, const struct variable *var,
406 const struct fmt_spec *f)
412 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
413 || c + table->col_ofs >= tab_nc (table)
414 || r + table->row_ofs >= tab_nr (table))
416 printf ("tab_value(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
418 c, table->col_ofs, c + table->col_ofs,
419 r, table->row_ofs, r + table->row_ofs,
420 tab_nc (table), tab_nr (table));
425 contents = data_out_stretchy (v, var_get_encoding (var),
426 f != NULL ? f : var_get_print_format (var),
429 table->cc[c + r * table->cf] = contents;
430 table->ct[c + r * table->cf] = opt;
433 /* Sets cell (C,R) in TABLE, with options OPT, to have value VAL as
435 If FMT is null, then the default print format will be used.
438 tab_double (struct tab_table *table, int c, int r, unsigned char opt,
439 double val, const struct fmt_spec *fmt, enum result_class rc)
441 union value double_value;
445 assert (c < tab_nc (table));
447 assert (r < tab_nr (table));
450 fmt = &table->fmtmap[rc];
452 fmt_check_output (fmt);
456 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
457 || c + table->col_ofs >= tab_nc (table)
458 || r + table->row_ofs >= tab_nr (table))
460 printf ("tab_double(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
462 c, table->col_ofs, c + table->col_ofs,
463 r, table->row_ofs, r + table->row_ofs,
464 tab_nc (table), tab_nr (table));
469 double_value.f = val;
470 s = data_out_stretchy (&double_value, C_ENCODING, fmt, table->container);
471 table->cc[c + r * table->cf] = s + strspn (s, " ");
472 table->ct[c + r * table->cf] = opt;
477 do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text)
481 assert (c < tab_nc (table));
482 assert (r < tab_nr (table));
486 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
487 || c + table->col_ofs >= tab_nc (table)
488 || r + table->row_ofs >= tab_nr (table))
490 printf ("tab_text(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
492 c, table->col_ofs, c + table->col_ofs,
493 r, table->row_ofs, r + table->row_ofs,
494 tab_nc (table), tab_nr (table));
499 table->cc[c + r * table->cf] = text;
500 table->ct[c + r * table->cf] = opt;
503 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
506 tab_text (struct tab_table *table, int c, int r, unsigned opt,
509 do_tab_text (table, c, r, opt, pool_strdup (table->container, text));
512 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
513 FORMAT, which is formatted as if passed to printf. */
515 tab_text_format (struct tab_table *table, int c, int r, unsigned opt,
516 const char *format, ...)
520 va_start (args, format);
521 do_tab_text (table, c, r, opt,
522 pool_vasprintf (table->container, format, args));
526 static struct tab_joined_cell *
527 add_joined_cell (struct tab_table *table, int x1, int y1, int x2, int y2,
530 struct tab_joined_cell *j;
532 assert (x1 + table->col_ofs >= 0);
533 assert (y1 + table->row_ofs >= 0);
536 assert (y2 + table->row_ofs < tab_nr (table));
537 assert (x2 + table->col_ofs < tab_nc (table));
541 if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= tab_nc (table)
542 || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= tab_nr (table)
543 || x2 < x1 || x2 + table->col_ofs >= tab_nc (table)
544 || y2 < y1 || y2 + table->row_ofs >= tab_nr (table))
546 printf ("tab_joint_text(): bad cell "
547 "(%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n",
548 x1, table->col_ofs, x1 + table->col_ofs,
549 y1, table->row_ofs, y1 + table->row_ofs,
550 x2, table->col_ofs, x2 + table->col_ofs,
551 y2, table->row_ofs, y2 + table->row_ofs,
552 tab_nc (table), tab_nr (table));
557 tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2);
559 j = pool_alloc (table->container, sizeof *j);
560 j->d[TABLE_HORZ][0] = x1 + table->col_ofs;
561 j->d[TABLE_VERT][0] = y1 + table->row_ofs;
562 j->d[TABLE_HORZ][1] = ++x2 + table->col_ofs;
563 j->d[TABLE_VERT][1] = ++y2 + table->row_ofs;
568 void **cc = &table->cc[x1 + y1 * table->cf];
569 unsigned char *ct = &table->ct[x1 + y1 * table->cf];
570 const int ofs = table->cf - (x2 - x1);
574 for (y = y1; y < y2; y++)
578 for (x = x1; x < x2; x++)
581 *ct++ = opt | TAB_JOIN;
592 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
593 options OPT to have text value TEXT. */
595 tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
596 unsigned opt, const char *text)
598 char *s = pool_strdup (table->container, text);
599 add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
602 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them
603 with options OPT to have text value FORMAT, which is formatted
604 as if passed to printf. */
606 tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2,
607 int y2, unsigned opt, const char *format, ...)
612 va_start (args, format);
613 s = pool_vasprintf (table->container, format, args);
616 add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
620 tab_footnote (struct tab_table *table, int x, int y, const char *format, ...)
622 int index = x + y * table->cf;
623 unsigned char opt = table->ct[index];
624 struct tab_joined_cell *j;
628 j = table->cc[index];
631 char *text = table->cc[index];
633 j = add_joined_cell (table, x, y, x, y, table->ct[index]);
634 j->u.text = text ? text : xstrdup ("");
637 j->footnotes = xrealloc (j->footnotes,
638 (j->n_footnotes + 1) * sizeof *j->footnotes);
640 va_start (args, format);
641 j->footnotes[j->n_footnotes++] =
642 pool_vasprintf (table->container, format, args);
647 subtable_unref (void *subtable)
649 table_item_unref (subtable);
652 /* Places SUBTABLE as the content for cells (X1,X2)-(Y1,Y2) inclusive in TABLE
655 tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2,
656 unsigned opt, struct table_item *subtable)
658 add_joined_cell (table, x1, y1, x2, y2, opt | TAB_SUBTABLE)->u.subtable
660 pool_register (table->container, subtable_unref, subtable);
663 /* Places the contents of SUBTABLE as the content for cells (X1,X2)-(Y1,Y2)
664 inclusive in TABLE with options OPT.
666 SUBTABLE must have exactly one row and column. The contents of its single
667 cell are used as the contents of TABLE's cell; that is, SUBTABLE is not used
668 as a nested table but its contents become part of TABLE. */
670 tab_subtable_bare (struct tab_table *table, int x1, int y1, int x2, int y2,
671 unsigned opt, struct table_item *subtable)
673 const struct table *t UNUSED = table_item_get_table (subtable);
674 assert (table_nc (t) == 1);
675 assert (table_nr (t) == 1);
676 tab_subtable (table, x1, y1, x2, y2, opt | TAB_BARE, subtable);
680 tab_cell_is_empty (const struct tab_table *table, int c, int r)
682 return table->cc[c + r * table->cf] == NULL;
687 /* Set the title of table T to TITLE, which is formatted as if
688 passed to printf(). */
690 tab_title (struct tab_table *t, const char *title, ...)
695 va_start (args, title);
696 t->title = xvasprintf (title, args);
700 /* Set the caption of table T to CAPTION, which is formatted as if
701 passed to printf(). */
703 tab_caption (struct tab_table *t, const char *caption, ...)
708 va_start (args, caption);
709 t->caption = xvasprintf (caption, args);
713 /* Easy, type-safe way to submit a tab table to som. */
715 tab_submit (struct tab_table *t)
717 table_item_submit (table_item_create (&t->table, t->title, t->caption));
722 /* Set table row and column offsets for all functions that affect
725 tab_offset (struct tab_table *t, int col, int row)
731 if (row < -1 || row > tab_nr (t))
733 printf ("tab_offset(): row=%d in %d-row table\n", row, tab_nr (t));
736 if (col < -1 || col > tab_nc (t))
738 printf ("tab_offset(): col=%d in %d-column table\n", col,
745 diff += (row - t->row_ofs) * t->cf, t->row_ofs = row;
747 diff += (col - t->col_ofs), t->col_ofs = col;
753 /* Increment the row offset by one. If the table is too small,
754 increase its size. */
756 tab_next_row (struct tab_table *t)
760 if (++t->row_ofs >= tab_nr (t))
761 tab_realloc (t, -1, tab_nr (t) * 4 / 3);
764 /* Writes STRING to the output. OPTIONS may be any valid combination of TAB_*
767 This function is obsolete. Please do not add new uses of it. Instead, use
768 a text_item (see output/text-item.h). */
770 tab_output_text (int options, const char *string)
772 enum text_item_type type = (options & TAB_EMPH ? TEXT_ITEM_SUBHEAD
773 : options & TAB_FIX ? TEXT_ITEM_MONOSPACE
774 : TEXT_ITEM_PARAGRAPH);
775 text_item_submit (text_item_create (type, string));
778 /* Same as tab_output_text(), but FORMAT is passed through printf-like
779 formatting before output. */
781 tab_output_text_format (int options, const char *format, ...)
786 va_start (args, format);
787 text = xvasprintf (format, args);
790 tab_output_text (options, text);
795 /* Table class implementation. */
798 tab_destroy (struct table *table)
800 struct tab_table *t = tab_cast (table);
805 pool_destroy (t->container);
809 tab_get_cell (const struct table *table, int x, int y,
810 struct table_cell *cell)
812 const struct tab_table *t = tab_cast (table);
813 int index = x + y * t->cf;
814 unsigned char opt = t->ct[index];
815 const void *cc = t->cc[index];
817 cell->inline_contents.options = opt;
818 cell->inline_contents.table = NULL;
819 cell->inline_contents.n_footnotes = 0;
820 cell->destructor = NULL;
824 const struct tab_joined_cell *jc = cc;
827 assert (opt & TAB_SUBTABLE);
829 /* This overwrites all of the members of CELL. */
830 table_get_cell (table_item_get_table (jc->u.subtable), 0, 0, cell);
834 cell->contents = &cell->inline_contents;
835 cell->n_contents = 1;
836 if (opt & TAB_SUBTABLE)
838 cell->inline_contents.table = jc->u.subtable;
839 cell->inline_contents.text = NULL;
842 cell->inline_contents.text = jc->u.text;
845 cell->inline_contents.footnotes = jc->footnotes;
846 cell->inline_contents.n_footnotes = jc->n_footnotes;
848 cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
849 cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
850 cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0];
851 cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1];
855 cell->d[TABLE_HORZ][0] = x;
856 cell->d[TABLE_HORZ][1] = x + 1;
857 cell->d[TABLE_VERT][0] = y;
858 cell->d[TABLE_VERT][1] = y + 1;
861 cell->contents = &cell->inline_contents;
862 cell->n_contents = 1;
863 cell->inline_contents.text = CONST_CAST (char *, cc);
867 cell->contents = NULL;
868 cell->n_contents = 0;
874 tab_get_rule (const struct table *table, enum table_axis axis, int x, int y)
876 const struct tab_table *t = tab_cast (table);
877 return (axis == TABLE_VERT
878 ? t->rh[x + t->cf * y] : t->rv[x + (t->cf + 1) * y]);
881 static const struct table_class tab_table_class = {
890 tab_cast (const struct table *table)
892 assert (table->klass == &tab_table_class);
893 return UP_CAST (table, struct tab_table, table);