34f1886d855c14d0a7fed33ce7256f99cf458488
[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     .style = FONT_STYLE_INITIALIZER,
72   };
73
74   if (type == TEXT_ITEM_SYNTAX || type == TEXT_ITEM_LOG)
75     {
76       free (item->style.typeface);
77       item->style.typeface = xstrdup ("Monospaced");
78     }
79
80   return item;
81 }
82
83 /* Creates and returns a new text item containing a copy of TEXT and the
84    specified TYPE and LABEL.  The caller retains ownership of TEXT and LABEL.
85    If LABEL is null, uses a default label for TYPE. */
86 struct text_item *
87 text_item_create (enum text_item_type type, const char *text,
88                   const char *label)
89 {
90   return text_item_create_nocopy (type, xstrdup (text),
91                                   label ? xstrdup (label) : NULL);
92 }
93
94 /* Returns ITEM's type. */
95 enum text_item_type
96 text_item_get_type (const struct text_item *item)
97 {
98   return item->type;
99 }
100
101 /* Returns ITEM's text, which the caller may not modify or free. */
102 const char *
103 text_item_get_text (const struct text_item *item)
104 {
105   return item->text;
106 }
107
108 /* Submits ITEM to the configured output drivers, and transfers ownership to
109    the output subsystem. */
110 void
111 text_item_submit (struct text_item *item)
112 {
113   output_submit (&item->output_item);
114 }
115
116 struct text_item *
117 text_item_unshare (struct text_item *old)
118 {
119   assert (old->output_item.ref_cnt > 0);
120   if (!text_item_is_shared (old))
121     return old;
122   text_item_unref (old);
123
124   struct text_item *new = xmalloc (sizeof *new);
125   *new = (struct text_item) {
126     .output_item = OUTPUT_ITEM_CLONE_INITIALIZER (&old->output_item),
127     .text = xstrdup (old->text),
128     .type = old->type,
129   };
130   font_style_copy (NULL, &new->style, &old->style);
131   return new;
132 }
133
134 /* Attempts to append the text in SRC to DST.  If successful, returns true,
135    otherwise false.
136
137    Only TEXT_ITEM_SYNTAX and TEXT_ITEM_LOG items can be combined, and not with
138    each other.
139
140    DST must not be shared. */
141 bool
142 text_item_append (struct text_item *dst, const struct text_item *src)
143 {
144   assert (!text_item_is_shared (dst));
145   if (dst->type != src->type
146       || (dst->type != TEXT_ITEM_SYNTAX && dst->type != TEXT_ITEM_LOG)
147       || strcmp (output_item_get_label (&dst->output_item),
148                  output_item_get_label (&src->output_item))
149       || !font_style_equal (&dst->style, &src->style)
150       || dst->style.markup)
151     return false;
152   else
153     {
154       char *new_text = xasprintf ("%s\n%s", dst->text, src->text);
155       free (dst->text);
156       dst->text = new_text;
157       return true;
158     }
159 }
160
161 struct table_item *
162 text_item_to_table_item (struct text_item *text_item)
163 {
164   struct table *tab = table_create (1, 1, 0, 0, 0, 0);
165
166   struct table_area_style *style = pool_alloc (tab->container, sizeof *style);
167   *style = (struct table_area_style) {
168     .cell_style = CELL_STYLE_INITIALIZER,
169     .cell_style.halign = TABLE_HALIGN_LEFT,
170   };
171   font_style_copy (tab->container, &style->font_style, &text_item->style);
172   tab->styles[0] = style;
173
174   int opts = 0;
175   if (text_item->style.markup)
176     opts |= TAB_MARKUP;
177   if (text_item->type == TEXT_ITEM_SYNTAX || text_item->type == TEXT_ITEM_LOG)
178     opts |= TAB_FIX;
179   table_text (tab, 0, 0, opts, text_item_get_text (text_item));
180   struct table_item *table_item = table_item_create (tab);
181   text_item_unref (text_item);
182   return table_item;
183 }
184 \f
185 static const char *
186 text_item_get_label (const struct output_item *output_item)
187 {
188   const struct text_item *item = to_text_item (output_item);
189   return text_item_type_to_string (item->type);
190 }
191
192 static void
193 text_item_destroy (struct output_item *output_item)
194 {
195   struct text_item *item = to_text_item (output_item);
196   free (item->text);
197   font_style_uninit (&item->style);
198   free (item);
199 }
200
201 const struct output_item_class text_item_class =
202   {
203     text_item_get_label,
204     text_item_destroy,
205   };