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;
67 static const struct table_class tab_table_class;
69 struct fmt_spec ugly [n_RC] =
71 {FMT_F, 8, 0}, /* INTEGER */
72 {FMT_F, 8, 3}, /* WEIGHT (ignored) */
73 {FMT_F, 8, 3}, /* PVALUE */
74 {FMT_F, 8, 3} /* OTHER (ignored) */
78 /* Creates and returns a new table with NC columns and NR rows and initially no
79 header rows or columns. The table's cells are initially empty. */
81 tab_create (int nc, int nr)
85 t = pool_create_container (struct tab_table, container);
86 table_init (&t->table, &tab_table_class);
87 table_set_nc (&t->table, nc);
88 table_set_nr (&t->table, nr);
93 t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
94 t->ct = pool_malloc (t->container, nr * nc);
95 memset (t->ct, 0, nc * nr);
97 t->rh = pool_nmalloc (t->container, nc, nr + 1);
98 memset (t->rh, 0, nc * (nr + 1));
100 t->rv = pool_nmalloc (t->container, nr, nc + 1);
101 memset (t->fmtmap, 0, sizeof (*t->fmtmap) * n_RC);
103 memset (t->rv, TAL_GAP, nr * (nc + 1));
105 t->fmtmap[RC_PVALUE] = ugly[RC_PVALUE];
106 t->fmtmap[RC_INTEGER] = ugly[RC_INTEGER];
107 t->fmtmap[RC_OTHER] = *settings_get_format ();
109 t->col_ofs = t->row_ofs = 0;
116 tab_set_format (struct tab_table *t, enum result_class rc, const struct fmt_spec *fmt)
118 t->fmtmap[rc] = *fmt;
122 /* Sets the width and height of a table, in columns and rows,
123 respectively. Use only to reduce the size of a table, since it
124 does not change the amount of allocated memory.
126 This function is obsolete. Please do not add new uses of it. (Instead, use
127 table_select() or one of its helper functions.) */
129 tab_resize (struct tab_table *t, int nc, int nr)
133 assert (nc + t->col_ofs <= t->cf);
134 table_set_nc (&t->table, nc + t->col_ofs);
138 assert (nr + t->row_ofs <= tab_nr (t));
139 table_set_nr (&t->table, nr + t->row_ofs);
143 /* Changes either or both dimensions of a table and reallocates memory as
146 This function is obsolete. Please do not add new uses of it. (Instead, use
147 table_paste() or one of its helper functions to paste multiple tables
148 together into a larger one.) */
150 tab_realloc (struct tab_table *t, int nc, int nr)
157 tab_offset (t, 0, 0);
164 assert (nc == tab_nc (t));
168 int mr1 = MIN (nr, tab_nr (t));
169 int mc1 = MIN (nc, tab_nc (t));
172 unsigned char *new_ct;
175 new_cc = pool_calloc (t->container, nr * nc, sizeof *new_cc);
176 new_ct = pool_malloc (t->container, nr * nc);
177 for (r = 0; r < mr1; r++)
179 memcpy (&new_cc[r * nc], &t->cc[r * tab_nc (t)], mc1 * sizeof *t->cc);
180 memcpy (&new_ct[r * nc], &t->ct[r * tab_nc (t)], mc1);
181 memset (&new_ct[r * nc + tab_nc (t)], 0, nc - tab_nc (t));
183 pool_free (t->container, t->cc);
184 pool_free (t->container, t->ct);
189 else if (nr != tab_nr (t))
191 t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc);
192 t->ct = pool_realloc (t->container, t->ct, nr * nc);
194 t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1);
195 t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1);
199 memset (&t->rh[nc * (tab_nr (t) + 1)], TAL_0, (nr - tab_nr (t)) * nc);
200 memset (&t->rv[(nc + 1) * tab_nr (t)], TAL_GAP,
201 (nr - tab_nr (t)) * (nc + 1));
205 memset (&t->ct[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)));
206 memset (&t->cc[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)) * sizeof *t->cc);
208 table_set_nr (&t->table, nr);
209 table_set_nc (&t->table, nc);
212 tab_offset (t, co, ro);
215 /* Sets the number of header rows on each side of TABLE to L on the
216 left, R on the right, T on the top, B on the bottom. Header rows
217 are repeated when a table is broken across multiple columns or
220 tab_headers (struct tab_table *table, int l, int r, int t, int b)
222 table_set_hl (&table->table, l);
223 table_set_hr (&table->table, r);
224 table_set_ht (&table->table, t);
225 table_set_hb (&table->table, b);
230 /* Draws a vertical line to the left of cells at horizontal position X
231 from Y1 to Y2 inclusive in style STYLE, if style is not -1. */
233 tab_vline (struct tab_table *t, int style, int x, int y1, int y2)
236 if (x + t->col_ofs < 0 || x + t->col_ofs > tab_nc (t)
237 || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
238 || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
240 printf (_("bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in "
241 "table size (%d,%d)\n"),
242 x, t->col_ofs, x + t->col_ofs,
243 y1, t->row_ofs, y1 + t->row_ofs,
244 y2, t->row_ofs, y2 + t->row_ofs,
245 tab_nc (t), tab_nr (t));
255 assert (x <= tab_nc (t));
258 assert (y2 <= tab_nr (t));
263 for (y = y1; y <= y2; y++)
264 t->rv[x + (t->cf + 1) * y] = style;
268 /* Draws a horizontal line above cells at vertical position Y from X1
269 to X2 inclusive in style STYLE, if style is not -1. */
271 tab_hline (struct tab_table * t, int style, int x1, int x2, int y)
274 if (y + t->row_ofs < 0 || y + t->row_ofs > tab_nr (t)
275 || x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
276 || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t))
278 printf (_("bad hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d in "
279 "table size (%d,%d)\n"),
280 x1, t->col_ofs, x1 + t->col_ofs,
281 x2, t->col_ofs, x2 + t->col_ofs,
282 y, t->row_ofs, y + t->row_ofs,
283 tab_nc (t), tab_nr (t));
293 assert (y <= tab_nr (t));
296 assert (x2 < tab_nc (t));
301 for (x = x1; x <= x2; x++)
302 t->rh[x + t->cf * y] = style;
306 /* Draws a box around cells (X1,Y1)-(X2,Y2) inclusive with horizontal
307 lines of style F_H and vertical lines of style F_V. Fills the
308 interior of the box with horizontal lines of style I_H and vertical
309 lines of style I_V. Any of the line styles may be -1 to avoid
310 drawing those lines. This is distinct from 0, which draws a null
313 tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
314 int x1, int y1, int x2, int y2)
317 if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
318 || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t)
319 || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
320 || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
322 printf (_("bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) "
323 "in table size (%d,%d)\n"),
324 x1, t->col_ofs, x1 + t->col_ofs,
325 y1, t->row_ofs, y1 + t->row_ofs,
326 x2, t->col_ofs, x2 + t->col_ofs,
327 y2, t->row_ofs, y2 + t->row_ofs,
328 tab_nc (t), tab_nr (t));
342 assert (x2 < tab_nc (t));
343 assert (y2 < tab_nr (t));
348 for (x = x1; x <= x2; x++)
350 t->rh[x + t->cf * y1] = f_h;
351 t->rh[x + t->cf * (y2 + 1)] = f_h;
357 for (y = y1; y <= y2; y++)
359 t->rv[x1 + (t->cf + 1) * y] = f_v;
360 t->rv[(x2 + 1) + (t->cf + 1) * y] = f_v;
368 for (y = y1 + 1; y <= y2; y++)
372 for (x = x1; x <= x2; x++)
373 t->rh[x + t->cf * y] = i_h;
380 for (x = x1 + 1; x <= x2; x++)
384 for (y = y1; y <= y2; y++)
385 t->rv[x + (t->cf + 1) * y] = i_v;
392 /* Sets cell (C,R) in TABLE, with options OPT, to have a value taken
393 from V, displayed with format spec F. */
395 tab_value (struct tab_table *table, int c, int r, unsigned char opt,
396 const union value *v, const struct variable *var,
397 const struct fmt_spec *f)
402 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
403 || c + table->col_ofs >= tab_nc (table)
404 || r + table->row_ofs >= tab_nr (table))
406 printf ("tab_value(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
408 c, table->col_ofs, c + table->col_ofs,
409 r, table->row_ofs, r + table->row_ofs,
410 tab_nc (table), tab_nr (table));
415 contents = data_out_stretchy (v, var_get_encoding (var),
416 f != NULL ? f : var_get_print_format (var),
419 table->cc[c + r * table->cf] = contents;
420 table->ct[c + r * table->cf] = opt;
423 /* Sets cell (C,R) in TABLE, with options OPT, to have value VAL as
425 If FMT is null, then the default print format will be used.
428 tab_double (struct tab_table *table, int c, int r, unsigned char opt,
429 double val, const struct fmt_spec *fmt, enum result_class rc)
431 union value double_value ;
435 assert (c < tab_nc (table));
437 assert (r < tab_nr (table));
440 fmt = &table->fmtmap[rc];
442 fmt_check_output (fmt);
445 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
446 || c + table->col_ofs >= tab_nc (table)
447 || r + table->row_ofs >= tab_nr (table))
449 printf ("tab_double(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
451 c, table->col_ofs, c + table->col_ofs,
452 r, table->row_ofs, r + table->row_ofs,
453 tab_nc (table), tab_nr (table));
458 double_value.f = val;
459 s = data_out_stretchy (&double_value, C_ENCODING, fmt, table->container);
460 table->cc[c + r * table->cf] = s + strspn (s, " ");
461 table->ct[c + r * table->cf] = opt;
466 do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text)
470 assert (c < tab_nc (table));
471 assert (r < tab_nr (table));
474 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
475 || c + table->col_ofs >= tab_nc (table)
476 || r + table->row_ofs >= tab_nr (table))
478 printf ("tab_text(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
480 c, table->col_ofs, c + table->col_ofs,
481 r, table->row_ofs, r + table->row_ofs,
482 tab_nc (table), tab_nr (table));
487 table->cc[c + r * table->cf] = text;
488 table->ct[c + r * table->cf] = opt;
491 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
494 tab_text (struct tab_table *table, int c, int r, unsigned opt,
497 do_tab_text (table, c, r, opt, pool_strdup (table->container, text));
500 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
501 FORMAT, which is formatted as if passed to printf. */
503 tab_text_format (struct tab_table *table, int c, int r, unsigned opt,
504 const char *format, ...)
508 va_start (args, format);
509 do_tab_text (table, c, r, opt,
510 pool_vasprintf (table->container, format, args));
514 static struct tab_joined_cell *
515 add_joined_cell (struct tab_table *table, int x1, int y1, int x2, int y2,
518 struct tab_joined_cell *j;
520 assert (x1 + table->col_ofs >= 0);
521 assert (y1 + table->row_ofs >= 0);
524 assert (y2 + table->row_ofs < tab_nr (table));
525 assert (x2 + table->col_ofs < tab_nc (table));
528 if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= tab_nc (table)
529 || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= tab_nr (table)
530 || x2 < x1 || x2 + table->col_ofs >= tab_nc (table)
531 || y2 < y2 || y2 + table->row_ofs >= tab_nr (table))
533 printf ("tab_joint_text(): bad cell "
534 "(%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n",
535 x1, table->col_ofs, x1 + table->col_ofs,
536 y1, table->row_ofs, y1 + table->row_ofs,
537 x2, table->col_ofs, x2 + table->col_ofs,
538 y2, table->row_ofs, y2 + table->row_ofs,
539 tab_nc (table), tab_nr (table));
544 tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2);
546 j = pool_alloc (table->container, sizeof *j);
547 j->d[TABLE_HORZ][0] = x1 + table->col_ofs;
548 j->d[TABLE_VERT][0] = y1 + table->row_ofs;
549 j->d[TABLE_HORZ][1] = ++x2 + table->col_ofs;
550 j->d[TABLE_VERT][1] = ++y2 + table->row_ofs;
555 void **cc = &table->cc[x1 + y1 * table->cf];
556 unsigned char *ct = &table->ct[x1 + y1 * table->cf];
557 const int ofs = table->cf - (x2 - x1);
561 for (y = y1; y < y2; y++)
565 for (x = x1; x < x2; x++)
568 *ct++ = opt | TAB_JOIN;
579 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
580 options OPT to have text value TEXT. */
582 tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
583 unsigned opt, const char *text)
585 char *s = pool_strdup (table->container, text);
586 add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
589 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them
590 with options OPT to have text value FORMAT, which is formatted
591 as if passed to printf. */
593 tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2,
594 unsigned opt, const char *format, ...)
599 va_start (args, format);
600 s = pool_vasprintf (table->container, format, args);
603 add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
607 tab_footnote (struct tab_table *table, int x, int y, const char *format, ...)
609 int index = x + y * table->cf;
610 unsigned char opt = table->ct[index];
611 struct tab_joined_cell *j;
615 j = table->cc[index];
618 char *text = table->cc[index];
620 j = add_joined_cell (table, x, y, x, y, table->ct[index]);
621 j->u.text = text ? text : xstrdup ("");
624 j->footnotes = xrealloc (j->footnotes,
625 (j->n_footnotes + 1) * sizeof *j->footnotes);
627 va_start (args, format);
628 j->footnotes[j->n_footnotes++] = pool_vasprintf (table->container, format, args);
633 subtable_unref (void *subtable)
635 table_item_unref (subtable);
638 /* Places SUBTABLE as the content for cells (X1,X2)-(Y1,Y2) inclusive in TABLE
641 tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2,
642 unsigned opt, struct table_item *subtable)
644 add_joined_cell (table, x1, y1, x2, y2, opt | TAB_SUBTABLE)->u.subtable
646 pool_register (table->container, subtable_unref, subtable);
649 /* Places the contents of SUBTABLE as the content for cells (X1,X2)-(Y1,Y2)
650 inclusive in TABLE with options OPT.
652 SUBTABLE must have exactly one row and column. The contents of its single
653 cell are used as the contents of TABLE's cell; that is, SUBTABLE is not used
654 as a nested table but its contents become part of TABLE. */
656 tab_subtable_bare (struct tab_table *table, int x1, int y1, int x2, int y2,
657 unsigned opt, struct table_item *subtable)
659 const struct table *t UNUSED = table_item_get_table (subtable);
660 assert (table_nc (t) == 1);
661 assert (table_nr (t) == 1);
662 tab_subtable (table, x1, y1, x2, y2, opt | TAB_BARE, subtable);
666 tab_cell_is_empty (const struct tab_table *table, int c, int r)
668 return table->cc[c + r * table->cf] == NULL;
673 /* Set the title of table T to TITLE, which is formatted as if
674 passed to printf(). */
676 tab_title (struct tab_table *t, const char *title, ...)
681 va_start (args, title);
682 t->title = xvasprintf (title, args);
686 /* Set the caption of table T to CAPTION, which is formatted as if
687 passed to printf(). */
689 tab_caption (struct tab_table *t, const char *caption, ...)
694 va_start (args, caption);
695 t->caption = xvasprintf (caption, args);
699 /* Easy, type-safe way to submit a tab table to som. */
701 tab_submit (struct tab_table *t)
703 table_item_submit (table_item_create (&t->table, t->title, t->caption));
708 /* Set table row and column offsets for all functions that affect
711 tab_offset (struct tab_table *t, int col, int row)
716 if (row < -1 || row > tab_nr (t))
718 printf ("tab_offset(): row=%d in %d-row table\n", row, tab_nr (t));
721 if (col < -1 || col > tab_nc (t))
723 printf ("tab_offset(): col=%d in %d-column table\n", col, tab_nc (t));
729 diff += (row - t->row_ofs) * t->cf, t->row_ofs = row;
731 diff += (col - t->col_ofs), t->col_ofs = col;
737 /* Increment the row offset by one. If the table is too small,
738 increase its size. */
740 tab_next_row (struct tab_table *t)
744 if (++t->row_ofs >= tab_nr (t))
745 tab_realloc (t, -1, tab_nr (t) * 4 / 3);
748 /* Writes STRING to the output. OPTIONS may be any valid combination of TAB_*
751 This function is obsolete. Please do not add new uses of it. Instead, use
752 a text_item (see output/text-item.h). */
754 tab_output_text (int options, const char *string)
756 enum text_item_type type = (options & TAB_EMPH ? TEXT_ITEM_SUBHEAD
757 : options & TAB_FIX ? TEXT_ITEM_MONOSPACE
758 : TEXT_ITEM_PARAGRAPH);
759 text_item_submit (text_item_create (type, string));
762 /* Same as tab_output_text(), but FORMAT is passed through printf-like
763 formatting before output. */
765 tab_output_text_format (int options, const char *format, ...)
770 va_start (args, format);
771 text = xvasprintf (format, args);
774 tab_output_text (options, text);
779 /* Table class implementation. */
782 tab_destroy (struct table *table)
784 struct tab_table *t = tab_cast (table);
789 pool_destroy (t->container);
793 tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell)
795 const struct tab_table *t = tab_cast (table);
796 int index = x + y * t->cf;
797 unsigned char opt = t->ct[index];
798 const void *cc = t->cc[index];
800 cell->inline_contents.options = opt;
801 cell->inline_contents.table = NULL;
802 cell->inline_contents.n_footnotes = 0;
803 cell->destructor = NULL;
807 const struct tab_joined_cell *jc = cc;
810 assert (opt & TAB_SUBTABLE);
812 /* This overwrites all of the members of CELL. */
813 table_get_cell (table_item_get_table (jc->u.subtable), 0, 0, cell);
817 cell->contents = &cell->inline_contents;
818 cell->n_contents = 1;
819 if (opt & TAB_SUBTABLE)
821 cell->inline_contents.table = jc->u.subtable;
822 cell->inline_contents.text = NULL;
825 cell->inline_contents.text = jc->u.text;
828 cell->inline_contents.footnotes = jc->footnotes;
829 cell->inline_contents.n_footnotes = jc->n_footnotes;
831 cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
832 cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
833 cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0];
834 cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1];
838 cell->d[TABLE_HORZ][0] = x;
839 cell->d[TABLE_HORZ][1] = x + 1;
840 cell->d[TABLE_VERT][0] = y;
841 cell->d[TABLE_VERT][1] = y + 1;
844 cell->contents = &cell->inline_contents;
845 cell->n_contents = 1;
846 cell->inline_contents.text = CONST_CAST (char *, cc);
850 cell->contents = NULL;
851 cell->n_contents = 0;
857 tab_get_rule (const struct table *table, enum table_axis axis, int x, int y)
859 const struct tab_table *t = tab_cast (table);
860 return (axis == TABLE_VERT
861 ? t->rh[x + t->cf * y]
862 : t->rv[x + (t->cf + 1) * y]);
865 static const struct table_class tab_table_class =
875 tab_cast (const struct table *table)
877 assert (table->klass == &tab_table_class);
878 return UP_CAST (table, struct tab_table, table);