output: Drop TAB_FIX and the idea of a configurable fixed-width font.
[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   table_text (tab, 0, 0, opts, text_item_get_text (text_item));
178   struct table_item *table_item = table_item_create (tab);
179   text_item_unref (text_item);
180   return table_item;
181 }
182 \f
183 static const char *
184 text_item_get_label (const struct output_item *output_item)
185 {
186   const struct text_item *item = to_text_item (output_item);
187   return text_item_type_to_string (item->type);
188 }
189
190 static void
191 text_item_destroy (struct output_item *output_item)
192 {
193   struct text_item *item = to_text_item (output_item);
194   free (item->text);
195   font_style_uninit (&item->style);
196   free (item);
197 }
198
199 const struct output_item_class text_item_class =
200   {
201     text_item_get_label,
202     text_item_destroy,
203   };