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