1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2013, 2014 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)
48 #define TAB_JOIN (1u << TAB_FIRST_AVAILABLE)
49 #define TAB_SUBTABLE (1u << (TAB_FIRST_AVAILABLE + 1))
50 #define TAB_BARE (1u << (TAB_FIRST_AVAILABLE + 2))
53 struct tab_joined_cell
55 int d[TABLE_N_AXES][2]; /* Table region, same as struct table_cell. */
59 struct table *subtable;
64 static const struct table_class tab_table_class;
66 struct fmt_spec ugly [n_RC] =
68 {FMT_F, 8, 0}, /* INTEGER */
69 {FMT_F, 8, 3}, /* WEIGHT (ignored) */
70 {FMT_F, 8, 3}, /* PVALUE */
71 {FMT_F, 8, 3} /* OTHER (ignored) */
75 /* Creates and returns a new table with NC columns and NR rows and initially no
76 header rows or columns. The table's cells are initially empty. */
78 tab_create (int nc, int nr)
82 t = pool_create_container (struct tab_table, container);
83 table_init (&t->table, &tab_table_class);
84 table_set_nc (&t->table, nc);
85 table_set_nr (&t->table, nr);
89 t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
90 t->ct = pool_malloc (t->container, nr * nc);
91 memset (t->ct, 0, nc * nr);
93 t->rh = pool_nmalloc (t->container, nc, nr + 1);
94 memset (t->rh, 0, nc * (nr + 1));
96 t->rv = pool_nmalloc (t->container, nr, nc + 1);
97 memset (t->fmtmap, 0, sizeof (*t->fmtmap) * n_RC);
99 memset (t->rv, TAL_GAP, nr * (nc + 1));
101 t->fmtmap[RC_PVALUE] = ugly[RC_PVALUE];
102 t->fmtmap[RC_INTEGER] = ugly[RC_INTEGER];
103 t->fmtmap[RC_OTHER] = *settings_get_format ();
105 t->col_ofs = t->row_ofs = 0;
112 tab_set_format (struct tab_table *t, enum result_class rc, const struct fmt_spec *fmt)
114 t->fmtmap[rc] = *fmt;
118 /* Sets the width and height of a table, in columns and rows,
119 respectively. Use only to reduce the size of a table, since it
120 does not change the amount of allocated memory.
122 This function is obsolete. Please do not add new uses of it. (Instead, use
123 table_select() or one of its helper functions.) */
125 tab_resize (struct tab_table *t, int nc, int nr)
129 assert (nc + t->col_ofs <= t->cf);
130 table_set_nc (&t->table, nc + t->col_ofs);
134 assert (nr + t->row_ofs <= tab_nr (t));
135 table_set_nr (&t->table, nr + t->row_ofs);
139 /* Changes either or both dimensions of a table and reallocates memory as
142 This function is obsolete. Please do not add new uses of it. (Instead, use
143 table_paste() or one of its helper functions to paste multiple tables
144 together into a larger one.) */
146 tab_realloc (struct tab_table *t, int nc, int nr)
153 tab_offset (t, 0, 0);
160 assert (nc == tab_nc (t));
164 int mr1 = MIN (nr, tab_nr (t));
165 int mc1 = MIN (nc, tab_nc (t));
168 unsigned char *new_ct;
171 new_cc = pool_calloc (t->container, nr * nc, sizeof *new_cc);
172 new_ct = pool_malloc (t->container, nr * nc);
173 for (r = 0; r < mr1; r++)
175 memcpy (&new_cc[r * nc], &t->cc[r * tab_nc (t)], mc1 * sizeof *t->cc);
176 memcpy (&new_ct[r * nc], &t->ct[r * tab_nc (t)], mc1);
177 memset (&new_ct[r * nc + tab_nc (t)], 0, nc - tab_nc (t));
179 pool_free (t->container, t->cc);
180 pool_free (t->container, t->ct);
185 else if (nr != tab_nr (t))
187 t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc);
188 t->ct = pool_realloc (t->container, t->ct, nr * nc);
190 t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1);
191 t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1);
195 memset (&t->rh[nc * (tab_nr (t) + 1)], TAL_0, (nr - tab_nr (t)) * nc);
196 memset (&t->rv[(nc + 1) * tab_nr (t)], TAL_GAP,
197 (nr - tab_nr (t)) * (nc + 1));
201 memset (&t->ct[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)));
202 memset (&t->cc[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)) * sizeof *t->cc);
204 table_set_nr (&t->table, nr);
205 table_set_nc (&t->table, nc);
208 tab_offset (t, co, ro);
211 /* Sets the number of header rows on each side of TABLE to L on the
212 left, R on the right, T on the top, B on the bottom. Header rows
213 are repeated when a table is broken across multiple columns or
216 tab_headers (struct tab_table *table, int l, int r, int t, int b)
218 table_set_hl (&table->table, l);
219 table_set_hr (&table->table, r);
220 table_set_ht (&table->table, t);
221 table_set_hb (&table->table, b);
226 /* Draws a vertical line to the left of cells at horizontal position X
227 from Y1 to Y2 inclusive in style STYLE, if style is not -1. */
229 tab_vline (struct tab_table *t, int style, int x, int y1, int y2)
232 if (x + t->col_ofs < 0 || x + t->col_ofs > tab_nc (t)
233 || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
234 || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
236 printf (_("bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in "
237 "table size (%d,%d)\n"),
238 x, t->col_ofs, x + t->col_ofs,
239 y1, t->row_ofs, y1 + t->row_ofs,
240 y2, t->row_ofs, y2 + t->row_ofs,
241 tab_nc (t), tab_nr (t));
251 assert (x <= tab_nc (t));
254 assert (y2 <= tab_nr (t));
259 for (y = y1; y <= y2; y++)
260 t->rv[x + (t->cf + 1) * y] = style;
264 /* Draws a horizontal line above cells at vertical position Y from X1
265 to X2 inclusive in style STYLE, if style is not -1. */
267 tab_hline (struct tab_table * t, int style, int x1, int x2, int y)
270 if (y + t->row_ofs < 0 || y + t->row_ofs > tab_nr (t)
271 || x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
272 || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t))
274 printf (_("bad hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d in "
275 "table size (%d,%d)\n"),
276 x1, t->col_ofs, x1 + t->col_ofs,
277 x2, t->col_ofs, x2 + t->col_ofs,
278 y, t->row_ofs, y + t->row_ofs,
279 tab_nc (t), tab_nr (t));
289 assert (y <= tab_nr (t));
292 assert (x2 < tab_nc (t));
297 for (x = x1; x <= x2; x++)
298 t->rh[x + t->cf * y] = style;
302 /* Draws a box around cells (X1,Y1)-(X2,Y2) inclusive with horizontal
303 lines of style F_H and vertical lines of style F_V. Fills the
304 interior of the box with horizontal lines of style I_H and vertical
305 lines of style I_V. Any of the line styles may be -1 to avoid
306 drawing those lines. This is distinct from 0, which draws a null
309 tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
310 int x1, int y1, int x2, int y2)
313 if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
314 || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t)
315 || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
316 || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
318 printf (_("bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) "
319 "in table size (%d,%d)\n"),
320 x1, t->col_ofs, x1 + t->col_ofs,
321 y1, t->row_ofs, y1 + t->row_ofs,
322 x2, t->col_ofs, x2 + t->col_ofs,
323 y2, t->row_ofs, y2 + t->row_ofs,
324 tab_nc (t), tab_nr (t));
338 assert (x2 < tab_nc (t));
339 assert (y2 < tab_nr (t));
344 for (x = x1; x <= x2; x++)
346 t->rh[x + t->cf * y1] = f_h;
347 t->rh[x + t->cf * (y2 + 1)] = f_h;
353 for (y = y1; y <= y2; y++)
355 t->rv[x1 + (t->cf + 1) * y] = f_v;
356 t->rv[(x2 + 1) + (t->cf + 1) * y] = f_v;
364 for (y = y1 + 1; y <= y2; y++)
368 for (x = x1; x <= x2; x++)
369 t->rh[x + t->cf * y] = i_h;
376 for (x = x1 + 1; x <= x2; x++)
380 for (y = y1; y <= y2; y++)
381 t->rv[x + (t->cf + 1) * y] = i_v;
388 /* Sets cell (C,R) in TABLE, with options OPT, to have a value taken
389 from V, displayed with format spec F. */
391 tab_value (struct tab_table *table, int c, int r, unsigned char opt,
392 const union value *v, const struct variable *var,
393 const struct fmt_spec *f)
398 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
399 || c + table->col_ofs >= tab_nc (table)
400 || r + table->row_ofs >= tab_nr (table))
402 printf ("tab_value(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
404 c, table->col_ofs, c + table->col_ofs,
405 r, table->row_ofs, r + table->row_ofs,
406 tab_nc (table), tab_nr (table));
411 contents = data_out_stretchy (v, var_get_encoding (var),
412 f != NULL ? f : var_get_print_format (var),
415 table->cc[c + r * table->cf] = contents;
416 table->ct[c + r * table->cf] = opt;
419 /* Sets cell (C,R) in TABLE, with options OPT, to have value VAL as
421 If FMT is null, then the default print format will be used.
424 tab_double (struct tab_table *table, int c, int r, unsigned char opt,
425 double val, const struct fmt_spec *fmt, enum result_class rc)
427 union value double_value ;
431 assert (c < tab_nc (table));
433 assert (r < tab_nr (table));
436 fmt = &table->fmtmap[rc];
438 fmt_check_output (fmt);
441 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
442 || c + table->col_ofs >= tab_nc (table)
443 || r + table->row_ofs >= tab_nr (table))
445 printf ("tab_double(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
447 c, table->col_ofs, c + table->col_ofs,
448 r, table->row_ofs, r + table->row_ofs,
449 tab_nc (table), tab_nr (table));
454 double_value.f = val;
455 s = data_out_stretchy (&double_value, C_ENCODING, fmt, table->container);
456 table->cc[c + r * table->cf] = s + strspn (s, " ");
457 table->ct[c + r * table->cf] = opt;
462 do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text)
466 assert (c < tab_nc (table));
467 assert (r < tab_nr (table));
470 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
471 || c + table->col_ofs >= tab_nc (table)
472 || r + table->row_ofs >= tab_nr (table))
474 printf ("tab_text(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
476 c, table->col_ofs, c + table->col_ofs,
477 r, table->row_ofs, r + table->row_ofs,
478 tab_nc (table), tab_nr (table));
483 table->cc[c + r * table->cf] = text;
484 table->ct[c + r * table->cf] = opt;
487 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
490 tab_text (struct tab_table *table, int c, int r, unsigned opt,
493 do_tab_text (table, c, r, opt, pool_strdup (table->container, text));
496 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
497 FORMAT, which is formatted as if passed to printf. */
499 tab_text_format (struct tab_table *table, int c, int r, unsigned opt,
500 const char *format, ...)
504 va_start (args, format);
505 do_tab_text (table, c, r, opt,
506 pool_vasprintf (table->container, format, args));
510 static struct tab_joined_cell *
511 add_joined_cell (struct tab_table *table, int x1, int y1, int x2, int y2,
514 struct tab_joined_cell *j;
516 assert (x1 + table->col_ofs >= 0);
517 assert (y1 + table->row_ofs >= 0);
520 assert (y2 + table->row_ofs < tab_nr (table));
521 assert (x2 + table->col_ofs < tab_nc (table));
524 if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= tab_nc (table)
525 || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= tab_nr (table)
526 || x2 < x1 || x2 + table->col_ofs >= tab_nc (table)
527 || y2 < y2 || y2 + table->row_ofs >= tab_nr (table))
529 printf ("tab_joint_text(): bad cell "
530 "(%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n",
531 x1, table->col_ofs, x1 + table->col_ofs,
532 y1, table->row_ofs, y1 + table->row_ofs,
533 x2, table->col_ofs, x2 + table->col_ofs,
534 y2, table->row_ofs, y2 + table->row_ofs,
535 tab_nc (table), tab_nr (table));
540 tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2);
542 j = pool_alloc (table->container, sizeof *j);
543 j->d[TABLE_HORZ][0] = x1 + table->col_ofs;
544 j->d[TABLE_VERT][0] = y1 + table->row_ofs;
545 j->d[TABLE_HORZ][1] = ++x2 + table->col_ofs;
546 j->d[TABLE_VERT][1] = ++y2 + table->row_ofs;
549 void **cc = &table->cc[x1 + y1 * table->cf];
550 unsigned char *ct = &table->ct[x1 + y1 * table->cf];
551 const int ofs = table->cf - (x2 - x1);
555 for (y = y1; y < y2; y++)
559 for (x = x1; x < x2; x++)
562 *ct++ = opt | TAB_JOIN;
573 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
574 options OPT to have text value TEXT. */
576 tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
577 unsigned opt, const char *text)
579 char *s = pool_strdup (table->container, text);
580 add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
583 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them
584 with options OPT to have text value FORMAT, which is formatted
585 as if passed to printf. */
587 tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2,
588 unsigned opt, const char *format, ...)
593 va_start (args, format);
594 s = pool_vasprintf (table->container, format, args);
597 add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
601 subtable_unref (void *subtable)
603 table_unref (subtable);
606 /* Places SUBTABLE as the content for cells (X1,X2)-(Y1,Y2) inclusive in TABLE
609 tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2,
610 unsigned opt, struct table *subtable)
612 add_joined_cell (table, x1, y1, x2, y2, opt | TAB_SUBTABLE)->u.subtable
614 pool_register (table->container, subtable_unref, subtable);
617 /* Places the contents of SUBTABLE as the content for cells (X1,X2)-(Y1,Y2)
618 inclusive in TABLE with options OPT.
620 SUBTABLE must have exactly one row and column. The contents of its single
621 cell are used as the contents of TABLE's cell; that is, SUBTABLE is not used
622 as a nested table but its contents become part of TABLE. */
624 tab_subtable_bare (struct tab_table *table, int x1, int y1, int x2, int y2,
625 unsigned opt, struct table *subtable)
627 assert (table_nc (subtable) == 1);
628 assert (table_nr (subtable) == 1);
629 tab_subtable (table, x1, y1, x2, y2, opt | TAB_BARE, subtable);
633 tab_cell_is_empty (const struct tab_table *table, int c, int r)
635 return table->cc[c + r * table->cf] == NULL;
640 /* Set the title of table T to TITLE, which is formatted as if
641 passed to printf(). */
643 tab_title (struct tab_table *t, const char *title, ...)
648 va_start (args, title);
649 t->title = xvasprintf (title, args);
653 /* Easy, type-safe way to submit a tab table to som. */
655 tab_submit (struct tab_table *t)
657 table_item_submit (table_item_create (&t->table, t->title));
662 /* Set table row and column offsets for all functions that affect
665 tab_offset (struct tab_table *t, int col, int row)
670 if (row < -1 || row > tab_nr (t))
672 printf ("tab_offset(): row=%d in %d-row table\n", row, tab_nr (t));
675 if (col < -1 || col > tab_nc (t))
677 printf ("tab_offset(): col=%d in %d-column table\n", col, tab_nc (t));
683 diff += (row - t->row_ofs) * t->cf, t->row_ofs = row;
685 diff += (col - t->col_ofs), t->col_ofs = col;
691 /* Increment the row offset by one. If the table is too small,
692 increase its size. */
694 tab_next_row (struct tab_table *t)
698 if (++t->row_ofs >= tab_nr (t))
699 tab_realloc (t, -1, tab_nr (t) * 4 / 3);
702 /* Writes STRING to the output. OPTIONS may be any valid combination of TAB_*
705 This function is obsolete. Please do not add new uses of it. Instead, use
706 a text_item (see output/text-item.h). */
708 tab_output_text (int options, const char *string)
710 enum text_item_type type = (options & TAB_EMPH ? TEXT_ITEM_SUBHEAD
711 : options & TAB_FIX ? TEXT_ITEM_MONOSPACE
712 : TEXT_ITEM_PARAGRAPH);
713 text_item_submit (text_item_create (type, string));
716 /* Same as tab_output_text(), but FORMAT is passed through printf-like
717 formatting before output. */
719 tab_output_text_format (int options, const char *format, ...)
724 va_start (args, format);
725 text = xvasprintf (format, args);
728 tab_output_text (options, text);
733 /* Table class implementation. */
736 tab_destroy (struct table *table)
738 struct tab_table *t = tab_cast (table);
741 pool_destroy (t->container);
745 tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell)
747 const struct tab_table *t = tab_cast (table);
748 int index = x + y * t->cf;
749 unsigned char opt = t->ct[index];
750 const void *cc = t->cc[index];
752 cell->inline_contents.options = opt;
753 cell->inline_contents.table = NULL;
754 cell->destructor = NULL;
758 const struct tab_joined_cell *jc = cc;
761 assert (opt & TAB_SUBTABLE);
763 /* This overwrites all of the members of CELL. */
764 table_get_cell (jc->u.subtable, 0, 0, cell);
768 cell->contents = &cell->inline_contents;
769 cell->n_contents = 1;
770 if (opt & TAB_SUBTABLE)
772 cell->inline_contents.table = jc->u.subtable;
773 cell->inline_contents.text = NULL;
776 cell->inline_contents.text = jc->u.text;
779 cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
780 cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
781 cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0];
782 cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1];
786 cell->d[TABLE_HORZ][0] = x;
787 cell->d[TABLE_HORZ][1] = x + 1;
788 cell->d[TABLE_VERT][0] = y;
789 cell->d[TABLE_VERT][1] = y + 1;
792 cell->contents = &cell->inline_contents;
793 cell->n_contents = 1;
794 cell->inline_contents.text = CONST_CAST (char *, cc);
798 cell->contents = NULL;
799 cell->n_contents = 0;
805 tab_get_rule (const struct table *table, enum table_axis axis, int x, int y)
807 const struct tab_table *t = tab_cast (table);
808 return (axis == TABLE_VERT
809 ? t->rh[x + t->cf * y]
810 : t->rv[x + (t->cf + 1) * y]);
813 static const struct table_class tab_table_class =
823 tab_cast (const struct table *table)
825 assert (table->klass == &tab_table_class);
826 return UP_CAST (table, struct tab_table, table);