table: Make table cells have exactly one piece of content again.
[pspp] / src / output / table-provider.h
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997, 1998, 1999, 2000, 2009, 2011, 2013, 2014, 2018 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_PROVIDER
18 #define OUTPUT_TABLE_PROVIDER 1
19
20 #include <stdint.h>
21 #include "output/table.h"
22
23 struct pool;
24 struct string;
25
26 struct footnote
27   {
28     size_t idx;
29     char *content;
30     char *marker;
31     struct cell_style *style;
32   };
33
34 struct cell_color
35   {
36     uint8_t r, g, b;
37   };
38
39 #define CELL_COLOR(r, g, b) (struct cell_color) { r, g, b }
40 #define CELL_COLOR_BLACK CELL_COLOR (0, 0, 0)
41 #define CELL_COLOR_WHITE CELL_COLOR (255, 255, 255)
42
43 static inline bool
44 cell_color_equal (const struct cell_color *a, const struct cell_color *b)
45 {
46   return a->r == b->r && a->g == b->g && a->b == b->b;
47 }
48
49 struct cell_style
50   {
51     struct cell_color fg[2], bg[2];
52     int margin[TABLE_N_AXES][2];
53     char *font;
54     int font_size;
55     bool bold, italic, underline;
56   };
57
58 #define CELL_STYLE_INITIALIZER                                  \
59     {                                                           \
60       .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK},  \
61       .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE},  \
62       .margin = { [TABLE_HORZ][0] = 8, [TABLE_HORZ][1] = 11,    \
63                   [TABLE_VERT][0] = 1, [TABLE_VERT][1] = 1 },   \
64       .font = NULL,                                             \
65       .font_size = 0,                                           \
66       .bold = false,                                            \
67       .italic = false,                                          \
68       .underline = false,                                       \
69     }
70
71 struct cell_style *cell_style_clone (struct pool *, const struct cell_style *);
72 void cell_style_free (struct cell_style *);
73
74 /* A cell in a table. */
75 struct table_cell
76   {
77     /* Occupied table region.
78
79        d[TABLE_HORZ][0] is the leftmost column.
80        d[TABLE_HORZ][1] is the rightmost column, plus 1.
81        d[TABLE_VERT][0] is the top row.
82        d[TABLE_VERT][1] is the bottom row, plus 1.
83
84        For an ordinary cell:
85            d[TABLE_HORZ][1] == d[TABLE_HORZ][0] + 1
86        and d[TABLE_VERT][1] == d[TABLE_VERT][0] + 1
87
88        For a joined cell:
89           d[TABLE_HORZ][1] > d[TABLE_HORZ][0] + 1
90        or d[TABLE_VERT][1] > d[TABLE_VERT][0] + 1
91        or both. */
92     int d[TABLE_N_AXES][2];
93
94     unsigned int options;       /* TAB_*. */
95     char *text;                 /* A paragraph of text. */
96
97     /* Optional footnote(s). */
98     const struct footnote **footnotes;
99     size_t n_footnotes;
100
101     const struct cell_style *style;
102
103     /* Called to free the cell's data, if nonnull. */
104     void (*destructor) (void *destructor_aux);
105     void *destructor_aux;
106   };
107
108 void table_cell_free (struct table_cell *);
109
110 void table_cell_format_footnote_markers (const struct table_cell *,
111                                          struct string *);
112
113 /* Returns the number of columns that CELL spans.  This is 1 for an ordinary
114    cell and greater than one for a cell that joins multiple columns. */
115 static inline int
116 table_cell_colspan (const struct table_cell *cell)
117 {
118   return cell->d[TABLE_HORZ][1] - cell->d[TABLE_HORZ][0];
119 }
120
121 /* Returns the number of rows that CELL spans.  This is 1 for an ordinary cell
122    and greater than one for a cell that joins multiple rows. */
123 static inline int
124 table_cell_rowspan (const struct table_cell *cell)
125 {
126   return cell->d[TABLE_VERT][1] - cell->d[TABLE_VERT][0];
127 }
128
129 /* Returns true if CELL is a joined cell, that is, if it spans multiple rows
130    or columns.  Otherwise, returns false. */
131 static inline bool
132 table_cell_is_joined (const struct table_cell *cell)
133 {
134   return table_cell_colspan (cell) > 1 || table_cell_rowspan (cell) > 1;
135 }
136 \f
137 /* Declarations to allow defining table classes. */
138
139 struct table_class
140   {
141     /* Frees TABLE.
142
143        The table class may assume that any cells that were retrieved by calling
144        the 'get_cell' function have been freed (by calling their destructors)
145        before this function is called. */
146     void (*destroy) (struct table *table);
147
148     /* Initializes CELL with the contents of the table cell at column X and row
149        Y within TABLE.  All members of CELL must be initialized, except that if
150        'destructor' is set to a null pointer, then 'destructor_aux' need not be
151        initialized.  The 'contents' member of CELL must be set to a nonnull
152        value.
153
154        The table class must allow any number of cells in the table to be
155        retrieved simultaneously; that is, TABLE must not assume that a given
156        cell will be freed before another one is retrieved using 'get_cell'.
157
158        The table class must allow joined cells to be retrieved, with identical
159        contents, using any (X,Y) location inside the cell.
160
161        The table class must not allow cells to overlap.
162
163        The table class should not allow a joined cell to cross the border
164        between header rows/columns and the interior of the table.  That is, a
165        joined cell should be entirely within headers rows and columns or
166        entirely outside them.
167
168        The table class may assume that CELL will be freed before TABLE is
169        destroyed. */
170     void (*get_cell) (const struct table *table, int x, int y,
171                       struct table_cell *cell);
172
173     /* Returns one of the TAL_* enumeration constants (declared in
174        output/table.h) representing a rule running alongside one of the cells
175        in TABLE.
176
177        See table_get_rule() in table.c for a detailed explanation of the
178        meaning of AXIS and X and Y, including a diagram. */
179     int (*get_rule) (const struct table *table,
180                      enum table_axis axis, int x, int y,
181                      struct cell_color *color);
182
183     /* This function is optional and most table classes will not implement it.
184
185        If provided, this function must take ownership of A and B and return a
186        table that consists of tables A and B "pasted together", that is, a
187        table whose size is the sum of the sizes of A and B along the axis
188        specified by ORIENTATION.  A and B will ordinarily have the same size
189        along the axis opposite ORIENTATION; no particular handling of tables
190        that have different sizes along that axis is required.
191
192        The handling of rules at the seam between A and B is not specified, but
193        table_rule_combine() is one reasonable way to do it.
194
195        Called only if neither A and B is shared (as returned by
196        table_is_shared()).
197
198        Called if A or B or both is of the class defined by this table class.
199        That is, the implementation must be prepared to deal with the case where
200        A or B is not the ordinarily expected table class.
201
202        This function may return a null pointer if it cannot implement the paste
203        operation, in which case the caller will use a fallback
204        implementation.
205
206        This function is used to implement table_paste(). */
207     struct table *(*paste) (struct table *a, struct table *b,
208                             enum table_axis orientation);
209
210     /* This function is optional and most table classes will not implement it.
211
212        If provided, this function must take ownership of TABLE and return a new
213        table whose contents are the TABLE's rows RECT[TABLE_VERT][0] through
214        RECT[TABLE_VERT][1], exclusive, and the TABLE's columns
215        RECT[TABLE_HORZ][0] through RECT[TABLE_HORZ][1].
216
217        Called only if TABLE is not shared (as returned by table_is_shared()).
218
219        This function may return a null pointer if it cannot implement the
220        select operation, in which case the caller will use a fallback
221        implementation.
222
223        This function is used to implement table_select(). */
224     struct table *(*select) (struct table *table, int rect[TABLE_N_AXES][2]);
225   };
226
227 void table_init (struct table *, const struct table_class *);
228
229 /* Table class implementations can call these functions or just set the
230    table's n[] and h[][] members directly. */
231 void table_set_nc (struct table *, int nc);
232 void table_set_nr (struct table *, int nr);
233 \f
234 /* For use primarily by output drivers. */
235
236 void table_get_cell (const struct table *, int x, int y, struct table_cell *);
237 int table_get_rule (const struct table *, enum table_axis, int x, int y,
238                     struct cell_color *);
239 size_t table_collect_footnotes (const struct table_item *,
240                                 const struct footnote ***);
241
242 #endif /* output/table-provider.h */