more work toward making table_item just a pivot_Table
[pspp] / src / output / text-item.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009, 2010, 2011 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/text-item.h"
20
21 #include <stdarg.h>
22 #include <stdlib.h>
23
24 #include "libpspp/cast.h"
25 #include "libpspp/pool.h"
26 #include "output/driver.h"
27 #include "output/output-item-provider.h"
28 #include "output/pivot-table.h"
29 #include "output/table.h"
30 #include "output/table-item.h"
31 #include "output/table-provider.h"
32
33 #include "gl/xalloc.h"
34 #include "gl/xvasprintf.h"
35
36 #include "gettext.h"
37 #define _(msgid) gettext (msgid)
38 #define N_(msgid) msgid
39
40 const char *
41 text_item_type_to_string (enum text_item_type type)
42 {
43   switch (type)
44     {
45     case TEXT_ITEM_PAGE_TITLE:
46       return _("Page Title");
47
48     case TEXT_ITEM_TITLE:
49       return _("Title");
50
51     case TEXT_ITEM_SYNTAX:
52     case TEXT_ITEM_LOG:
53       return _("Log");
54
55     default:
56       return _("Text");
57     }
58 }
59
60 /* Creates and returns a new text item containing TEXT and the specified TYPE
61    and LABEL.  The new text item takes ownership of TEXT and LABEL.  If LABEL
62    is NULL, uses the default label for TYPE. */
63 struct text_item *
64 text_item_create_nocopy (enum text_item_type type, char *text, char *label)
65 {
66   struct text_item *item = xzalloc (sizeof *item);
67   *item = (struct text_item) {
68     .output_item = OUTPUT_ITEM_INITIALIZER (&text_item_class),
69     .output_item.label = label,
70     .text = text,
71     .type = type,
72     .style = FONT_STYLE_INITIALIZER,
73   };
74
75   if (type == TEXT_ITEM_SYNTAX || type == TEXT_ITEM_LOG)
76     {
77       free (item->style.typeface);
78       item->style.typeface = xstrdup ("Monospaced");
79     }
80
81   return item;
82 }
83
84 /* Creates and returns a new text item containing a copy of TEXT and the
85    specified TYPE and LABEL.  The caller retains ownership of TEXT and LABEL.
86    If LABEL is null, uses a default label for TYPE. */
87 struct text_item *
88 text_item_create (enum text_item_type type, const char *text,
89                   const char *label)
90 {
91   return text_item_create_nocopy (type, xstrdup (text),
92                                   label ? xstrdup (label) : NULL);
93 }
94
95 /* Returns ITEM's type. */
96 enum text_item_type
97 text_item_get_type (const struct text_item *item)
98 {
99   return item->type;
100 }
101
102 /* Returns ITEM's text, which the caller may not modify or free. */
103 const char *
104 text_item_get_text (const struct text_item *item)
105 {
106   return item->text;
107 }
108
109 /* Submits ITEM to the configured output drivers, and transfers ownership to
110    the output subsystem. */
111 void
112 text_item_submit (struct text_item *item)
113 {
114   output_submit (&item->output_item);
115 }
116
117 struct text_item *
118 text_item_unshare (struct text_item *old)
119 {
120   assert (old->output_item.ref_cnt > 0);
121   if (!text_item_is_shared (old))
122     return old;
123   text_item_unref (old);
124
125   struct text_item *new = xmalloc (sizeof *new);
126   *new = (struct text_item) {
127     .output_item = OUTPUT_ITEM_CLONE_INITIALIZER (&old->output_item),
128     .text = xstrdup (old->text),
129     .type = old->type,
130   };
131   font_style_copy (NULL, &new->style, &old->style);
132   return new;
133 }
134
135 /* Attempts to append the text in SRC to DST.  If successful, returns true,
136    otherwise false.
137
138    Only TEXT_ITEM_SYNTAX and TEXT_ITEM_LOG items can be combined, and not with
139    each other.
140
141    DST must not be shared. */
142 bool
143 text_item_append (struct text_item *dst, const struct text_item *src)
144 {
145   assert (!text_item_is_shared (dst));
146   if (dst->type != src->type
147       || (dst->type != TEXT_ITEM_SYNTAX && dst->type != TEXT_ITEM_LOG)
148       || strcmp (output_item_get_label (&dst->output_item),
149                  output_item_get_label (&src->output_item))
150       || !font_style_equal (&dst->style, &src->style)
151       || dst->style.markup)
152     return false;
153   else
154     {
155       char *new_text = xasprintf ("%s\n%s", dst->text, src->text);
156       free (dst->text);
157       dst->text = new_text;
158       return true;
159     }
160 }
161
162 struct table_item *
163 text_item_to_table_item (struct text_item *text_item)
164 {
165   struct pivot_table *table = pivot_table_create__ (NULL, "Text");
166   pivot_table_set_look (table, pivot_table_look_builtin_default ());
167
168   struct pivot_dimension *d = pivot_dimension_create (
169     table, PIVOT_AXIS_ROW, N_("Text"));
170   d->hide_all_labels = true;
171   pivot_category_create_leaf (d->root, pivot_value_new_text ("null"));
172
173   struct pivot_value *content = pivot_value_new_user_text (
174     text_item->text, SIZE_MAX);
175   pivot_value_set_font_style (content, &text_item->style);
176   pivot_table_put1 (table, 0, content);
177
178   return table_item_create (table);
179 }
180 \f
181 static const char *
182 text_item_get_label (const struct output_item *output_item)
183 {
184   const struct text_item *item = to_text_item (output_item);
185   return text_item_type_to_string (item->type);
186 }
187
188 static void
189 text_item_destroy (struct output_item *output_item)
190 {
191   struct text_item *item = to_text_item (output_item);
192   free (item->text);
193   font_style_uninit (&item->style);
194   free (item);
195 }
196
197 const struct output_item_class text_item_class =
198   {
199     text_item_get_label,
200     text_item_destroy,
201   };