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