output-item: Make label a part of every output_item.
[pspp] / src / output / table-item.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009, 2011, 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 #include <config.h>
18
19 #include "output/table-provider.h"
20
21 #include <assert.h>
22
23 #include "libpspp/assertion.h"
24 #include "libpspp/cast.h"
25 #include "output/driver.h"
26 #include "output/output-item-provider.h"
27 #include "output/pivot-table.h"
28 #include "output/table-item.h"
29
30 #include "gl/xalloc.h"
31
32 #include "gettext.h"
33 #define _(msgid) gettext (msgid)
34
35 struct table_item_text *
36 table_item_text_create (const char *content)
37 {
38   if (!content)
39     return NULL;
40
41   struct table_item_text *text = xmalloc (sizeof *text);
42   *text = (struct table_item_text) { .content = xstrdup (content) };
43   return text;
44 }
45
46 struct table_item_text *
47 table_item_text_clone (const struct table_item_text *old)
48 {
49   if (!old)
50     return NULL;
51
52   struct table_item_text *new = xmalloc (sizeof *new);
53   *new = (struct table_item_text) {
54     .content = xstrdup (old->content),
55     .footnotes = xmemdup (old->footnotes,
56                           old->n_footnotes * sizeof *old->footnotes),
57     .n_footnotes = old->n_footnotes,
58     .style = table_area_style_clone (NULL, old->style),
59   };
60   return new;
61 }
62
63 void
64 table_item_text_destroy (struct table_item_text *text)
65 {
66   if (text)
67     {
68       free (text->content);
69       free (text->footnotes);
70       table_area_style_free (text->style);
71       free (text);
72     }
73 }
74
75 void
76 table_item_layer_copy (struct table_item_layer *dst,
77                        const struct table_item_layer *src)
78 {
79   dst->content = xstrdup (src->content);
80   dst->footnotes = xmemdup (src->footnotes,
81                             src->n_footnotes * sizeof *src->footnotes);
82   dst->n_footnotes = src->n_footnotes;
83 }
84  
85 void
86 table_item_layer_uninit (struct table_item_layer *layer)
87 {
88   if (layer)
89     {
90       free (layer->content);
91       free (layer->footnotes);
92     }
93 }
94
95 struct table_item_layers *
96 table_item_layers_clone (const struct table_item_layers *old)
97 {
98   if (!old)
99     return NULL;
100
101   struct table_item_layers *new = xmalloc (sizeof *new);
102   *new = (struct table_item_layers) {
103     .layers = xnmalloc (old->n_layers, sizeof *new->layers),
104     .n_layers = old->n_layers,
105     .style = table_area_style_clone (NULL, old->style),
106   };
107   for (size_t i = 0; i < new->n_layers; i++)
108     table_item_layer_copy (&new->layers[i], &old->layers[i]);
109   return new;
110 }
111
112 void
113 table_item_layers_destroy (struct table_item_layers *layers)
114 {
115   if (layers)
116     {
117       for (size_t i = 0; i < layers->n_layers; i++)
118         table_item_layer_uninit (&layers->layers[i]);
119       free (layers->layers);
120       table_area_style_free (layers->style);
121       free (layers);
122     }
123 }
124
125 /* Initializes ITEM as a table item for rendering TABLE.  The new table item
126    initially has the specified TITLE, CAPTION, and NOTES, which may each be
127    NULL.  The caller retains ownership of TITLE, CAPTION, and NOTES. */
128 struct table_item *
129 table_item_create (struct table *table, const char *title, const char *caption,
130                    const char *notes)
131 {
132   struct table_item *item = xmalloc (sizeof *item);
133   *item = (struct table_item) {
134     .output_item = OUTPUT_ITEM_INITIALIZER (&table_item_class),
135     .table = table,
136     .title = table_item_text_create (title),
137     .caption = table_item_text_create (caption),
138     .notes = notes ? xstrdup (notes) : NULL,
139   };
140   return item;
141 }
142
143 /* Returns the table contained by TABLE_ITEM.  The caller must not modify or
144    unref the returned table. */
145 const struct table *
146 table_item_get_table (const struct table_item *table_item)
147 {
148   return table_item->table;
149 }
150
151 /* Returns ITEM's title, which is a null pointer if no title has been
152    set. */
153 const struct table_item_text *
154 table_item_get_title (const struct table_item *item)
155 {
156   return item->title;
157 }
158
159 /* Sets ITEM's title to TITLE, replacing any previous title.  Specify NULL for
160    TITLE to clear any title from ITEM.  The caller retains ownership of TITLE.
161
162    This function may only be used on a table_item that is unshared. */
163 void
164 table_item_set_title (struct table_item *item,
165                       const struct table_item_text *title)
166 {
167   assert (!table_item_is_shared (item));
168   table_item_text_destroy (item->title);
169   item->title = table_item_text_clone (title);
170 }
171
172 /* Returns ITEM's layers, which will be a null pointer if no layers have been
173    set. */
174 const struct table_item_layers *
175 table_item_get_layers (const struct table_item *item)
176 {
177   return item->layers;
178 }
179
180 /* Sets ITEM's layers to LAYERS, replacing any previous layers.  Specify NULL
181    for LAYERS to clear any layers from ITEM.  The caller retains ownership of
182    LAYERS.
183
184    This function may only be used on a table_item that is unshared. */
185 void
186 table_item_set_layers (struct table_item *item,
187                        const struct table_item_layers *layers)
188 {
189   assert (!table_item_is_shared (item));
190   table_item_layers_destroy (item->layers);
191   item->layers = table_item_layers_clone (layers);
192 }
193
194 /* Returns ITEM's caption, which is a null pointer if no caption has been
195    set. */
196 const struct table_item_text *
197 table_item_get_caption (const struct table_item *item)
198 {
199   return item->caption;
200 }
201
202 /* Sets ITEM's caption to CAPTION, replacing any previous caption.  Specify
203    NULL for CAPTION to clear any caption from ITEM.  The caller retains
204    ownership of CAPTION.
205
206    This function may only be used on a table_item that is unshared. */
207 void
208 table_item_set_caption (struct table_item *item,
209                         const struct table_item_text *caption)
210 {
211   assert (!table_item_is_shared (item));
212   table_item_text_destroy (item->caption);
213   item->caption = table_item_text_clone (caption);
214 }
215
216 /* Returns ITEM's notes, which is a null pointer if ITEM has no notes. */
217 const char *
218 table_item_get_notes (const struct table_item *item)
219 {
220   return item->notes;
221 }
222
223 /* Sets ITEM's notes to NOTES, replacing any previous notes.  Specify NULL for
224    NOTES to clear any notes from ITEM.  The caller retains ownership of
225    NOTES.
226
227    This function may only be used on a table_item that is unshared.*/
228 void
229 table_item_set_notes (struct table_item *item, const char *notes)
230 {
231   assert (!table_item_is_shared (item));
232   free (item->notes);
233   item->notes = notes ? xstrdup (notes) : NULL;
234 }
235
236 /* Submits TABLE_ITEM to the configured output drivers, and transfers ownership
237    to the output subsystem. */
238 void
239 table_item_submit (struct table_item *table_item)
240 {
241   output_submit (&table_item->output_item);
242 }
243 \f
244 static const char *
245 table_item_get_label (const struct output_item *output_item)
246 {
247   const struct table_item *item = to_table_item (output_item);
248   return (item->title && item->title->content
249           ? item->title->content
250           : _("Table"));
251 }
252
253 static void
254 table_item_destroy (struct output_item *output_item)
255 {
256   struct table_item *item = to_table_item (output_item);
257   table_item_text_destroy (item->title);
258   table_item_text_destroy (item->caption);
259   table_item_layers_destroy (item->layers);
260   free (item->notes);
261   pivot_table_unref (item->pt);
262   table_unref (item->table);
263   free (item);
264 }
265
266 const struct output_item_class table_item_class =
267   {
268     table_item_get_label,
269     table_item_destroy,
270   };