output-item: Make label a part of every output_item.
[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/table.h"
29 #include "output/table-item.h"
30 #include "output/table-provider.h"
31
32 #include "gl/xalloc.h"
33 #include "gl/xvasprintf.h"
34
35 #include "gettext.h"
36 #define _(msgid) gettext (msgid)
37 #define N_(msgid) msgid
38
39 const char *
40 text_item_type_to_string (enum text_item_type type)
41 {
42   switch (type)
43     {
44     case TEXT_ITEM_PAGE_TITLE:
45       return _("Page Title");
46
47     case TEXT_ITEM_TITLE:
48       return _("Title");
49
50     case TEXT_ITEM_SYNTAX:
51     case TEXT_ITEM_LOG:
52       return _("Log");
53
54     default:
55       return _("Text");
56     }
57 }
58
59 /* Creates and returns a new text item containing TEXT and the specified TYPE
60    and LABEL.  The new text item takes ownership of TEXT and LABEL.  If LABEL
61    is NULL, uses the default label for TYPE. */
62 struct text_item *
63 text_item_create_nocopy (enum text_item_type type, char *text, char *label)
64 {
65   struct text_item *item = xzalloc (sizeof *item);
66   *item = (struct text_item) {
67     .output_item = OUTPUT_ITEM_INITIALIZER (&text_item_class),
68     .output_item.label = label,
69     .text = text,
70     .type = type,
71   };
72   return item;
73 }
74
75 /* Creates and returns a new text item containing a copy of TEXT and the
76    specified TYPE and LABEL.  The caller retains ownership of TEXT and LABEL.
77    If LABEL is null, uses a default label for TYPE. */
78 struct text_item *
79 text_item_create (enum text_item_type type, const char *text,
80                   const char *label)
81 {
82   return text_item_create_nocopy (type, xstrdup (text),
83                                   label ? xstrdup (label) : NULL);
84 }
85
86 /* Returns ITEM's type. */
87 enum text_item_type
88 text_item_get_type (const struct text_item *item)
89 {
90   return item->type;
91 }
92
93 /* Returns ITEM's text, which the caller may not modify or free. */
94 const char *
95 text_item_get_text (const struct text_item *item)
96 {
97   return item->text;
98 }
99
100 /* Submits ITEM to the configured output drivers, and transfers ownership to
101    the output subsystem. */
102 void
103 text_item_submit (struct text_item *item)
104 {
105   output_submit (&item->output_item);
106 }
107
108 struct text_item *
109 text_item_unshare (struct text_item *old)
110 {
111   assert (old->output_item.ref_cnt > 0);
112   if (!text_item_is_shared (old))
113     return old;
114   text_item_unref (old);
115
116   struct text_item *new = xmalloc (sizeof *new);
117   *new = (struct text_item) {
118     .output_item = OUTPUT_ITEM_CLONE_INITIALIZER (&old->output_item),
119     .text = xstrdup (old->text),
120     .type = old->type,
121     .bold = old->bold,
122     .italic = old->italic,
123     .underline = old->underline,
124     .markup = old->markup,
125     .typeface = old->typeface ? xstrdup (old->typeface) : NULL,
126     .size = old->size
127   };
128   return new;
129 }
130
131 /* Attempts to append the text in SRC to DST.  If successful, returns true,
132    otherwise false.
133
134    Only TEXT_ITEM_SYNTAX and TEXT_ITEM_LOG items can be combined, and not with
135    each other.
136
137    DST must not be shared. */
138 bool
139 text_item_append (struct text_item *dst, const struct text_item *src)
140 {
141   assert (!text_item_is_shared (dst));
142   if (dst->type != src->type
143       || (dst->type != TEXT_ITEM_SYNTAX && dst->type != TEXT_ITEM_LOG)
144       || strcmp (output_item_get_label (&dst->output_item),
145                  output_item_get_label (&src->output_item))
146       || dst->bold != src->bold
147       || dst->italic != src->italic
148       || dst->underline != src->underline
149       || dst->markup
150       || src->markup
151       || strcmp (dst->typeface ? dst->typeface : "",
152                  src->typeface ? src->typeface : "")
153       || dst->size != src->size)
154     return false;
155   else
156     {
157       char *new_text = xasprintf ("%s\n%s", dst->text, src->text);
158       free (dst->text);
159       dst->text = new_text;
160       return true;
161     }
162 }
163
164 struct table_item *
165 text_item_to_table_item (struct text_item *text_item)
166 {
167   struct table *tab = table_create (1, 1, 0, 0, 0, 0);
168
169   struct table_area_style *style = pool_alloc (tab->container, sizeof *style);
170   *style = (struct table_area_style) { TABLE_AREA_STYLE_INITIALIZER__,
171                                        .cell_style.halign = TABLE_HALIGN_LEFT };
172   struct font_style *font_style = &style->font_style;
173   if (text_item->typeface)
174     font_style->typeface = pool_strdup (tab->container, text_item->typeface);
175   font_style->size = text_item->size;
176   font_style->bold = text_item->bold;
177   font_style->italic = text_item->italic;
178   font_style->underline = text_item->underline;
179   font_style->markup = text_item->markup;
180   tab->styles[0] = style;
181
182   int opts = 0;
183   if (text_item->markup)
184     opts |= TAB_MARKUP;
185   if (text_item->type == TEXT_ITEM_SYNTAX || text_item->type == TEXT_ITEM_LOG)
186     opts |= TAB_FIX;
187   table_text (tab, 0, 0, opts, text_item_get_text (text_item));
188   struct table_item *table_item = table_item_create (tab, NULL, NULL, NULL);
189   text_item_unref (text_item);
190   return table_item;
191 }
192 \f
193 static const char *
194 text_item_get_label (const struct output_item *output_item)
195 {
196   const struct text_item *item = to_text_item (output_item);
197   return text_item_type_to_string (item->type);
198 }
199
200 static void
201 text_item_destroy (struct output_item *output_item)
202 {
203   struct text_item *item = to_text_item (output_item);
204   free (item->text);
205   free (item->typeface);
206   free (item);
207 }
208
209 const struct output_item_class text_item_class =
210   {
211     text_item_get_label,
212     text_item_destroy,
213   };