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 0 rows and columns and no headers. The table
105 implementation should update the numbers of rows and columns. The table
106 implementation (or its client) may update the header rows and columns.
108 A table is an abstract class, that is, a plain struct table is not useful on
109 its own. Thus, this function is normally called from the initialization
110 function of some subclass of table. */
112 table_init (struct table *table, const struct table_class *class)
114 table->klass = class;
115 table->n[TABLE_HORZ] = table->n[TABLE_VERT] = 0;
116 table->h[TABLE_HORZ][0] = table->h[TABLE_HORZ][1] = 0;
117 table->h[TABLE_VERT][0] = table->h[TABLE_VERT][1] = 0;
121 /* Sets the number of columns in TABLE to NC. */
123 table_set_nc (struct table *table, int nc)
125 assert (!table_is_shared (table));
126 table->n[TABLE_HORZ] = nc;
129 /* Sets the number of rows in TABLE to NR. */
131 table_set_nr (struct table *table, int nr)
133 assert (!table_is_shared (table));
134 table->n[TABLE_VERT] = nr;
138 area_style_clone (struct pool *pool, const struct area_style *old)
140 struct area_style *new = pool_malloc (pool, sizeof *new);
142 if (new->font_style.typeface)
143 new->font_style.typeface = pool_strdup (pool, new->font_style.typeface);
148 area_style_free (struct area_style *style)
152 free (style->font_style.typeface);
157 /* Initializes CELL with the contents of the table cell at column X and row Y
158 within TABLE. When CELL is no longer needed, the caller is responsible for
159 freeing it by calling table_cell_free(CELL).
161 The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
163 table_get_cell (const struct table *table, int x, int y,
164 struct table_cell *cell)
166 assert (x >= 0 && x < table->n[TABLE_HORZ]);
167 assert (y >= 0 && y < table->n[TABLE_VERT]);
169 static const struct area_style default_style = AREA_STYLE_INITIALIZER;
170 cell->style = &default_style;
172 table->klass->get_cell (table, x, y, cell);
175 /* Returns one of the TAL_* enumeration constants (declared in output/table.h)
176 representing a rule running alongside one of the cells in TABLE.
178 Suppose NC is the number of columns in TABLE and NR is the number of rows.
179 Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR. If (X,Y) =
180 (0,0), the return value is the rule that runs vertically on the left side of
181 cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
182 cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
185 The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
186 within a 7x7 table. The '|' characters at the intersection of the X labels
187 and Y labels show the rule whose style would be returned by calling
188 table_get_rule with those X and Y values:
191 +--+--+--+--+--+--+--+
193 +--+--+--+--+--+--+--+
195 +--+--+--+--+--+--+--+
197 +--+--+--+--+--+--+--+
199 +--+--+--+--+--+--+--+
201 +--+--+--+--+--+--+--+
203 +--+--+--+--+--+--+--+
205 +--+--+--+--+--+--+--+
207 Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR. If
208 (X,Y) = (0,0), the return value is the rule that runs horizontally above
209 the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
210 between that cell and cell (0,1); and so on, up to (0,NR), which runs
211 horizontally below cell (0,NR-1). */
213 table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
214 struct cell_color *color)
216 assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
217 assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
218 *color = (struct cell_color) CELL_COLOR_BLACK;
219 return table->klass->get_rule (table, axis, x, y, color);
223 table_cell_format_footnote_markers (const struct table_cell *cell,
226 for (size_t i = 0; i < cell->n_footnotes; i++)
229 ds_put_byte (s, ',');
230 ds_put_cstr (s, cell->footnotes[i]->marker);
234 static const struct footnote **
235 add_footnotes (const struct footnote **refs, size_t n_refs,
236 const struct footnote **footnotes, size_t *allocated, size_t *n)
238 for (size_t i = 0; i < n_refs; i++)
240 const struct footnote *f = refs[i];
241 if (f->idx >= *allocated)
243 size_t new_allocated = (f->idx + 1) * 2;
244 footnotes = xrealloc (footnotes, new_allocated * sizeof *footnotes);
245 while (*allocated < new_allocated)
246 footnotes[(*allocated)++] = NULL;
248 footnotes[f->idx] = f;
256 table_collect_footnotes (const struct table_item *item,
257 const struct footnote ***footnotesp)
259 const struct footnote **footnotes = NULL;
260 size_t allocated = 0;
263 struct table *t = item->table;
264 for (int y = 0; y < table_nr (t); y++)
266 struct table_cell cell;
267 for (int x = 0; x < table_nc (t); x = cell.d[TABLE_HORZ][1])
269 table_get_cell (t, x, y, &cell);
271 if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
272 footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
273 footnotes, &allocated, &n);
277 const struct table_item_text *title = table_item_get_title (item);
279 footnotes = add_footnotes (title->footnotes, title->n_footnotes,
280 footnotes, &allocated, &n);
282 const struct table_item_layers *layers = table_item_get_layers (item);
285 for (size_t i = 0; i < layers->n_layers; i++)
286 footnotes = add_footnotes (layers->layers[i].footnotes,
287 layers->layers[i].n_footnotes,
288 footnotes, &allocated, &n);
291 const struct table_item_text *caption = table_item_get_caption (item);
293 footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
294 footnotes, &allocated, &n);
296 size_t n_nonnull = 0;
297 for (size_t i = 0; i < n; i++)
299 footnotes[n_nonnull++] = footnotes[i];
301 *footnotesp = footnotes;
305 /* Returns a table that contains a single cell, whose contents are the
306 left-aligned TEXT. */
308 table_from_string (const char *text)
310 struct tab_table *t = tab_create (1, 1);
311 tab_text (t, 0, 0, TAB_LEFT, text);
316 table_halign_to_string (enum table_halign halign)
320 case TABLE_HALIGN_LEFT: return "left";
321 case TABLE_HALIGN_CENTER: return "center";
322 case TABLE_HALIGN_RIGHT: return "right";
323 case TABLE_HALIGN_DECIMAL: return "decimal";
324 case TABLE_HALIGN_MIXED: return "mixed";
325 default: return "**error**";
330 table_valign_to_string (enum table_valign valign)
334 case TABLE_VALIGN_TOP: return "top";
335 case TABLE_VALIGN_CENTER: return "center";
336 case TABLE_VALIGN_BOTTOM: return "bottom";
337 default: return "**error**";
342 table_halign_interpret (enum table_halign halign, bool numeric)
346 case TABLE_HALIGN_LEFT:
347 case TABLE_HALIGN_CENTER:
348 case TABLE_HALIGN_RIGHT:
351 case TABLE_HALIGN_MIXED:
352 return numeric ? TABLE_HALIGN_RIGHT : TABLE_HALIGN_LEFT;
354 case TABLE_HALIGN_DECIMAL:
355 return TABLE_HALIGN_DECIMAL;
363 font_style_copy (struct font_style *dst, const struct font_style *src)
367 dst->typeface = xstrdup (dst->typeface);
371 font_style_uninit (struct font_style *font)
374 free (font->typeface);
378 area_style_copy (struct area_style *dst, const struct area_style *src)
380 font_style_copy (&dst->font_style, &src->font_style);
381 dst->cell_style = src->cell_style;
385 area_style_uninit (struct area_style *area)
388 font_style_uninit (&area->font_style);
392 table_stroke_to_string (enum table_stroke stroke)
396 case TABLE_STROKE_NONE: return "none";
397 case TABLE_STROKE_SOLID: return "solid";
398 case TABLE_STROKE_DASHED: return "dashed";
399 case TABLE_STROKE_THICK: return "thick";
400 case TABLE_STROKE_THIN: return "thin";
401 case TABLE_STROKE_DOUBLE: return "double";
408 cell_color_dump (const struct cell_color *c)
411 printf ("rgba(%d, %d, %d, %d)", c->r, c->g, c->b, c->alpha);
413 printf ("#%02"PRIx8"%02"PRIx8"%02"PRIx8, c->r, c->g, c->b);
417 font_style_dump (const struct font_style *f)
419 printf ("%s %dpx ", f->typeface, f->size);
420 cell_color_dump (&f->fg[0]);
422 cell_color_dump (&f->bg[0]);
423 if (!cell_color_equal (&f->fg[0], &f->fg[1])
424 || !cell_color_equal (&f->bg[0], &f->bg[1]))
427 cell_color_dump (&f->fg[1]);
429 cell_color_dump (&f->bg[1]);
432 fputs (" bold", stdout);
434 fputs (" italic", stdout);
436 fputs (" underline", stdout);
440 cell_style_dump (const struct cell_style *c)
442 fputs (table_halign_to_string (c->halign), stdout);
443 if (c->halign == TABLE_HALIGN_DECIMAL)
444 printf ("(%.2gpx)", c->decimal_offset);
445 printf (" %s", table_valign_to_string (c->valign));
446 printf (" %d,%d,%d,%dpx",
447 c->margin[TABLE_HORZ][0], c->margin[TABLE_HORZ][1],
448 c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);