helper: New function value_to_text__().
[pspp] / src / ui / gui / helper.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007, 2009, 2010, 2011, 2012  Free Software Foundation
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
18 /* This file is a rubbish bin where stuff gets put when it doesn't seem to
19    belong anywhere else.
20 */
21 #include <config.h>
22
23 #include        <glib-object.h>
24
25 #include <glib.h>
26 #include "helper.h"
27 #include <data/format.h>
28 #include <data/data-in.h>
29 #include <data/data-out.h>
30 #include <data/dictionary.h>
31 #include <data/casereader-provider.h>
32 #include <libpspp/message.h>
33 #include "psppire-syntax-window.h"
34 #include <gtk/gtk.h>
35 #include <libpspp/i18n.h>
36
37 #include <ctype.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <data/settings.h>
41
42 #include "psppire-data-store.h"
43 #include "psppire.h"
44
45 #include "gl/configmake.h"
46 #include "xalloc.h"
47
48 #include <gettext.h>
49
50 /* Formats a value according to VAR's print format and strips white space
51    appropriately for VAR's type.  That is, if VAR is numeric, strips leading
52    white space (because numbers are right-justified within their fields), and
53    if VAR is string, strips trailing white space (because spaces pad out string
54    values on the right).
55
56    Returns an allocated string.  The returned string must be freed when no
57    longer required. */
58 gchar *
59 value_to_text (union value v, const struct variable *var)
60 {
61   return value_to_text__ (v, var_get_print_format (var),
62                           var_get_encoding (var));
63 }
64
65 /* Formats a value with format FORMAT and strips white space appropriately for
66    FORMATs' type.  That is, if FORMAT is numeric, strips leading white space
67    (because numbers are right-justified within their fields), and if FORMAT is
68    string, strips trailing white space (because spaces pad out string values on
69    the right).
70
71    Returns an allocated string.  The returned string must be freed when no
72    longer required. */
73 gchar *
74 value_to_text__ (union value v,
75                  const struct fmt_spec *format, const char *encoding)
76 {
77   gchar *s;
78
79   s = data_out (&v, encoding, format);
80   if (fmt_is_numeric (format->type))
81     g_strchug (s);
82   else
83     g_strchomp (s);
84
85   return s;
86 }
87
88 /* Converts TEXT to a value.
89
90    VAL will be initialised and filled by this function.
91    It is the caller's responsibility to destroy VAL when no longer needed.
92    VAR must be the variable with which VAL is associated.
93
94    On success, VAL is returned, NULL otherwise.
95 */
96 union value *
97 text_to_value (const gchar *text,
98                const struct variable *var,
99                union value *val)
100 {
101   const struct fmt_spec *format = var_get_print_format (var);
102   int width = var_get_width (var);
103
104   if ( format->type != FMT_A)
105     {
106       if ( ! text ) return NULL;
107
108       {
109         const gchar *s = text;
110         while (*s)
111           {
112             if ( !isspace (*s))
113               break;
114             s++;
115           }
116
117         if ( !*s) return NULL;
118       }
119     }
120
121   value_init (val, width);
122   free (data_in (ss_cstr (text), UTF8, format->type, val, width,
123                  var_get_encoding (var)));
124
125   return val;
126 }
127
128
129 /* This function must be used whenever a filename generated by glib,
130    (eg, from gtk_file_chooser_get_filename) and passed to the C library,
131    (eg through a pspp syntax string).
132 */
133 gchar *
134 convert_glib_filename_to_system_filename (const gchar *fname, GError **err)
135 {
136   gchar *output_name;
137
138 #ifdef G_OS_WIN32
139   const gchar *target_encoding;
140   gchar *utf8_name = NULL;
141
142   g_get_charset (&target_encoding);
143
144   output_name = g_convert (fname, -1, target_encoding,
145                         "UTF-8", NULL, NULL, err);
146 #else
147   output_name = xstrdup (fname);
148 #endif
149
150   return output_name;
151 }
152
153
154
155 #define _(msgid) gettext (msgid)
156 #define N_(msgid) msgid
157
158
159 static void
160 give_help (void)
161 {
162   GtkWidget *dialog;
163
164   dialog = gtk_message_dialog_new (NULL,
165                                    GTK_DIALOG_MODAL,
166                                    GTK_MESSAGE_INFO,
167                                    GTK_BUTTONS_CLOSE,
168                                    _("Sorry. The help system hasn't yet "
169                                      "been implemented."));
170   gtk_dialog_run (GTK_DIALOG (dialog));
171   gtk_widget_destroy (dialog);
172 }
173
174 void
175 connect_help (GtkBuilder *xml)
176 {
177   GSList *helps = gtk_builder_get_objects (xml);
178
179   GSList *i;
180   for ( i = helps; i ; i = g_slist_next (i))
181     {
182       GObject *o = i->data;
183       if ( GTK_IS_WIDGET (o) )
184         {
185           const gchar *name = gtk_buildable_get_name (GTK_BUILDABLE (o));
186           gchar s[12] = {0};
187
188           if ( name)
189             strncpy (s, name, 11);
190           s[11] = '\0';
191
192
193           if ( 0 == strcmp ("help_button", s))
194             {
195             g_signal_connect (o, "clicked", give_help, 0);
196             }
197         }
198     }
199
200   g_slist_free (helps);
201 }
202
203
204 /* Create a deep copy of SRC */
205 GtkListStore *
206 clone_list_store (const GtkListStore *src)
207 {
208   GtkTreeIter src_iter;
209   gboolean ok;
210   gint i;
211   const gint n_cols =  gtk_tree_model_get_n_columns (GTK_TREE_MODEL (src));
212   GType *types = g_malloc (sizeof (*types) *  n_cols);
213
214   int row = 0;
215   GtkListStore *dest;
216
217   for (i = 0 ; i < n_cols; ++i )
218     types[i] = gtk_tree_model_get_column_type (GTK_TREE_MODEL (src), i);
219
220   dest = gtk_list_store_newv (n_cols, types);
221
222   for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src),
223                                            &src_iter);
224        ok;
225        ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter))
226     {
227       GtkTreeIter dest_iter;
228       gtk_list_store_append  (dest, &dest_iter);
229
230       for (i = 0 ; i < n_cols; ++i )
231         {
232           GValue val = {0};
233
234           gtk_tree_model_get_value (GTK_TREE_MODEL (src), &src_iter, i, &val);
235           gtk_list_store_set_value (dest, &dest_iter, i, &val);
236
237           g_value_unset (&val);
238         }
239       row++;
240     }
241
242   g_free (types);
243
244   return dest;
245 }
246
247
248
249
250 static gboolean 
251 on_delete (GtkWindow *window, GdkEvent *e, GtkWindow **addr)
252 {
253   *addr = NULL;
254
255   return FALSE;
256 }
257
258 char *
259 paste_syntax_to_window (gchar *syntax)
260 {
261   static GtkWidget *the_syntax_pasteboard = NULL;
262
263   GtkTextBuffer *buffer = NULL;
264
265   if ( NULL == the_syntax_pasteboard)
266     {
267       the_syntax_pasteboard = psppire_syntax_window_new (NULL);
268       g_signal_connect (the_syntax_pasteboard, "delete-event", G_CALLBACK (on_delete),
269                         &the_syntax_pasteboard);
270     }
271
272   buffer = GTK_TEXT_BUFFER (PSPPIRE_SYNTAX_WINDOW (the_syntax_pasteboard)->buffer);
273
274   gtk_text_buffer_begin_user_action (buffer);
275   gtk_text_buffer_insert_at_cursor (buffer, syntax, -1);
276   gtk_text_buffer_insert_at_cursor (buffer, "\n", 1);
277   gtk_text_buffer_end_user_action (buffer);
278
279   gtk_widget_show (the_syntax_pasteboard);
280
281   return syntax;
282 }
283
284
285 /* gtk_box_pack_start_defaults is deprecated.
286    Therefore we roll our own until a better solution is found */
287 void
288 psppire_box_pack_start_defaults (GtkBox *box, GtkWidget *widget)
289 {
290   gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
291 }