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_item *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_item_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_item *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_item *subtable)
627 const struct table *t UNUSED = table_item_get_table (subtable);
628 assert (table_nc (t) == 1);
629 assert (table_nr (t) == 1);
630 tab_subtable (table, x1, y1, x2, y2, opt | TAB_BARE, subtable);
634 tab_cell_is_empty (const struct tab_table *table, int c, int r)
636 return table->cc[c + r * table->cf] == NULL;
641 /* Set the title of table T to TITLE, which is formatted as if
642 passed to printf(). */
644 tab_title (struct tab_table *t, const char *title, ...)
649 va_start (args, title);
650 t->title = xvasprintf (title, args);
654 /* Easy, type-safe way to submit a tab table to som. */
656 tab_submit (struct tab_table *t)
658 table_item_submit (table_item_create (&t->table, t->title));
663 /* Set table row and column offsets for all functions that affect
666 tab_offset (struct tab_table *t, int col, int row)
671 if (row < -1 || row > tab_nr (t))
673 printf ("tab_offset(): row=%d in %d-row table\n", row, tab_nr (t));
676 if (col < -1 || col > tab_nc (t))
678 printf ("tab_offset(): col=%d in %d-column table\n", col, tab_nc (t));
684 diff += (row - t->row_ofs) * t->cf, t->row_ofs = row;
686 diff += (col - t->col_ofs), t->col_ofs = col;
692 /* Increment the row offset by one. If the table is too small,
693 increase its size. */
695 tab_next_row (struct tab_table *t)
699 if (++t->row_ofs >= tab_nr (t))
700 tab_realloc (t, -1, tab_nr (t) * 4 / 3);
703 /* Writes STRING to the output. OPTIONS may be any valid combination of TAB_*
706 This function is obsolete. Please do not add new uses of it. Instead, use
707 a text_item (see output/text-item.h). */
709 tab_output_text (int options, const char *string)
711 enum text_item_type type = (options & TAB_EMPH ? TEXT_ITEM_SUBHEAD
712 : options & TAB_FIX ? TEXT_ITEM_MONOSPACE
713 : TEXT_ITEM_PARAGRAPH);
714 text_item_submit (text_item_create (type, string));
717 /* Same as tab_output_text(), but FORMAT is passed through printf-like
718 formatting before output. */
720 tab_output_text_format (int options, const char *format, ...)
725 va_start (args, format);
726 text = xvasprintf (format, args);
729 tab_output_text (options, text);
734 /* Table class implementation. */
737 tab_destroy (struct table *table)
739 struct tab_table *t = tab_cast (table);
742 pool_destroy (t->container);
746 tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell)
748 const struct tab_table *t = tab_cast (table);
749 int index = x + y * t->cf;
750 unsigned char opt = t->ct[index];
751 const void *cc = t->cc[index];
753 cell->inline_contents.options = opt;
754 cell->inline_contents.table = NULL;
755 cell->destructor = NULL;
759 const struct tab_joined_cell *jc = cc;
762 assert (opt & TAB_SUBTABLE);
764 /* This overwrites all of the members of CELL. */
765 table_get_cell (table_item_get_table (jc->u.subtable), 0, 0, cell);
769 cell->contents = &cell->inline_contents;
770 cell->n_contents = 1;
771 if (opt & TAB_SUBTABLE)
773 cell->inline_contents.table = jc->u.subtable;
774 cell->inline_contents.text = NULL;
777 cell->inline_contents.text = jc->u.text;
780 cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
781 cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
782 cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0];
783 cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1];
787 cell->d[TABLE_HORZ][0] = x;
788 cell->d[TABLE_HORZ][1] = x + 1;
789 cell->d[TABLE_VERT][0] = y;
790 cell->d[TABLE_VERT][1] = y + 1;
793 cell->contents = &cell->inline_contents;
794 cell->n_contents = 1;
795 cell->inline_contents.text = CONST_CAST (char *, cc);
799 cell->contents = NULL;
800 cell->n_contents = 0;
806 tab_get_rule (const struct table *table, enum table_axis axis, int x, int y)
808 const struct tab_table *t = tab_cast (table);
809 return (axis == TABLE_VERT
810 ? t->rh[x + t->cf * y]
811 : t->rv[x + (t->cf + 1) * y]);
814 static const struct table_class tab_table_class =
824 tab_cast (const struct table *table)
826 assert (table->klass == &tab_table_class);
827 return UP_CAST (table, struct tab_table, table);