1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2009, 2011, 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/table.h"
20 #include "output/table-provider.h"
25 #include "libpspp/cast.h"
26 #include "libpspp/compiler.h"
27 #include "libpspp/str.h"
28 #include "output/table-item.h"
30 #include "gl/xalloc.h"
32 /* Increases TABLE's reference count, indicating that it has an additional
33 owner. An table that is shared among multiple owners must not be
36 table_ref (const struct table *table_)
38 struct table *table = CONST_CAST (struct table *, table_);
43 /* Decreases TABLE's reference count, indicating that it has one fewer owner.
44 If TABLE no longer has any owners, it is freed. */
46 table_unref (struct table *table)
50 assert (table->ref_cnt > 0);
51 if (--table->ref_cnt == 0)
52 table->klass->destroy (table);
56 /* Returns true if TABLE has more than one owner. A table item that is shared
57 among multiple owners must not be modified. */
59 table_is_shared (const struct table *table)
61 return table->ref_cnt > 1;
64 /* Sets the number of left header columns in TABLE to HL. */
66 table_set_hl (struct table *table, int hl)
68 assert (!table_is_shared (table));
69 table->h[TABLE_HORZ][0] = hl;
72 /* Sets the number of right header columns in TABLE to HR. */
74 table_set_hr (struct table *table, int hr)
76 assert (!table_is_shared (table));
77 table->h[TABLE_HORZ][1] = hr;
80 /* Sets the number of top header rows in TABLE to HT. */
82 table_set_ht (struct table *table, int ht)
84 assert (!table_is_shared (table));
85 table->h[TABLE_VERT][0] = ht;
88 /* Sets the number of top header rows in TABLE to HB. */
90 table_set_hb (struct table *table, int hb)
92 assert (!table_is_shared (table));
93 table->h[TABLE_VERT][1] = hb;
96 /* Initializes TABLE as a table of the specified CLASS, initially with a
99 TABLE initially has 0 rows and columns and no headers. The table
100 implementation should update the numbers of rows and columns. The table
101 implementation (or its client) may update the header rows and columns.
103 A table is an abstract class, that is, a plain struct table is not useful on
104 its own. Thus, this function is normally called from the initialization
105 function of some subclass of table. */
107 table_init (struct table *table, const struct table_class *class)
109 table->klass = class;
110 table->n[TABLE_HORZ] = table->n[TABLE_VERT] = 0;
111 table->h[TABLE_HORZ][0] = table->h[TABLE_HORZ][1] = 0;
112 table->h[TABLE_VERT][0] = table->h[TABLE_VERT][1] = 0;
116 /* Sets the number of columns in TABLE to NC. */
118 table_set_nc (struct table *table, int nc)
120 assert (!table_is_shared (table));
121 table->n[TABLE_HORZ] = nc;
124 /* Sets the number of rows in TABLE to NR. */
126 table_set_nr (struct table *table, int nr)
128 assert (!table_is_shared (table));
129 table->n[TABLE_VERT] = nr;
132 /* Initializes CELL with the contents of the table cell at column X and row Y
133 within TABLE. When CELL is no longer needed, the caller is responsible for
134 freeing it by calling table_cell_free(CELL).
136 The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
138 table_get_cell (const struct table *table, int x, int y,
139 struct table_cell *cell)
141 assert (x >= 0 && x < table->n[TABLE_HORZ]);
142 assert (y >= 0 && y < table->n[TABLE_VERT]);
144 static const struct cell_style default_style =
147 .bg = { 255, 255, 255 },
148 .margin = { [TABLE_HORZ][0] = 8, [TABLE_HORZ][1] = 11,
149 [TABLE_VERT][0] = 1, [TABLE_VERT][1] = 1 },
151 cell->style = &default_style;
153 table->klass->get_cell (table, x, y, cell);
156 /* Frees CELL, which should have been initialized by calling
159 table_cell_free (struct table_cell *cell)
161 if (cell->destructor != NULL)
162 cell->destructor (cell->destructor_aux);
165 /* Returns one of the TAL_* enumeration constants (declared in output/table.h)
166 representing a rule running alongside one of the cells in TABLE.
168 Suppose NC is the number of columns in TABLE and NR is the number of rows.
169 Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR. If (X,Y) =
170 (0,0), the return value is the rule that runs vertically on the left side of
171 cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
172 cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
175 The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
176 within a 7x7 table. The '|' characters at the intersection of the X labels
177 and Y labels show the rule whose style would be returned by calling
178 table_get_rule with those X and Y values:
181 +--+--+--+--+--+--+--+
183 +--+--+--+--+--+--+--+
185 +--+--+--+--+--+--+--+
187 +--+--+--+--+--+--+--+
189 +--+--+--+--+--+--+--+
191 +--+--+--+--+--+--+--+
193 +--+--+--+--+--+--+--+
195 +--+--+--+--+--+--+--+
197 Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR. If
198 (X,Y) = (0,0), the return value is the rule that runs horizontally above
199 the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
200 between that cell and cell (0,1); and so on, up to (0,NR), which runs
201 horizontally below cell (0,NR-1). */
203 table_get_rule (const struct table *table, enum table_axis axis, int x, int y)
205 assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
206 assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
207 return table->klass->get_rule (table, axis, x, y);
211 cell_contents_format_footnote_markers (const struct cell_contents *c,
214 for (size_t i = 0; i < c->n_footnotes; i++)
217 ds_put_byte (s, ',');
218 ds_put_cstr (s, c->footnotes[i]->marker);
222 static const struct footnote **
223 add_footnotes (const struct footnote **refs, size_t n_refs,
224 const struct footnote **footnotes, size_t *allocated, size_t *n)
226 for (size_t i = 0; i < n_refs; i++)
228 const struct footnote *f = refs[i];
229 if (f->idx >= *allocated)
231 size_t new_allocated = (f->idx + 1) * 2;
232 footnotes = xrealloc (footnotes, new_allocated * sizeof *footnotes);
233 while (*allocated < new_allocated)
234 footnotes[(*allocated)++] = NULL;
236 footnotes[f->idx] = f;
244 table_collect_footnotes (const struct table_item *item,
245 const struct footnote ***footnotesp)
247 const struct footnote **footnotes = NULL;
248 size_t allocated = 0;
251 struct table *t = item->table;
252 for (int y = 0; y < table_nr (t); y++)
254 struct table_cell cell;
255 for (int x = 0; x < table_nc (t); x = cell.d[TABLE_HORZ][1])
257 table_get_cell (t, x, y, &cell);
259 if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
260 for (size_t i = 0; i < cell.n_contents; i++)
262 const struct cell_contents *c = &cell.contents[i];
263 footnotes = add_footnotes (c->footnotes, c->n_footnotes,
264 footnotes, &allocated, &n);
266 table_cell_free (&cell);
270 const struct table_item_text *title = table_item_get_title (item);
272 footnotes = add_footnotes (title->footnotes, title->n_footnotes,
273 footnotes, &allocated, &n);
275 const struct table_item_text *caption = table_item_get_caption (item);
277 footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
278 footnotes, &allocated, &n);
280 *footnotesp = footnotes;
284 struct table_unshared
287 struct table *subtable;
290 static const struct table_class table_unshared_class;
292 /* Takes ownership of TABLE and returns a table with the same contents but
293 which is guaranteed not to be shared (as returned by table_is_shared()).
295 If TABLE is unshared, just returns TABLE.
297 The only real use for this function is to create a copy of TABLE in which
298 the headers can be adjusted, which is a pretty specialized use case. */
300 table_unshare (struct table *table)
302 if (!table_is_shared (table))
306 struct table_unshared *tiu = xmalloc (sizeof *tiu);
307 table_init (&tiu->table, &table_unshared_class);
308 table_set_nc (&tiu->table, table_nc (table));
309 table_set_nr (&tiu->table, table_nr (table));
310 table_set_hl (&tiu->table, table_hl (table));
311 table_set_hr (&tiu->table, table_hr (table));
312 table_set_ht (&tiu->table, table_ht (table));
313 table_set_hb (&tiu->table, table_hb (table));
314 tiu->subtable = table;
319 static struct table_unshared *
320 table_unshared_cast (const struct table *table)
322 assert (table->klass == &table_unshared_class);
323 return UP_CAST (table, struct table_unshared, table);
327 table_unshared_destroy (struct table *tiu_)
329 struct table_unshared *tiu = table_unshared_cast (tiu_);
330 table_unref (tiu->subtable);
335 table_unshared_get_cell (const struct table *tiu_, int x, int y,
336 struct table_cell *cell)
338 struct table_unshared *tiu = table_unshared_cast (tiu_);
339 table_get_cell (tiu->subtable, x, y, cell);
343 table_unshared_get_rule (const struct table *tiu_,
344 enum table_axis axis, int x, int y)
346 struct table_unshared *tiu = table_unshared_cast (tiu_);
347 return table_get_rule (tiu->subtable, axis, x, y);
350 static const struct table_class table_unshared_class =
352 table_unshared_destroy,
353 table_unshared_get_cell,
354 table_unshared_get_rule,
363 unsigned int options;
366 static const struct table_class table_string_class;
368 /* Returns a table that contains a single cell, whose contents are S with
369 options OPTIONS (a combination of TAB_* values). */
371 table_from_string (unsigned int options, const char *s)
373 struct table_string *ts = xmalloc (sizeof *ts);
374 table_init (&ts->table, &table_string_class);
375 ts->table.n[TABLE_HORZ] = ts->table.n[TABLE_VERT] = 1;
376 ts->string = xstrdup (s);
377 ts->options = options;
381 static struct table_string *
382 table_string_cast (const struct table *table)
384 assert (table->klass == &table_string_class);
385 return UP_CAST (table, struct table_string, table);
389 table_string_destroy (struct table *ts_)
391 struct table_string *ts = table_string_cast (ts_);
397 table_string_get_cell (const struct table *ts_, int x UNUSED, int y UNUSED,
398 struct table_cell *cell)
400 struct table_string *ts = table_string_cast (ts_);
401 cell->d[TABLE_HORZ][0] = 0;
402 cell->d[TABLE_HORZ][1] = 1;
403 cell->d[TABLE_VERT][0] = 0;
404 cell->d[TABLE_VERT][1] = 1;
405 cell->contents = &cell->inline_contents;
406 cell->inline_contents.options = ts->options;
407 cell->inline_contents.text = ts->string;
408 cell->inline_contents.n_footnotes = 0;
409 cell->n_contents = 1;
410 cell->destructor = NULL;
415 table_string_get_rule (const struct table *ts UNUSED,
416 enum table_axis axis UNUSED, int x UNUSED, int y UNUSED)
421 static const struct table_class table_string_class =
423 table_string_destroy,
424 table_string_get_cell,
425 table_string_get_rule,