c70be1e620e884d86287997f8e86352a28699fc8
[pspp] / src / output / table.h
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    Some drivers use tables as an implementation detail of rendering pivot
30    tables.
31 */
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 pivot_footnote;
41 struct pivot_value;
42 struct pool;
43 struct table_item;
44 struct variable;
45
46 /* A table axis.
47
48    Many table-related declarations use 2-element arrays in place of "x" and "y"
49    variables.  This reduces code duplication significantly, because much table
50    code treats rows and columns the same way.
51
52    A lot of code that uses these enumerations assumes that the two values are 0
53    and 1, so don't change them to other values. */
54 enum table_axis
55   {
56     TABLE_HORZ,
57     TABLE_VERT
58 #define TABLE_N_AXES 2
59   };
60
61 struct cell_color
62   {
63     uint8_t alpha, r, g, b;
64   };
65
66 #define CELL_COLOR(r, g, b) { 255, r, g, b }
67 #define CELL_COLOR_BLACK CELL_COLOR (0, 0, 0)
68 #define CELL_COLOR_WHITE CELL_COLOR (255, 255, 255)
69
70 static inline bool
71 cell_color_equal (const struct cell_color *a, const struct cell_color *b)
72 {
73   return a->alpha == b->alpha && a->r == b->r && a->g == b->g && a->b == b->b;
74 }
75
76 void cell_color_dump (const struct cell_color *);
77
78 enum table_stroke
79   {
80     TABLE_STROKE_NONE = 0,      /* Must be zero. */
81     TABLE_STROKE_SOLID,
82     TABLE_STROKE_DASHED,
83     TABLE_STROKE_THICK,
84     TABLE_STROKE_THIN,
85     TABLE_STROKE_DOUBLE,
86     TABLE_N_STROKES,
87   };
88
89 const char *table_stroke_to_string (enum table_stroke);
90
91 /* Given strokes A and B, returns a stroke that "combines" them, that is, that
92    gives a reasonable stroke choice for a rule for different reasons should
93    have both styles A and B. */
94 static inline int
95 table_stroke_combine (enum table_stroke a, enum table_stroke b)
96 {
97   return a > b ? a : b;
98 }
99
100 struct table_border_style
101   {
102     enum table_stroke stroke;
103     struct cell_color color;
104   };
105
106 #define TABLE_BORDER_STYLE_INITIALIZER { TABLE_STROKE_SOLID, CELL_COLOR_BLACK }
107
108 enum table_halign
109   {
110     TABLE_HALIGN_RIGHT,
111     TABLE_HALIGN_LEFT,
112     TABLE_HALIGN_CENTER,
113     TABLE_HALIGN_MIXED,
114     TABLE_HALIGN_DECIMAL
115   };
116
117 const char *table_halign_to_string (enum table_halign);
118
119 enum table_valign
120   {
121     TABLE_VALIGN_TOP,
122     TABLE_VALIGN_CENTER,
123     TABLE_VALIGN_BOTTOM,
124   };
125
126 const char *table_valign_to_string (enum table_valign);
127
128 struct cell_style
129   {
130     enum table_halign halign;
131     enum table_valign valign;
132     double decimal_offset;       /* In 1/96" units. */
133     char decimal_char;           /* Either '.' or ','. */
134     int margin[TABLE_N_AXES][2]; /* In 1/96" units. */
135   };
136
137 #define CELL_STYLE_INITIALIZER { CELL_STYLE_INITIALIZER__ }
138 #define CELL_STYLE_INITIALIZER__                                \
139         .margin = { [TABLE_HORZ][0] = 8, [TABLE_HORZ][1] = 11,  \
140                     [TABLE_VERT][0] = 1, [TABLE_VERT][1] = 1 }
141
142 void cell_style_dump (const struct cell_style *);
143
144 struct font_style
145   {
146     bool bold, italic, underline, markup;
147     struct cell_color fg[2], bg[2];
148     char *typeface;
149     int size;                   /* In 1/72" units. */
150   };
151
152 #define FONT_STYLE_INITIALIZER { FONT_STYLE_INITIALIZER__ }
153 #define FONT_STYLE_INITIALIZER__                                        \
154         .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK},        \
155         .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE},
156
157 void font_style_copy (struct pool *,
158                       struct font_style *, const struct font_style *);
159 void font_style_uninit (struct font_style *);
160 void font_style_dump (const struct font_style *);
161 bool font_style_equal (const struct font_style *, const struct font_style *);
162
163 struct table_area_style
164   {
165     struct cell_style cell_style;
166     struct font_style font_style;
167   };
168
169 #define TABLE_AREA_STYLE_INITIALIZER { TABLE_AREA_STYLE_INITIALIZER__ }
170 #define TABLE_AREA_STYLE_INITIALIZER__          \
171        .cell_style = CELL_STYLE_INITIALIZER,    \
172        .font_style = FONT_STYLE_INITIALIZER
173
174 struct table_area_style *table_area_style_clone (
175   struct pool *, const struct table_area_style *);
176 void table_area_style_copy (struct pool *, struct table_area_style *,
177                             const struct table_area_style *);
178 void table_area_style_uninit (struct table_area_style *);
179 void table_area_style_free (struct table_area_style *);
180
181 /* Cell properties. */
182 enum
183   {
184     TABLE_CELL_ROTATE     = 1 << 0,    /* Rotate cell contents 90 degrees. */
185     TABLE_CELL_JOIN       = 1 << 1,    /* Joined cell (internal use only). */
186     TABLE_CELL_STYLE_SHIFT = 2,
187     TABLE_CELL_STYLE_MASK = 7 << TABLE_CELL_STYLE_SHIFT,
188   };
189
190 /* A table. */
191 struct table
192   {
193     struct pool *container;
194
195     /* Table size.
196
197        n[TABLE_HORZ]: Number of columns.
198        n[TABLE_VERT]: Number of rows. */
199     int n[TABLE_N_AXES];
200
201     /* Table headers.
202
203        Rows at the top and bottom of a table and columns at the left and right
204        edges of a table can be designated as headers.  If the table must be
205        broken across more than one page for output, headers rows and columns
206        are repeated on each page.
207
208        h[TABLE_HORZ][0]: Left header columns.
209        h[TABLE_HORZ][1]: Right header columns.
210        h[TABLE_VERT][0]: Top header rows.
211        h[TABLE_VERT][1]: Bottom header rows. */
212     int h[TABLE_N_AXES][2];
213
214     /* Reference count.  A table may be shared between multiple owners,
215        indicated by a reference count greater than 1.  When this is the case,
216        the table must not be modified. */
217     int ref_cnt;
218
219     /* Table contents.
220
221        Each array element in cc[] is ordinarily a "struct pivot_value *".  If
222        TABLE_CELL_JOIN is set in cp[] for the element, however, it is a joined
223        cell and the corresponding element of cc[] points to a struct
224        table_cell. */
225     void **cc;                  /* Cell contents; void *[nr][nc]. */
226     unsigned char *cp;          /* Cell properties; unsigned char[nr][nc]. */
227     struct table_area_style *styles[8];
228
229     /* Rules. */
230     unsigned char *rh;          /* Horiz rules; unsigned char[nr+1][nc]. */
231     unsigned char *rv;          /* Vert rules; unsigned char[nr][nc+1]. */
232     struct cell_color *rule_colors[32];
233   };
234
235 /* Reference counting. */
236 struct table *table_ref (const struct table *);
237 void table_unref (struct table *);
238 bool table_is_shared (const struct table *);
239
240 /* Rule masks. */
241 #define TAB_RULE_TYPE_MASK   7
242 #define TAB_RULE_TYPE_SHIFT  0
243 #define TAB_RULE_STYLE_MASK  (31 << TAB_RULE_STYLE_SHIFT)
244 #define TAB_RULE_STYLE_SHIFT 3
245
246 /* Tables. */
247 struct table *table_create (int nc, int nr, int hl, int hr, int ht, int hb);
248
249 /* Rules. */
250 void table_hline (struct table *, int style, int x1, int x2, int y);
251 void table_vline (struct table *, int style, int x, int y1, int y2);
252
253 /* Cells. */
254 void table_put (struct table *, int x1, int y1, int x2, int y2,
255                 unsigned opt, const struct pivot_value *);
256 void table_put_owned (struct table *, int x1, int y1, int x2, int y2,
257                       unsigned opt, struct pivot_value *);
258
259 bool table_cell_is_empty (const struct table *, int c, int r);
260
261 #endif /* output/table.h */