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);
92 t->cc = pool_calloc (t->container, nr * nc, sizeof *t->cc);
93 t->ct = pool_malloc (t->container, nr * nc);
94 memset (t->ct, 0, nc * nr);
96 t->rh = pool_nmalloc (t->container, nc, nr + 1);
97 memset (t->rh, 0, nc * (nr + 1));
99 t->rv = pool_nmalloc (t->container, nr, nc + 1);
100 memset (t->fmtmap, 0, sizeof (*t->fmtmap) * n_RC);
102 memset (t->rv, TAL_GAP, nr * (nc + 1));
104 t->fmtmap[RC_PVALUE] = ugly[RC_PVALUE];
105 t->fmtmap[RC_INTEGER] = ugly[RC_INTEGER];
106 t->fmtmap[RC_OTHER] = *settings_get_format ();
108 t->col_ofs = t->row_ofs = 0;
115 tab_set_format (struct tab_table *t, enum result_class rc, const struct fmt_spec *fmt)
117 t->fmtmap[rc] = *fmt;
121 /* Sets the width and height of a table, in columns and rows,
122 respectively. Use only to reduce the size of a table, since it
123 does not change the amount of allocated memory.
125 This function is obsolete. Please do not add new uses of it. (Instead, use
126 table_select() or one of its helper functions.) */
128 tab_resize (struct tab_table *t, int nc, int nr)
132 assert (nc + t->col_ofs <= t->cf);
133 table_set_nc (&t->table, nc + t->col_ofs);
137 assert (nr + t->row_ofs <= tab_nr (t));
138 table_set_nr (&t->table, nr + t->row_ofs);
142 /* Changes either or both dimensions of a table and reallocates memory as
145 This function is obsolete. Please do not add new uses of it. (Instead, use
146 table_paste() or one of its helper functions to paste multiple tables
147 together into a larger one.) */
149 tab_realloc (struct tab_table *t, int nc, int nr)
156 tab_offset (t, 0, 0);
163 assert (nc == tab_nc (t));
167 int mr1 = MIN (nr, tab_nr (t));
168 int mc1 = MIN (nc, tab_nc (t));
171 unsigned char *new_ct;
174 new_cc = pool_calloc (t->container, nr * nc, sizeof *new_cc);
175 new_ct = pool_malloc (t->container, nr * nc);
176 for (r = 0; r < mr1; r++)
178 memcpy (&new_cc[r * nc], &t->cc[r * tab_nc (t)], mc1 * sizeof *t->cc);
179 memcpy (&new_ct[r * nc], &t->ct[r * tab_nc (t)], mc1);
180 memset (&new_ct[r * nc + tab_nc (t)], 0, nc - tab_nc (t));
182 pool_free (t->container, t->cc);
183 pool_free (t->container, t->ct);
188 else if (nr != tab_nr (t))
190 t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc);
191 t->ct = pool_realloc (t->container, t->ct, nr * nc);
193 t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1);
194 t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1);
198 memset (&t->rh[nc * (tab_nr (t) + 1)], TAL_0, (nr - tab_nr (t)) * nc);
199 memset (&t->rv[(nc + 1) * tab_nr (t)], TAL_GAP,
200 (nr - tab_nr (t)) * (nc + 1));
204 memset (&t->ct[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)));
205 memset (&t->cc[nc * tab_nr (t)], 0, nc * (nr - tab_nr (t)) * sizeof *t->cc);
207 table_set_nr (&t->table, nr);
208 table_set_nc (&t->table, nc);
211 tab_offset (t, co, ro);
214 /* Sets the number of header rows on each side of TABLE to L on the
215 left, R on the right, T on the top, B on the bottom. Header rows
216 are repeated when a table is broken across multiple columns or
219 tab_headers (struct tab_table *table, int l, int r, int t, int b)
221 table_set_hl (&table->table, l);
222 table_set_hr (&table->table, r);
223 table_set_ht (&table->table, t);
224 table_set_hb (&table->table, b);
229 /* Draws a vertical line to the left of cells at horizontal position X
230 from Y1 to Y2 inclusive in style STYLE, if style is not -1. */
232 tab_vline (struct tab_table *t, int style, int x, int y1, int y2)
235 if (x + t->col_ofs < 0 || x + t->col_ofs > tab_nc (t)
236 || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
237 || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
239 printf (_("bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in "
240 "table size (%d,%d)\n"),
241 x, t->col_ofs, x + t->col_ofs,
242 y1, t->row_ofs, y1 + t->row_ofs,
243 y2, t->row_ofs, y2 + t->row_ofs,
244 tab_nc (t), tab_nr (t));
254 assert (x <= tab_nc (t));
257 assert (y2 <= tab_nr (t));
262 for (y = y1; y <= y2; y++)
263 t->rv[x + (t->cf + 1) * y] = style;
267 /* Draws a horizontal line above cells at vertical position Y from X1
268 to X2 inclusive in style STYLE, if style is not -1. */
270 tab_hline (struct tab_table * t, int style, int x1, int x2, int y)
273 if (y + t->row_ofs < 0 || y + t->row_ofs > tab_nr (t)
274 || x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
275 || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t))
277 printf (_("bad hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d in "
278 "table size (%d,%d)\n"),
279 x1, t->col_ofs, x1 + t->col_ofs,
280 x2, t->col_ofs, x2 + t->col_ofs,
281 y, t->row_ofs, y + t->row_ofs,
282 tab_nc (t), tab_nr (t));
292 assert (y <= tab_nr (t));
295 assert (x2 < tab_nc (t));
300 for (x = x1; x <= x2; x++)
301 t->rh[x + t->cf * y] = style;
305 /* Draws a box around cells (X1,Y1)-(X2,Y2) inclusive with horizontal
306 lines of style F_H and vertical lines of style F_V. Fills the
307 interior of the box with horizontal lines of style I_H and vertical
308 lines of style I_V. Any of the line styles may be -1 to avoid
309 drawing those lines. This is distinct from 0, which draws a null
312 tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
313 int x1, int y1, int x2, int y2)
316 if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= tab_nc (t)
317 || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= tab_nc (t)
318 || y1 + t->row_ofs < 0 || y1 + t->row_ofs >= tab_nr (t)
319 || y2 + t->row_ofs < 0 || y2 + t->row_ofs >= tab_nr (t))
321 printf (_("bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) "
322 "in table size (%d,%d)\n"),
323 x1, t->col_ofs, x1 + t->col_ofs,
324 y1, t->row_ofs, y1 + t->row_ofs,
325 x2, t->col_ofs, x2 + t->col_ofs,
326 y2, t->row_ofs, y2 + t->row_ofs,
327 tab_nc (t), tab_nr (t));
341 assert (x2 < tab_nc (t));
342 assert (y2 < tab_nr (t));
347 for (x = x1; x <= x2; x++)
349 t->rh[x + t->cf * y1] = f_h;
350 t->rh[x + t->cf * (y2 + 1)] = f_h;
356 for (y = y1; y <= y2; y++)
358 t->rv[x1 + (t->cf + 1) * y] = f_v;
359 t->rv[(x2 + 1) + (t->cf + 1) * y] = f_v;
367 for (y = y1 + 1; y <= y2; y++)
371 for (x = x1; x <= x2; x++)
372 t->rh[x + t->cf * y] = i_h;
379 for (x = x1 + 1; x <= x2; x++)
383 for (y = y1; y <= y2; y++)
384 t->rv[x + (t->cf + 1) * y] = i_v;
391 /* Sets cell (C,R) in TABLE, with options OPT, to have a value taken
392 from V, displayed with format spec F. */
394 tab_value (struct tab_table *table, int c, int r, unsigned char opt,
395 const union value *v, const struct variable *var,
396 const struct fmt_spec *f)
401 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
402 || c + table->col_ofs >= tab_nc (table)
403 || r + table->row_ofs >= tab_nr (table))
405 printf ("tab_value(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
407 c, table->col_ofs, c + table->col_ofs,
408 r, table->row_ofs, r + table->row_ofs,
409 tab_nc (table), tab_nr (table));
414 contents = data_out_stretchy (v, var_get_encoding (var),
415 f != NULL ? f : var_get_print_format (var),
418 table->cc[c + r * table->cf] = contents;
419 table->ct[c + r * table->cf] = opt;
422 /* Sets cell (C,R) in TABLE, with options OPT, to have value VAL as
424 If FMT is null, then the default print format will be used.
427 tab_double (struct tab_table *table, int c, int r, unsigned char opt,
428 double val, const struct fmt_spec *fmt, enum result_class rc)
430 union value double_value ;
434 assert (c < tab_nc (table));
436 assert (r < tab_nr (table));
439 fmt = &table->fmtmap[rc];
441 fmt_check_output (fmt);
444 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
445 || c + table->col_ofs >= tab_nc (table)
446 || r + table->row_ofs >= tab_nr (table))
448 printf ("tab_double(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
450 c, table->col_ofs, c + table->col_ofs,
451 r, table->row_ofs, r + table->row_ofs,
452 tab_nc (table), tab_nr (table));
457 double_value.f = val;
458 s = data_out_stretchy (&double_value, C_ENCODING, fmt, table->container);
459 table->cc[c + r * table->cf] = s + strspn (s, " ");
460 table->ct[c + r * table->cf] = opt;
465 do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text)
469 assert (c < tab_nc (table));
470 assert (r < tab_nr (table));
473 if (c + table->col_ofs < 0 || r + table->row_ofs < 0
474 || c + table->col_ofs >= tab_nc (table)
475 || r + table->row_ofs >= tab_nr (table))
477 printf ("tab_text(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
479 c, table->col_ofs, c + table->col_ofs,
480 r, table->row_ofs, r + table->row_ofs,
481 tab_nc (table), tab_nr (table));
486 table->cc[c + r * table->cf] = text;
487 table->ct[c + r * table->cf] = opt;
490 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
493 tab_text (struct tab_table *table, int c, int r, unsigned opt,
496 do_tab_text (table, c, r, opt, pool_strdup (table->container, text));
499 /* Sets cell (C,R) in TABLE, with options OPT, to have text value
500 FORMAT, which is formatted as if passed to printf. */
502 tab_text_format (struct tab_table *table, int c, int r, unsigned opt,
503 const char *format, ...)
507 va_start (args, format);
508 do_tab_text (table, c, r, opt,
509 pool_vasprintf (table->container, format, args));
513 static struct tab_joined_cell *
514 add_joined_cell (struct tab_table *table, int x1, int y1, int x2, int y2,
517 struct tab_joined_cell *j;
519 assert (x1 + table->col_ofs >= 0);
520 assert (y1 + table->row_ofs >= 0);
523 assert (y2 + table->row_ofs < tab_nr (table));
524 assert (x2 + table->col_ofs < tab_nc (table));
527 if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= tab_nc (table)
528 || y1 + table->row_ofs < 0 || y1 + table->row_ofs >= tab_nr (table)
529 || x2 < x1 || x2 + table->col_ofs >= tab_nc (table)
530 || y2 < y2 || y2 + table->row_ofs >= tab_nr (table))
532 printf ("tab_joint_text(): bad cell "
533 "(%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n",
534 x1, table->col_ofs, x1 + table->col_ofs,
535 y1, table->row_ofs, y1 + table->row_ofs,
536 x2, table->col_ofs, x2 + table->col_ofs,
537 y2, table->row_ofs, y2 + table->row_ofs,
538 tab_nc (table), tab_nr (table));
543 tab_box (table, -1, -1, TAL_0, TAL_0, x1, y1, x2, y2);
545 j = pool_alloc (table->container, sizeof *j);
546 j->d[TABLE_HORZ][0] = x1 + table->col_ofs;
547 j->d[TABLE_VERT][0] = y1 + table->row_ofs;
548 j->d[TABLE_HORZ][1] = ++x2 + table->col_ofs;
549 j->d[TABLE_VERT][1] = ++y2 + table->row_ofs;
554 void **cc = &table->cc[x1 + y1 * table->cf];
555 unsigned char *ct = &table->ct[x1 + y1 * table->cf];
556 const int ofs = table->cf - (x2 - x1);
560 for (y = y1; y < y2; y++)
564 for (x = x1; x < x2; x++)
567 *ct++ = opt | TAB_JOIN;
578 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
579 options OPT to have text value TEXT. */
581 tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
582 unsigned opt, const char *text)
584 char *s = pool_strdup (table->container, text);
585 add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
588 /* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them
589 with options OPT to have text value FORMAT, which is formatted
590 as if passed to printf. */
592 tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2,
593 unsigned opt, const char *format, ...)
598 va_start (args, format);
599 s = pool_vasprintf (table->container, format, args);
602 add_joined_cell (table, x1, y1, x2, y2, opt)->u.text = s;
606 tab_footnote (struct tab_table *table, int x, int y, const char *format, ...)
608 int index = x + y * table->cf;
609 unsigned char opt = table->ct[index];
610 struct tab_joined_cell *j;
614 j = table->cc[index];
617 char *text = table->cc[index];
619 j = add_joined_cell (table, x, y, x, y, table->ct[index]);
620 j->u.text = text ? text : xstrdup ("");
623 j->footnotes = xrealloc (j->footnotes,
624 (j->n_footnotes + 1) * sizeof *j->footnotes);
626 va_start (args, format);
627 j->footnotes[j->n_footnotes++] = pool_vasprintf (table->container, format, args);
632 subtable_unref (void *subtable)
634 table_item_unref (subtable);
637 /* Places SUBTABLE as the content for cells (X1,X2)-(Y1,Y2) inclusive in TABLE
640 tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2,
641 unsigned opt, struct table_item *subtable)
643 add_joined_cell (table, x1, y1, x2, y2, opt | TAB_SUBTABLE)->u.subtable
645 pool_register (table->container, subtable_unref, subtable);
648 /* Places the contents of SUBTABLE as the content for cells (X1,X2)-(Y1,Y2)
649 inclusive in TABLE with options OPT.
651 SUBTABLE must have exactly one row and column. The contents of its single
652 cell are used as the contents of TABLE's cell; that is, SUBTABLE is not used
653 as a nested table but its contents become part of TABLE. */
655 tab_subtable_bare (struct tab_table *table, int x1, int y1, int x2, int y2,
656 unsigned opt, struct table_item *subtable)
658 const struct table *t UNUSED = table_item_get_table (subtable);
659 assert (table_nc (t) == 1);
660 assert (table_nr (t) == 1);
661 tab_subtable (table, x1, y1, x2, y2, opt | TAB_BARE, subtable);
665 tab_cell_is_empty (const struct tab_table *table, int c, int r)
667 return table->cc[c + r * table->cf] == NULL;
672 /* Set the title of table T to TITLE, which is formatted as if
673 passed to printf(). */
675 tab_title (struct tab_table *t, const char *title, ...)
680 va_start (args, title);
681 t->title = xvasprintf (title, args);
685 /* Easy, type-safe way to submit a tab table to som. */
687 tab_submit (struct tab_table *t)
689 table_item_submit (table_item_create (&t->table, t->title));
694 /* Set table row and column offsets for all functions that affect
697 tab_offset (struct tab_table *t, int col, int row)
702 if (row < -1 || row > tab_nr (t))
704 printf ("tab_offset(): row=%d in %d-row table\n", row, tab_nr (t));
707 if (col < -1 || col > tab_nc (t))
709 printf ("tab_offset(): col=%d in %d-column table\n", col, tab_nc (t));
715 diff += (row - t->row_ofs) * t->cf, t->row_ofs = row;
717 diff += (col - t->col_ofs), t->col_ofs = col;
723 /* Increment the row offset by one. If the table is too small,
724 increase its size. */
726 tab_next_row (struct tab_table *t)
730 if (++t->row_ofs >= tab_nr (t))
731 tab_realloc (t, -1, tab_nr (t) * 4 / 3);
734 /* Writes STRING to the output. OPTIONS may be any valid combination of TAB_*
737 This function is obsolete. Please do not add new uses of it. Instead, use
738 a text_item (see output/text-item.h). */
740 tab_output_text (int options, const char *string)
742 enum text_item_type type = (options & TAB_EMPH ? TEXT_ITEM_SUBHEAD
743 : options & TAB_FIX ? TEXT_ITEM_MONOSPACE
744 : TEXT_ITEM_PARAGRAPH);
745 text_item_submit (text_item_create (type, string));
748 /* Same as tab_output_text(), but FORMAT is passed through printf-like
749 formatting before output. */
751 tab_output_text_format (int options, const char *format, ...)
756 va_start (args, format);
757 text = xvasprintf (format, args);
760 tab_output_text (options, text);
765 /* Table class implementation. */
768 tab_destroy (struct table *table)
770 struct tab_table *t = tab_cast (table);
773 pool_destroy (t->container);
777 tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell)
779 const struct tab_table *t = tab_cast (table);
780 int index = x + y * t->cf;
781 unsigned char opt = t->ct[index];
782 const void *cc = t->cc[index];
784 cell->inline_contents.options = opt;
785 cell->inline_contents.table = NULL;
786 cell->inline_contents.n_footnotes = 0;
787 cell->destructor = NULL;
791 const struct tab_joined_cell *jc = cc;
794 assert (opt & TAB_SUBTABLE);
796 /* This overwrites all of the members of CELL. */
797 table_get_cell (table_item_get_table (jc->u.subtable), 0, 0, cell);
801 cell->contents = &cell->inline_contents;
802 cell->n_contents = 1;
803 if (opt & TAB_SUBTABLE)
805 cell->inline_contents.table = jc->u.subtable;
806 cell->inline_contents.text = NULL;
809 cell->inline_contents.text = jc->u.text;
812 cell->inline_contents.footnotes = jc->footnotes;
813 cell->inline_contents.n_footnotes = jc->n_footnotes;
815 cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
816 cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
817 cell->d[TABLE_VERT][0] = jc->d[TABLE_VERT][0];
818 cell->d[TABLE_VERT][1] = jc->d[TABLE_VERT][1];
822 cell->d[TABLE_HORZ][0] = x;
823 cell->d[TABLE_HORZ][1] = x + 1;
824 cell->d[TABLE_VERT][0] = y;
825 cell->d[TABLE_VERT][1] = y + 1;
828 cell->contents = &cell->inline_contents;
829 cell->n_contents = 1;
830 cell->inline_contents.text = CONST_CAST (char *, cc);
834 cell->contents = NULL;
835 cell->n_contents = 0;
841 tab_get_rule (const struct table *table, enum table_axis axis, int x, int y)
843 const struct tab_table *t = tab_cast (table);
844 return (axis == TABLE_VERT
845 ? t->rh[x + t->cf * y]
846 : t->rv[x + (t->cf + 1) * y]);
849 static const struct table_class tab_table_class =
859 tab_cast (const struct table *table)
861 assert (table->klass == &tab_table_class);
862 return UP_CAST (table, struct tab_table, table);