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)
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;
102 area_style_clone (struct pool *pool, const struct area_style *old)
104 struct area_style *new = pool_malloc (pool, sizeof *new);
106 if (new->font_style.typeface)
107 new->font_style.typeface = pool_strdup (pool, new->font_style.typeface);
112 area_style_free (struct area_style *style)
116 free (style->font_style.typeface);
121 /* Initializes CELL with the contents of the table cell at column X and row Y
122 within TABLE. When CELL is no longer needed, the caller is responsible for
123 freeing it by calling table_cell_free(CELL).
125 The caller must ensure that CELL is destroyed before TABLE is unref'ed. */
127 table_get_cell (const struct table *table, int x, int y,
128 struct table_cell *cell)
130 assert (x >= 0 && x < table->n[TABLE_HORZ]);
131 assert (y >= 0 && y < table->n[TABLE_VERT]);
133 static const struct area_style default_style = AREA_STYLE_INITIALIZER;
134 cell->style = &default_style;
136 tab_get_cell (table, x, y, cell);
139 /* Returns one of the TAL_* enumeration constants (declared in output/table.h)
140 representing a rule running alongside one of the cells in TABLE.
142 Suppose NC is the number of columns in TABLE and NR is the number of rows.
143 Then, if AXIS is TABLE_HORZ, then 0 <= X <= NC and 0 <= Y < NR. If (X,Y) =
144 (0,0), the return value is the rule that runs vertically on the left side of
145 cell (0,0); if (X,Y) = (1,0), it is the vertical rule between that cell and
146 cell (1,0); and so on, up to (NC,0), which runs vertically on the right of
149 The following diagram illustrates the meaning of (X,Y) for AXIS = TABLE_HORZ
150 within a 7x7 table. The '|' characters at the intersection of the X labels
151 and Y labels show the rule whose style would be returned by calling
152 table_get_rule with those X and Y values:
155 +--+--+--+--+--+--+--+
157 +--+--+--+--+--+--+--+
159 +--+--+--+--+--+--+--+
161 +--+--+--+--+--+--+--+
163 +--+--+--+--+--+--+--+
165 +--+--+--+--+--+--+--+
167 +--+--+--+--+--+--+--+
169 +--+--+--+--+--+--+--+
171 Similarly, if AXIS is TABLE_VERT, then 0 <= X < NC and 0 <= Y <= NR. If
172 (X,Y) = (0,0), the return value is the rule that runs horizontally above
173 the top of cell (0,0); if (X,Y) = (0,1), it is the horizontal rule
174 between that cell and cell (0,1); and so on, up to (0,NR), which runs
175 horizontally below cell (0,NR-1). */
177 table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
178 struct cell_color *color)
180 assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
181 assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
182 *color = (struct cell_color) CELL_COLOR_BLACK;
183 return tab_get_rule (table, axis, x, y, color);
187 table_cell_format_footnote_markers (const struct table_cell *cell,
190 for (size_t i = 0; i < cell->n_footnotes; i++)
193 ds_put_byte (s, ',');
194 ds_put_cstr (s, cell->footnotes[i]->marker);
198 static const struct footnote **
199 add_footnotes (const struct footnote **refs, size_t n_refs,
200 const struct footnote **footnotes, size_t *allocated, size_t *n)
202 for (size_t i = 0; i < n_refs; i++)
204 const struct footnote *f = refs[i];
205 if (f->idx >= *allocated)
207 size_t new_allocated = (f->idx + 1) * 2;
208 footnotes = xrealloc (footnotes, new_allocated * sizeof *footnotes);
209 while (*allocated < new_allocated)
210 footnotes[(*allocated)++] = NULL;
212 footnotes[f->idx] = f;
220 table_collect_footnotes (const struct table_item *item,
221 const struct footnote ***footnotesp)
223 const struct footnote **footnotes = NULL;
224 size_t allocated = 0;
227 struct table *t = item->table;
228 for (int y = 0; y < table_nr (t); y++)
230 struct table_cell cell;
231 for (int x = 0; x < table_nc (t); x = cell.d[TABLE_HORZ][1])
233 table_get_cell (t, x, y, &cell);
235 if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
236 footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
237 footnotes, &allocated, &n);
241 const struct table_item_text *title = table_item_get_title (item);
243 footnotes = add_footnotes (title->footnotes, title->n_footnotes,
244 footnotes, &allocated, &n);
246 const struct table_item_layers *layers = table_item_get_layers (item);
249 for (size_t i = 0; i < layers->n_layers; i++)
250 footnotes = add_footnotes (layers->layers[i].footnotes,
251 layers->layers[i].n_footnotes,
252 footnotes, &allocated, &n);
255 const struct table_item_text *caption = table_item_get_caption (item);
257 footnotes = add_footnotes (caption->footnotes, caption->n_footnotes,
258 footnotes, &allocated, &n);
260 size_t n_nonnull = 0;
261 for (size_t i = 0; i < n; i++)
263 footnotes[n_nonnull++] = footnotes[i];
265 *footnotesp = footnotes;
269 /* Returns a table that contains a single cell, whose contents are the
270 left-aligned TEXT. */
272 table_from_string (const char *text)
274 struct tab_table *t = tab_create (1, 1);
275 tab_text (t, 0, 0, TAB_LEFT, text);
280 table_halign_to_string (enum table_halign halign)
284 case TABLE_HALIGN_LEFT: return "left";
285 case TABLE_HALIGN_CENTER: return "center";
286 case TABLE_HALIGN_RIGHT: return "right";
287 case TABLE_HALIGN_DECIMAL: return "decimal";
288 case TABLE_HALIGN_MIXED: return "mixed";
289 default: return "**error**";
294 table_valign_to_string (enum table_valign valign)
298 case TABLE_VALIGN_TOP: return "top";
299 case TABLE_VALIGN_CENTER: return "center";
300 case TABLE_VALIGN_BOTTOM: return "bottom";
301 default: return "**error**";
306 table_halign_interpret (enum table_halign halign, bool numeric)
310 case TABLE_HALIGN_LEFT:
311 case TABLE_HALIGN_CENTER:
312 case TABLE_HALIGN_RIGHT:
315 case TABLE_HALIGN_MIXED:
316 return numeric ? TABLE_HALIGN_RIGHT : TABLE_HALIGN_LEFT;
318 case TABLE_HALIGN_DECIMAL:
319 return TABLE_HALIGN_DECIMAL;
327 font_style_copy (struct font_style *dst, const struct font_style *src)
331 dst->typeface = xstrdup (dst->typeface);
335 font_style_uninit (struct font_style *font)
338 free (font->typeface);
342 area_style_copy (struct area_style *dst, const struct area_style *src)
344 font_style_copy (&dst->font_style, &src->font_style);
345 dst->cell_style = src->cell_style;
349 area_style_uninit (struct area_style *area)
352 font_style_uninit (&area->font_style);
356 table_stroke_to_string (enum table_stroke stroke)
360 case TABLE_STROKE_NONE: return "none";
361 case TABLE_STROKE_SOLID: return "solid";
362 case TABLE_STROKE_DASHED: return "dashed";
363 case TABLE_STROKE_THICK: return "thick";
364 case TABLE_STROKE_THIN: return "thin";
365 case TABLE_STROKE_DOUBLE: return "double";
372 cell_color_dump (const struct cell_color *c)
375 printf ("rgba(%d, %d, %d, %d)", c->r, c->g, c->b, c->alpha);
377 printf ("#%02"PRIx8"%02"PRIx8"%02"PRIx8, c->r, c->g, c->b);
381 font_style_dump (const struct font_style *f)
383 printf ("%s %dpx ", f->typeface, f->size);
384 cell_color_dump (&f->fg[0]);
386 cell_color_dump (&f->bg[0]);
387 if (!cell_color_equal (&f->fg[0], &f->fg[1])
388 || !cell_color_equal (&f->bg[0], &f->bg[1]))
391 cell_color_dump (&f->fg[1]);
393 cell_color_dump (&f->bg[1]);
396 fputs (" bold", stdout);
398 fputs (" italic", stdout);
400 fputs (" underline", stdout);
404 cell_style_dump (const struct cell_style *c)
406 fputs (table_halign_to_string (c->halign), stdout);
407 if (c->halign == TABLE_HALIGN_DECIMAL)
408 printf ("(%.2gpx)", c->decimal_offset);
409 printf (" %s", table_valign_to_string (c->valign));
410 printf (" %d,%d,%d,%dpx",
411 c->margin[TABLE_HORZ][0], c->margin[TABLE_HORZ][1],
412 c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);