1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997, 1998, 1999, 2000, 2009, 2013, 2014 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #ifndef OUTPUT_TABLE_H
18 #define OUTPUT_TABLE_H 1
19
20 /* Tables.
21
22 . A table is a rectangular grid of cells. Cells can be joined to form larger
23 cells. Rows and columns can be separated by rules of various types. Rows
24 at the top and bottom of a table and columns at the left and right edges of
25 a table can be designated as headers, which means that if the table must be
26 broken across more than one page, those rows or columns are repeated on each
27 page.
28
29 A table is not itself an output_item, and thus a table cannot by itself be
30 used for output, but they can be embedded inside struct table_item (see
31 table-item.h) for that purpose. */
32
33 #include <stdbool.h>
34 #include <stdint.h>
35 #include <stddef.h>
36 #include "libpspp/compiler.h"
37
38 struct casereader;
39 struct fmt_spec;
40 struct pool;
41 struct table_item;
42 struct variable;
43
44 /* A table axis.
45
46 Many table-related declarations use 2-element arrays in place of "x" and "y"
47 variables. This reduces code duplication significantly, because much table
48 code treats rows and columns the same way.
49
50 A lot of code that uses these enumerations assumes that the two values are 0
51 and 1, so don't change them to other values. */
52 enum table_axis
53 {
54 TABLE_HORZ,
55 TABLE_VERT
56 #define TABLE_N_AXES 2
57 };
58
59 struct cell_color
60 {
61 uint8_t alpha, r, g, b;
62 };
63
64 #define CELL_COLOR(r, g, b) { 255, r, g, b }
65 #define CELL_COLOR_BLACK CELL_COLOR (0, 0, 0)
66 #define CELL_COLOR_WHITE CELL_COLOR (255, 255, 255)
67
68 static inline bool
cell_color_equal(const struct cell_color * a,const struct cell_color * b)69 cell_color_equal (const struct cell_color *a, const struct cell_color *b)
70 {
71 return a->alpha == b->alpha && a->r == b->r && a->g == b->g && a->b == b->b;
72 }
73
74 void cell_color_dump (const struct cell_color *);
75
76 enum table_stroke
77 {
78 TABLE_STROKE_NONE,
79 TABLE_STROKE_SOLID,
80 TABLE_STROKE_DASHED,
81 TABLE_STROKE_THICK,
82 TABLE_STROKE_THIN,
83 TABLE_STROKE_DOUBLE,
84 TABLE_N_STROKES,
85 };
86
87 const char *table_stroke_to_string (enum table_stroke);
88
89 /* Given strokes A and B, returns a stroke that "combines" them, that is, that
90 gives a reasonable stroke choice for a rule for different reasons should
91 have both styles A and B. */
92 static inline int
table_stroke_combine(enum table_stroke a,enum table_stroke b)93 table_stroke_combine (enum table_stroke a, enum table_stroke b)
94 {
95 return a > b ? a : b;
96 }
97
98 struct table_border_style
99 {
100 enum table_stroke stroke;
101 struct cell_color color;
102 };
103
104 #define TABLE_BORDER_STYLE_INITIALIZER { TABLE_STROKE_SOLID, CELL_COLOR_BLACK }
105
106 enum table_halign
107 {
108 TABLE_HALIGN_RIGHT,
109 TABLE_HALIGN_LEFT,
110 TABLE_HALIGN_CENTER,
111 TABLE_HALIGN_MIXED,
112 TABLE_HALIGN_DECIMAL
113 };
114
115 const char *table_halign_to_string (enum table_halign);
116
117 enum table_valign
118 {
119 TABLE_VALIGN_TOP,
120 TABLE_VALIGN_CENTER,
121 TABLE_VALIGN_BOTTOM,
122 };
123
124 const char *table_valign_to_string (enum table_valign);
125
126 struct cell_style
127 {
128 enum table_halign halign;
129 enum table_valign valign;
130 double decimal_offset; /* In 1/96" units. */
131 char decimal_char; /* Either '.' or ','. */
132 int margin[TABLE_N_AXES][2]; /* In 1/96" units. */
133 };
134
135 #define CELL_STYLE_INITIALIZER { CELL_STYLE_INITIALIZER__ }
136 #define CELL_STYLE_INITIALIZER__ \
137 .margin = { [TABLE_HORZ][0] = 8, [TABLE_HORZ][1] = 11, \
138 [TABLE_VERT][0] = 1, [TABLE_VERT][1] = 1 }
139
140 void cell_style_dump (const struct cell_style *);
141
142 struct font_style
143 {
144 bool bold, italic, underline, markup;
145 struct cell_color fg[2], bg[2];
146 char *typeface;
147 int size;
148 };
149
150 #define FONT_STYLE_INITIALIZER { FONT_STYLE_INITIALIZER__ }
151 #define FONT_STYLE_INITIALIZER__ \
152 .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK}, \
153 .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE},
154
155 void font_style_copy (struct pool *,
156 struct font_style *, const struct font_style *);
157 void font_style_uninit (struct font_style *);
158 void font_style_dump (const struct font_style *);
159
160 struct area_style
161 {
162 struct cell_style cell_style;
163 struct font_style font_style;
164 };
165
166 #define AREA_STYLE_INITIALIZER { AREA_STYLE_INITIALIZER__ }
167 #define AREA_STYLE_INITIALIZER__ \
168 .cell_style = CELL_STYLE_INITIALIZER, \
169 .font_style = FONT_STYLE_INITIALIZER
170
171 struct area_style *area_style_clone (struct pool *, const struct area_style *);
172 void area_style_copy (struct pool *,
173 struct area_style *, const struct area_style *);
174 void area_style_uninit (struct area_style *);
175 void area_style_free (struct area_style *);
176
177 /* Properties of a table cell. */
178 enum
179 {
180 TAB_NONE = 0,
181 TAB_FIX = 1 << 1, /* Use fixed font. */
182 TAB_MARKUP = 1 << 2, /* Text contains Pango markup. */
183 TAB_NUMERIC = 1 << 3, /* Cell contents are numeric. */
184 TAB_ROTATE = 1 << 4, /* Rotate cell contents 90 degrees. */
185
186 TAB_STYLE_SHIFT = 5,
187 TAB_STYLE_MASK = 7 << TAB_STYLE_SHIFT,
188
189 /* Internal use by tab.c only. */
190 TAB_JOIN = 1 << 14,
191 };
192
193 /* A table. */
194 struct table
195 {
196 struct pool *container;
197
198 /* Table size.
199
200 n[TABLE_HORZ]: Number of columns.
201 n[TABLE_VERT]: Number of rows. */
202 int n[TABLE_N_AXES];
203
204 /* Table headers.
205
206 Rows at the top and bottom of a table and columns at the left and right
207 edges of a table can be designated as headers. If the table must be
208 broken across more than one page for output, headers rows and columns
209 are repeated on each page.
210
211 h[TABLE_HORZ][0]: Left header columns.
212 h[TABLE_HORZ][1]: Right header columns.
213 h[TABLE_VERT][0]: Top header rows.
214 h[TABLE_VERT][1]: Bottom header rows. */
215 int h[TABLE_N_AXES][2];
216
217 /* Reference count. A table may be shared between multiple owners,
218 indicated by a reference count greater than 1. When this is the case,
219 the table must not be modified. */
220 int ref_cnt;
221
222 /* Table contents.
223
224 Each array element in cc[] is ordinarily a "char *" pointer to a string.
225 If TAB_JOIN (defined in table.c) is set in ct[] for the element,
226 however, it is a joined cell and the corresponding element of cc[]
227 points to a struct table_cell. */
228 void **cc; /* Cell contents; void *[nr][nc]. */
229 unsigned short *ct; /* Cell types; unsigned short[nr][nc]. */
230 struct area_style *styles[8];
231
232 /* Rules. */
233 unsigned char *rh; /* Horiz rules; unsigned char[nr+1][nc]. */
234 unsigned char *rv; /* Vert rules; unsigned char[nr][nc+1]. */
235 struct cell_color *rule_colors[32];
236 };
237
238 /* Reference counting. */
239 struct table *table_ref (const struct table *);
240 void table_unref (struct table *);
241 bool table_is_shared (const struct table *);
242
243 /* Returns the number of columns or rows, respectively, in T. */
table_nc(const struct table * t)244 static inline int table_nc (const struct table *t)
245 { return t->n[TABLE_HORZ]; }
table_nr(const struct table * t)246 static inline int table_nr (const struct table *t)
247 { return t->n[TABLE_VERT]; }
248
249 /* Returns the number of left, right, top, or bottom headers, respectively, in
250 T. */
table_hl(const struct table * t)251 static inline int table_hl (const struct table *t)
252 { return t->h[TABLE_HORZ][0]; }
table_hr(const struct table * t)253 static inline int table_hr (const struct table *t)
254 { return t->h[TABLE_HORZ][1]; }
table_ht(const struct table * t)255 static inline int table_ht (const struct table *t)
256 { return t->h[TABLE_VERT][0]; }
table_hb(const struct table * t)257 static inline int table_hb (const struct table *t)
258 { return t->h[TABLE_VERT][1]; }
259
260 /* Simple kinds of output. */
261 struct table *table_from_string (const char *);
262 void table_output_text (int options, const char *string);
263 void table_output_text_format (int options, const char *, ...)
264 PRINTF_FORMAT (2, 3);
265
266 /* Rule masks. */
267 #define TAB_RULE_TYPE_MASK 7
268 #define TAB_RULE_TYPE_SHIFT 0
269 #define TAB_RULE_STYLE_MASK (31 << TAB_RULE_STYLE_SHIFT)
270 #define TAB_RULE_STYLE_SHIFT 3
271
272 /* Tables. */
273 struct table *table_create (int nc, int nr, int hl, int hr, int ht, int hb);
274
275 /* Rules. */
276 void table_hline (struct table *, int style, int x1, int x2, int y);
277 void table_vline (struct table *, int style, int x, int y1, int y2);
278 void table_box (struct table *, int f_h, int f_v, int i_h, int i_v,
279 int x1, int y1, int x2, int y2);
280
281 /* Cells. */
282 void table_text (struct table *, int c, int r, unsigned opt, const char *);
283 void table_text_format (struct table *, int c, int r, unsigned opt,
284 const char *, ...)
285 PRINTF_FORMAT (5, 6);
286 void table_joint_text (struct table *, int x1, int y1, int x2, int y2,
287 unsigned opt, const char *);
288
289 void table_add_subscripts (struct table *, int x, int y,
290 char **subscripts, size_t n_subscripts);
291 void table_add_superscript (struct table *, int x, int y,
292 const char *superscript);
293
294 /* Footnotes.
295
296 Use table_create_footnote() to create the footnotes themselves, then use
297 table_add_footnote() to create a reference from a table cell to a footnote.
298 There are two steps because a footnote may have multiple references. */
299 struct footnote *table_create_footnote (struct table *, size_t idx,
300 const char *content,
301 const char *marker,
302 struct area_style *);
303 void table_add_footnote (struct table *, int x, int y,
304 const struct footnote *);
305
306 void table_add_style (struct table *, int x, int y,
307 const struct area_style *);
308
309 bool table_cell_is_empty (const struct table *, int c, int r);
310
311 #endif /* output/table.h */
312