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 "output/table-item.h"
29 #include "gl/xalloc.h"
31 /* Increases TABLE's reference count, indicating that it has an additional
32 owner. An table that is shared among multiple owners must not be
35 table_ref (const struct table *table_)
37 struct table *table = CONST_CAST (struct table *, table_);
42 /* Decreases TABLE's reference count, indicating that it has one fewer owner.
43 If TABLE no longer has any owners, it is freed. */
45 table_unref (struct table *table)
49 assert (table->ref_cnt > 0);
50 if (--table->ref_cnt == 0)
51 table->klass->destroy (table);
55 /* Returns true if TABLE has more than one owner. A table item that is shared
56 among multiple owners must not be modified. */
58 table_is_shared (const struct table *table)
60 return table->ref_cnt > 1;
63 /* Sets the number of left header columns in TABLE to HL. */
65 table_set_hl (struct table *table, int hl)
67 assert (!table_is_shared (table));
68 table->h[TABLE_HORZ][0] = hl;
71 /* Sets the number of right header columns in TABLE to HR. */
73 table_set_hr (struct table *table, int hr)
75 assert (!table_is_shared (table));
76 table->h[TABLE_HORZ][1] = hr;
79 /* Sets the number of top header rows in TABLE to HT. */
81 table_set_ht (struct table *table, int ht)
83 assert (!table_is_shared (table));
84 table->h[TABLE_VERT][0] = ht;
87 /* Sets the number of top header rows in TABLE to HB. */
89 table_set_hb (struct table *table, int hb)
91 assert (!table_is_shared (table));
92 table->h[TABLE_VERT][1] = hb;
95 /* Initializes TABLE as a table of the specified CLASS, initially with a
98 TABLE initially has 0 rows and columns and no headers. The table
99 implementation should update the numbers of rows and columns. The table
100 implementation (or its client) may update the header rows and columns.
102 A table is an abstract class, that is, a plain struct table is not useful on
103 its own. Thus, this function is normally called from the initialization
104 function of some subclass of table. */
106 table_init (struct table *table, const struct table_class *class)
108 table->klass = class;
109 table->n[TABLE_HORZ] = table->n[TABLE_VERT] = 0;
110 table->h[TABLE_HORZ][0] = table->h[TABLE_HORZ][1] = 0;
111 table->h[TABLE_VERT][0] = table->h[TABLE_VERT][1] = 0;
115 /* Sets the number of columns in TABLE to NC. */
117 table_set_nc (struct table *table, int nc)
119 assert (!table_is_shared (table));
120 table->n[TABLE_HORZ] = nc;
123 /* Sets the number of rows in TABLE to NR. */
125 table_set_nr (struct table *table, int nr)
127 assert (!table_is_shared (table));
128 table->n[TABLE_VERT] = nr;
131 /* Initializes CELL with the contents of the table cell at column X and row Y
132 within TABLE. When CELL is no longer needed, the caller is responsible for
133 freeing it by calling table_cell_free(CELL).
135 The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
137 table_get_cell (const struct table *table, int x, int y,
138 struct table_cell *cell)
140 assert (x >= 0 && x < table->n[TABLE_HORZ]);
141 assert (y >= 0 && y < table->n[TABLE_VERT]);
142 table->klass->get_cell (table, x, y, cell);
145 /* Frees CELL, which should have been initialized by calling
148 table_cell_free (struct table_cell *cell)
150 if (cell->destructor != NULL)
151 cell->destructor (cell->destructor_aux);
154 /* Returns one of the TAL_* enumeration constants (declared in output/table.h)
155 representing a rule running alongside one of the cells in TABLE.
157 Suppose NC is the number of columns in TABLE and NR is the number of rows.
158 Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR. If (X,Y) =
159 (0,0), the return value is the rule that runs vertically on the left side of
160 cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
161 cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
164 The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
165 within a 7x7 table. The '|' characters at the intersection of the X labels
166 and Y labels show the rule whose style would be returned by calling
167 table_get_rule with those X and Y values:
170 +--+--+--+--+--+--+--+
172 +--+--+--+--+--+--+--+
174 +--+--+--+--+--+--+--+
176 +--+--+--+--+--+--+--+
178 +--+--+--+--+--+--+--+
180 +--+--+--+--+--+--+--+
182 +--+--+--+--+--+--+--+
184 +--+--+--+--+--+--+--+
186 Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR. If
187 (X,Y) = (0,0), the return value is the rule that runs horizontally above
188 the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
189 between that cell and cell (0,1); and so on, up to (0,NR), which runs
190 horizontally below cell (0,NR-1). */
192 table_get_rule (const struct table *table, enum table_axis axis, int x, int y)
194 assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
195 assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
196 return table->klass->get_rule (table, axis, x, y);
199 struct table_unshared
202 struct table *subtable;
205 static const struct table_class table_unshared_class;
207 /* Takes ownership of TABLE and returns a table with the same contents but
208 which is guaranteed not to be shared (as returned by table_is_shared()).
210 If TABLE is unshared, just returns TABLE.
212 The only real use for this function is to create a copy of TABLE in which
213 the headers can be adjusted, which is a pretty specialized use case. */
215 table_unshare (struct table *table)
217 if (!table_is_shared (table))
221 struct table_unshared *tiu = xmalloc (sizeof *tiu);
222 table_init (&tiu->table, &table_unshared_class);
223 table_set_nc (&tiu->table, table_nc (table));
224 table_set_nr (&tiu->table, table_nr (table));
225 table_set_hl (&tiu->table, table_hl (table));
226 table_set_hr (&tiu->table, table_hr (table));
227 table_set_ht (&tiu->table, table_ht (table));
228 table_set_hb (&tiu->table, table_hb (table));
229 tiu->subtable = table;
234 static struct table_unshared *
235 table_unshared_cast (const struct table *table)
237 assert (table->klass == &table_unshared_class);
238 return UP_CAST (table, struct table_unshared, table);
242 table_unshared_destroy (struct table *tiu_)
244 struct table_unshared *tiu = table_unshared_cast (tiu_);
245 table_unref (tiu->subtable);
250 table_unshared_get_cell (const struct table *tiu_, int x, int y,
251 struct table_cell *cell)
253 struct table_unshared *tiu = table_unshared_cast (tiu_);
254 table_get_cell (tiu->subtable, x, y, cell);
258 table_unshared_get_rule (const struct table *tiu_,
259 enum table_axis axis, int x, int y)
261 struct table_unshared *tiu = table_unshared_cast (tiu_);
262 return table_get_rule (tiu->subtable, axis, x, y);
265 static const struct table_class table_unshared_class =
267 table_unshared_destroy,
268 table_unshared_get_cell,
269 table_unshared_get_rule,
278 unsigned int options;
281 static const struct table_class table_string_class;
283 /* Returns a table that contains a single cell, whose contents are S with
284 options OPTIONS (a combination of TAB_* values). */
286 table_from_string (unsigned int options, const char *s)
288 struct table_string *ts = xmalloc (sizeof *ts);
289 table_init (&ts->table, &table_string_class);
290 ts->table.n[TABLE_HORZ] = ts->table.n[TABLE_VERT] = 1;
291 ts->string = xstrdup (s);
292 ts->options = options;
296 static struct table_string *
297 table_string_cast (const struct table *table)
299 assert (table->klass == &table_string_class);
300 return UP_CAST (table, struct table_string, table);
304 table_string_destroy (struct table *ts_)
306 struct table_string *ts = table_string_cast (ts_);
312 table_string_get_cell (const struct table *ts_, int x UNUSED, int y UNUSED,
313 struct table_cell *cell)
315 struct table_string *ts = table_string_cast (ts_);
316 cell->d[TABLE_HORZ][0] = 0;
317 cell->d[TABLE_HORZ][1] = 1;
318 cell->d[TABLE_VERT][0] = 0;
319 cell->d[TABLE_VERT][1] = 1;
320 cell->contents = &cell->inline_contents;
321 cell->inline_contents.options = ts->options;
322 cell->inline_contents.text = ts->string;
323 cell->inline_contents.n_footnotes = 0;
324 cell->n_contents = 1;
325 cell->destructor = NULL;
330 table_string_get_rule (const struct table *ts UNUSED,
331 enum table_axis axis UNUSED, int x UNUSED, int y UNUSED)
336 static const struct table_class table_string_class =
338 table_string_destroy,
339 table_string_get_cell,
340 table_string_get_rule,