bc154d5462ab0f7b9072688dfc15bee91f178164
[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.  Takes ownership of
126    TABLE. */
127 struct table_item *
128 table_item_create (struct table *table)
129 {
130   struct table_item *item = xmalloc (sizeof *item);
131   *item = (struct table_item) {
132     .output_item = OUTPUT_ITEM_INITIALIZER (&table_item_class),
133     .table = table,
134   };
135   return item;
136 }
137
138 /* Returns the table contained by TABLE_ITEM.  The caller must not modify or
139    unref the returned table. */
140 const struct table *
141 table_item_get_table (const struct table_item *table_item)
142 {
143   return table_item->table;
144 }
145
146 /* Returns ITEM's title, which is a null pointer if no title has been
147    set. */
148 const struct table_item_text *
149 table_item_get_title (const struct table_item *item)
150 {
151   return item->title;
152 }
153
154 /* Sets ITEM's title to TITLE, replacing any previous title.  Specify NULL for
155    TITLE to clear any title from ITEM.  The caller retains ownership of TITLE.
156
157    This function may only be used on a table_item that is unshared. */
158 void
159 table_item_set_title (struct table_item *item,
160                       const struct table_item_text *title)
161 {
162   assert (!table_item_is_shared (item));
163   table_item_text_destroy (item->title);
164   item->title = table_item_text_clone (title);
165 }
166
167 /* Returns ITEM's layers, which will be a null pointer if no layers have been
168    set. */
169 const struct table_item_layers *
170 table_item_get_layers (const struct table_item *item)
171 {
172   return item->layers;
173 }
174
175 /* Sets ITEM's layers to LAYERS, replacing any previous layers.  Specify NULL
176    for LAYERS to clear any layers from ITEM.  The caller retains ownership of
177    LAYERS.
178
179    This function may only be used on a table_item that is unshared. */
180 void
181 table_item_set_layers (struct table_item *item,
182                        const struct table_item_layers *layers)
183 {
184   assert (!table_item_is_shared (item));
185   table_item_layers_destroy (item->layers);
186   item->layers = table_item_layers_clone (layers);
187 }
188
189 /* Returns ITEM's caption, which is a null pointer if no caption has been
190    set. */
191 const struct table_item_text *
192 table_item_get_caption (const struct table_item *item)
193 {
194   return item->caption;
195 }
196
197 /* Sets ITEM's caption to CAPTION, replacing any previous caption.  Specify
198    NULL for CAPTION to clear any caption from ITEM.  The caller retains
199    ownership of CAPTION.
200
201    This function may only be used on a table_item that is unshared. */
202 void
203 table_item_set_caption (struct table_item *item,
204                         const struct table_item_text *caption)
205 {
206   assert (!table_item_is_shared (item));
207   table_item_text_destroy (item->caption);
208   item->caption = table_item_text_clone (caption);
209 }
210
211 /* Returns ITEM's notes, which is a null pointer if ITEM has no notes. */
212 const char *
213 table_item_get_notes (const struct table_item *item)
214 {
215   return item->notes;
216 }
217
218 /* Sets ITEM's notes to NOTES, replacing any previous notes.  Specify NULL for
219    NOTES to clear any notes from ITEM.  The caller retains ownership of
220    NOTES.
221
222    This function may only be used on a table_item that is unshared.*/
223 void
224 table_item_set_notes (struct table_item *item, const char *notes)
225 {
226   assert (!table_item_is_shared (item));
227   free (item->notes);
228   item->notes = notes ? xstrdup (notes) : NULL;
229 }
230
231 /* Submits TABLE_ITEM to the configured output drivers, and transfers ownership
232    to the output subsystem. */
233 void
234 table_item_submit (struct table_item *table_item)
235 {
236   output_submit (&table_item->output_item);
237 }
238 \f
239 static const char *
240 table_item_get_label (const struct output_item *output_item)
241 {
242   const struct table_item *item = to_table_item (output_item);
243   return (item->title && item->title->content
244           ? item->title->content
245           : _("Table"));
246 }
247
248 static void
249 table_item_destroy (struct output_item *output_item)
250 {
251   struct table_item *item = to_table_item (output_item);
252   table_item_text_destroy (item->title);
253   table_item_text_destroy (item->caption);
254   table_item_layers_destroy (item->layers);
255   free (item->notes);
256   pivot_table_unref (item->pt);
257   table_unref (item->table);
258   free (item);
259 }
260
261 const struct output_item_class table_item_class =
262   {
263     table_item_get_label,
264     table_item_destroy,
265   };