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"
26 #include "data/format.h"
27 #include "libpspp/assertion.h"
28 #include "libpspp/cast.h"
29 #include "libpspp/compiler.h"
30 #include "libpspp/pool.h"
31 #include "libpspp/str.h"
32 #include "output/table-item.h"
33 #include "output/tab.h"
35 #include "gl/xalloc.h"
37 /* Increases TABLE's reference count, indicating that it has an additional
38 owner. An table that is shared among multiple owners must not be
41 table_ref (const struct table *table_)
43 struct table *table = CONST_CAST (struct table *, table_);
48 /* Decreases TABLE's reference count, indicating that it has one fewer owner.
49 If TABLE no longer has any owners, it is freed. */
51 table_unref (struct table *table)
55 assert (table->ref_cnt > 0);
56 if (--table->ref_cnt == 0)
57 table->klass->destroy (table);
61 /* Returns true if TABLE has more than one owner. A table item that is shared
62 among multiple owners must not be modified. */
64 table_is_shared (const struct table *table)
66 return table->ref_cnt > 1;
69 /* Sets the number of left header columns in TABLE to HL. */
71 table_set_hl (struct table *table, int hl)
73 assert (!table_is_shared (table));
74 table->h[TABLE_HORZ][0] = hl;
77 /* Sets the number of right header columns in TABLE to HR. */
79 table_set_hr (struct table *table, int hr)
81 assert (!table_is_shared (table));
82 table->h[TABLE_HORZ][1] = hr;
85 /* Sets the number of top header rows in TABLE to HT. */
87 table_set_ht (struct table *table, int ht)
89 assert (!table_is_shared (table));
90 table->h[TABLE_VERT][0] = ht;
93 /* Sets the number of top header rows in TABLE to HB. */
95 table_set_hb (struct table *table, int hb)
97 assert (!table_is_shared (table));
98 table->h[TABLE_VERT][1] = hb;
101 /* Initializes TABLE as a table of the specified CLASS, initially with a
102 reference count of 1.
104 TABLE initially has NR rows and NC columns and no headers. The table
105 implementation (or its client) may update the header rows and columns.
107 A table is an abstract class, that is, a plain struct table is not useful on
108 its own. Thus, this function is normally called from the initialization
109 function of some subclass of table. */
111 table_init (struct table *table, const struct table_class *class,
114 table->klass = class;
115 table->n[TABLE_HORZ] = nc;
116 table->n[TABLE_VERT] = nr;
117 table->h[TABLE_HORZ][0] = table->h[TABLE_HORZ][1] = 0;
118 table->h[TABLE_VERT][0] = table->h[TABLE_VERT][1] = 0;
123 area_style_clone (struct pool *pool, const struct area_style *old)
125 struct area_style *new = pool_malloc (pool, sizeof *new);
127 if (new->font_style.typeface)
128 new->font_style.typeface = pool_strdup (pool, new->font_style.typeface);
133 area_style_free (struct area_style *style)
137 free (style->font_style.typeface);
142 /* Initializes CELL with the contents of the table cell at column X and row Y
143 within TABLE. When CELL is no longer needed, the caller is responsible for
144 freeing it by calling table_cell_free(CELL).
146 The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
148 table_get_cell (const struct table *table, int x, int y,
149 struct table_cell *cell)
151 assert (x >= 0 && x < table->n[TABLE_HORZ]);
152 assert (y >= 0 && y < table->n[TABLE_VERT]);
154 static const struct area_style default_style = AREA_STYLE_INITIALIZER;
155 cell->style = &default_style;
157 table->klass->get_cell (table, x, y, cell);
160 /* Returns one of the TAL_* enumeration constants (declared in output/table.h)
161 representing a rule running alongside one of the cells in TABLE.
163 Suppose NC is the number of columns in TABLE and NR is the number of rows.
164 Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR. If (X,Y) =
165 (0,0), the return value is the rule that runs vertically on the left side of
166 cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
167 cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
170 The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
171 within a 7x7 table. The '|' characters at the intersection of the X labels
172 and Y labels show the rule whose style would be returned by calling
173 table_get_rule with those X and Y values:
176 +--+--+--+--+--+--+--+
178 +--+--+--+--+--+--+--+
180 +--+--+--+--+--+--+--+
182 +--+--+--+--+--+--+--+
184 +--+--+--+--+--+--+--+
186 +--+--+--+--+--+--+--+
188 +--+--+--+--+--+--+--+
190 +--+--+--+--+--+--+--+
192 Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR. If
193 (X,Y) = (0,0), the return value is the rule that runs horizontally above
194 the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
195 between that cell and cell (0,1); and so on, up to (0,NR), which runs
196 horizontally below cell (0,NR-1). */
198 table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
199 struct cell_color *color)
201 assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
202 assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
203 *color = (struct cell_color) CELL_COLOR_BLACK;
204 return table->klass->get_rule (table, axis, x, y, color);
208 table_cell_format_footnote_markers (const struct table_cell *cell,
211 for (size_t i = 0; i < cell->n_footnotes; i++)
214 ds_put_byte (s, ',');
215 ds_put_cstr (s, cell->footnotes[i]->marker);
219 static const struct footnote **
220 add_footnotes (const struct footnote **refs, size_t n_refs,
221 const struct footnote **footnotes, size_t *allocated, size_t *n)
223 for (size_t i = 0; i < n_refs; i++)
225 const struct footnote *f = refs[i];
226 if (f->idx >= *allocated)
228 size_t new_allocated = (f->idx + 1) * 2;
229 footnotes = xrealloc (footnotes, new_allocated * sizeof *footnotes);
230 while (*allocated < new_allocated)
231 footnotes[(*allocated)++] = NULL;
233 footnotes[f->idx] = f;
241 table_collect_footnotes (const struct table_item *item,
242 const struct footnote ***footnotesp)
244 const struct footnote **footnotes = NULL;
245 size_t allocated = 0;
248 struct table *t = item->table;
249 for (int y = 0; y < table_nr (t); y++)
251 struct table_cell cell;
252 for (int x = 0; x < table_nc (t); x = cell.d[TABLE_HORZ][1])
254 table_get_cell (t, x, y, &cell);
256 if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
257 footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
258 footnotes, &allocated, &n);
262 const struct table_item_text *title = table_item_get_title (item);
264 footnotes = add_footnotes (title->footnotes, title->n_footnotes,
265 footnotes, &allocated, &n);
267 const struct table_item_layers *layers = table_item_get_layers (item);
270 for (size_t i = 0; i < layers->n_layers; i++)
271 footnotes = add_footnotes (layers->layers[i].footnotes,
272 layers->layers[i].n_footnotes,
273 footnotes, &allocated, &n);
276 const struct table_item_text *caption = table_item_get_caption (item);
278 footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
279 footnotes, &allocated, &n);
281 size_t n_nonnull = 0;
282 for (size_t i = 0; i < n; i++)
284 footnotes[n_nonnull++] = footnotes[i];
286 *footnotesp = footnotes;
290 /* Returns a table that contains a single cell, whose contents are the
291 left-aligned TEXT. */
293 table_from_string (const char *text)
295 struct tab_table *t = tab_create (1, 1);
296 tab_text (t, 0, 0, TAB_LEFT, text);
301 table_halign_to_string (enum table_halign halign)
305 case TABLE_HALIGN_LEFT: return "left";
306 case TABLE_HALIGN_CENTER: return "center";
307 case TABLE_HALIGN_RIGHT: return "right";
308 case TABLE_HALIGN_DECIMAL: return "decimal";
309 case TABLE_HALIGN_MIXED: return "mixed";
310 default: return "**error**";
315 table_valign_to_string (enum table_valign valign)
319 case TABLE_VALIGN_TOP: return "top";
320 case TABLE_VALIGN_CENTER: return "center";
321 case TABLE_VALIGN_BOTTOM: return "bottom";
322 default: return "**error**";
327 table_halign_interpret (enum table_halign halign, bool numeric)
331 case TABLE_HALIGN_LEFT:
332 case TABLE_HALIGN_CENTER:
333 case TABLE_HALIGN_RIGHT:
336 case TABLE_HALIGN_MIXED:
337 return numeric ? TABLE_HALIGN_RIGHT : TABLE_HALIGN_LEFT;
339 case TABLE_HALIGN_DECIMAL:
340 return TABLE_HALIGN_DECIMAL;
348 font_style_copy (struct font_style *dst, const struct font_style *src)
352 dst->typeface = xstrdup (dst->typeface);
356 font_style_uninit (struct font_style *font)
359 free (font->typeface);
363 area_style_copy (struct area_style *dst, const struct area_style *src)
365 font_style_copy (&dst->font_style, &src->font_style);
366 dst->cell_style = src->cell_style;
370 area_style_uninit (struct area_style *area)
373 font_style_uninit (&area->font_style);
377 table_stroke_to_string (enum table_stroke stroke)
381 case TABLE_STROKE_NONE: return "none";
382 case TABLE_STROKE_SOLID: return "solid";
383 case TABLE_STROKE_DASHED: return "dashed";
384 case TABLE_STROKE_THICK: return "thick";
385 case TABLE_STROKE_THIN: return "thin";
386 case TABLE_STROKE_DOUBLE: return "double";
393 cell_color_dump (const struct cell_color *c)
396 printf ("rgba(%d, %d, %d, %d)", c->r, c->g, c->b, c->alpha);
398 printf ("#%02"PRIx8"%02"PRIx8"%02"PRIx8, c->r, c->g, c->b);
402 font_style_dump (const struct font_style *f)
404 printf ("%s %dpx ", f->typeface, f->size);
405 cell_color_dump (&f->fg[0]);
407 cell_color_dump (&f->bg[0]);
408 if (!cell_color_equal (&f->fg[0], &f->fg[1])
409 || !cell_color_equal (&f->bg[0], &f->bg[1]))
412 cell_color_dump (&f->fg[1]);
414 cell_color_dump (&f->bg[1]);
417 fputs (" bold", stdout);
419 fputs (" italic", stdout);
421 fputs (" underline", stdout);
425 cell_style_dump (const struct cell_style *c)
427 fputs (table_halign_to_string (c->halign), stdout);
428 if (c->halign == TABLE_HALIGN_DECIMAL)
429 printf ("(%.2gpx)", c->decimal_offset);
430 printf (" %s", table_valign_to_string (c->valign));
431 printf (" %d,%d,%d,%dpx",
432 c->margin[TABLE_HORZ][0], c->margin[TABLE_HORZ][1],
433 c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);