Add support for reading and writing SPV files.
[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 struct table_item_text *
33 table_item_text_create (const char *content)
34 {
35   if (!content)
36     return NULL;
37
38   struct table_item_text *text = xmalloc (sizeof *text);
39   *text = (struct table_item_text) { .content = xstrdup (content) };
40   return text;
41 }
42
43 struct table_item_text *
44 table_item_text_clone (const struct table_item_text *old)
45 {
46   if (!old)
47     return NULL;
48
49   struct table_item_text *new = xmalloc (sizeof *new);
50   *new = (struct table_item_text) {
51     .content = xstrdup (old->content),
52     .footnotes = xmemdup (old->footnotes,
53                           old->n_footnotes * sizeof *old->footnotes),
54     .n_footnotes = old->n_footnotes,
55     .style = area_style_clone (NULL, old->style),
56   };
57   return new;
58 }
59
60 void
61 table_item_text_destroy (struct table_item_text *text)
62 {
63   if (text)
64     {
65       free (text->content);
66       free (text->footnotes);
67       area_style_free (text->style);
68       free (text);
69     }
70 }
71
72 void
73 table_item_layer_copy (struct table_item_layer *dst,
74                        const struct table_item_layer *src)
75 {
76   dst->content = xstrdup (src->content);
77   dst->footnotes = xmemdup (src->footnotes,
78                             src->n_footnotes * sizeof *src->footnotes);
79   dst->n_footnotes = src->n_footnotes;
80 }
81
82 void
83 table_item_layer_uninit (struct table_item_layer *layer)
84 {
85   if (layer)
86     {
87       free (layer->content);
88       free (layer->footnotes);
89     }
90 }
91
92 struct table_item_layers *
93 table_item_layers_clone (const struct table_item_layers *old)
94 {
95   if (!old)
96     return NULL;
97
98   struct table_item_layers *new = xmalloc (sizeof *new);
99   *new = (struct table_item_layers) {
100     .layers = xnmalloc (old->n_layers, sizeof *new->layers),
101     .n_layers = old->n_layers,
102     .style = area_style_clone (NULL, old->style),
103   };
104   for (size_t i = 0; i < new->n_layers; i++)
105     table_item_layer_copy (&new->layers[i], &old->layers[i]);
106   return new;
107 }
108
109 void
110 table_item_layers_destroy (struct table_item_layers *layers)
111 {
112   if (layers)
113     {
114       for (size_t i = 0; i < layers->n_layers; i++)
115         table_item_layer_uninit (&layers->layers[i]);
116       free (layers->layers);
117       area_style_free (layers->style);
118       free (layers);
119     }
120 }
121
122 /* Initializes ITEM as a table item for rendering TABLE.  The new table item
123    initially has the specified TITLE and CAPTION, which may each be NULL.  The
124    caller retains ownership of TITLE and CAPTION. */
125 struct table_item *
126 table_item_create (struct table *table, const char *title, const char *caption)
127 {
128   struct table_item *item = xmalloc (sizeof *item);
129   output_item_init (&item->output_item, &table_item_class);
130   item->table = table;
131   item->title = table_item_text_create (title);
132   item->layers = NULL;
133   item->caption = table_item_text_create (caption);
134   item->pt = NULL;
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 /* Submits TABLE_ITEM to the configured output drivers, and transfers ownership
212    to the output subsystem. */
213 void
214 table_item_submit (struct table_item *table_item)
215 {
216   output_submit (&table_item->output_item);
217 }
218 \f
219 static void
220 table_item_destroy (struct output_item *output_item)
221 {
222   struct table_item *item = to_table_item (output_item);
223   table_item_text_destroy (item->title);
224   table_item_text_destroy (item->caption);
225   table_item_layers_destroy (item->layers);
226   pivot_table_unref (item->pt);
227   table_unref (item->table);
228   free (item);
229 }
230
231 const struct output_item_class table_item_class =
232   {
233     "table",
234     table_item_destroy,
235   };