cde9d92b8f186a29525a00b24fb55e09b3707771
[pspp] / src / ui / gui / helper.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013  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
44 #include "gl/configmake.h"
45 #include "xalloc.h"
46
47 #include <gettext.h>
48
49 /* Formats a value according to VAR's print format and strips white space
50    appropriately for VAR's type.  That is, if VAR is numeric, strips leading
51    white space (because numbers are right-justified within their fields), and
52    if VAR is string, strips trailing white space (because spaces pad out string
53    values on the right).
54
55    Returns an allocated string.  The returned string must be freed when no
56    longer required. */
57 gchar *
58 value_to_text (union value v, const struct variable *var)
59 {
60   return value_to_text__ (v, var_get_print_format (var),
61                           var_get_encoding (var));
62 }
63
64 /* Formats a value with format FORMAT and strips white space appropriately for
65    FORMATs' type.  That is, if FORMAT is numeric, strips leading white space
66    (because numbers are right-justified within their fields), and if FORMAT is
67    string, strips trailing white space (because spaces pad out string values on
68    the right).
69
70    Returns an allocated string.  The returned string must be freed when no
71    longer required. */
72 gchar *
73 value_to_text__ (union value v,
74                  const struct fmt_spec *format, const char *encoding)
75 {
76   gchar *s;
77
78   s = data_out_stretchy (&v, encoding, format, NULL);
79   if (fmt_is_numeric (format->type))
80     g_strchug (s);
81   else
82     g_strchomp (s);
83
84   return s;
85 }
86
87 /* Converts TEXT to a value.
88
89    VAL will be initialised and filled by this function.
90    It is the caller's responsibility to destroy VAL when no longer needed.
91    VAR must be the variable with which VAL is associated.
92
93    On success, VAL is returned, NULL otherwise.
94 */
95 union value *
96 text_to_value (const gchar *text,
97                const struct variable *var,
98                union value *val)
99 {
100   return text_to_value__ (text, var_get_print_format (var),
101                           var_get_encoding (var), val);
102 }
103
104 /* Converts TEXT, which contains a value in the given FORMAT encoding in
105    ENCODING, into a value.
106
107    VAL will be initialised and filled by this function.
108    It is the caller's responsibility to destroy VAL when no longer needed.
109
110    On success, VAL is returned, NULL otherwise.
111 */
112 union value *
113 text_to_value__ (const gchar *text,
114                  const struct fmt_spec *format,
115                  const gchar *encoding,
116                  union value *val)
117 {
118   int width = fmt_var_width (format);
119
120   if (format->type != FMT_A)
121     {
122       if (! text) return NULL;
123
124       {
125         const gchar *s = text;
126         while (*s)
127           {
128             if (!isspace (*s))
129               break;
130             s++;
131           }
132
133         if (!*s) return NULL;
134       }
135     }
136
137   value_init (val, width);
138   char *err = data_in (ss_cstr (text), UTF8, format->type, val, width, encoding);
139
140   if (err)
141     {
142       value_destroy (val, width);
143       val = NULL;
144       free (err);
145     }
146
147   return val;
148 }
149
150
151 #define _(msgid) gettext (msgid)
152 #define N_(msgid) msgid
153
154 /* Create a deep copy of SRC */
155 GtkListStore *
156 clone_list_store (const GtkListStore *src)
157 {
158   GtkTreeIter src_iter;
159   gboolean ok;
160   gint i;
161   const gint n_cols =  gtk_tree_model_get_n_columns (GTK_TREE_MODEL (src));
162   GType *types = g_malloc (sizeof (*types) *  n_cols);
163
164   int row = 0;
165   GtkListStore *dest;
166
167   for (i = 0 ; i < n_cols; ++i)
168     types[i] = gtk_tree_model_get_column_type (GTK_TREE_MODEL (src), i);
169
170   dest = gtk_list_store_newv (n_cols, types);
171
172   for (ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (src),
173                                            &src_iter);
174        ok;
175        ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (src), &src_iter))
176     {
177       GtkTreeIter dest_iter;
178       gtk_list_store_append  (dest, &dest_iter);
179
180       for (i = 0 ; i < n_cols; ++i)
181         {
182           GValue val = {0};
183
184           gtk_tree_model_get_value (GTK_TREE_MODEL (src), &src_iter, i, &val);
185           gtk_list_store_set_value (dest, &dest_iter, i, &val);
186
187           g_value_unset (&val);
188         }
189       row++;
190     }
191
192   g_free (types);
193
194   return dest;
195 }
196
197
198
199
200 static gboolean
201 on_delete (GtkWindow *window, GdkEvent *e, GtkWindow **addr)
202 {
203   *addr = NULL;
204
205   return FALSE;
206 }
207
208 char *
209 paste_syntax_to_window (gchar *syntax)
210 {
211   static GtkWidget *the_syntax_pasteboard = NULL;
212
213   GtkTextBuffer *buffer = NULL;
214
215   if (NULL == the_syntax_pasteboard)
216     {
217       the_syntax_pasteboard = psppire_syntax_window_new (NULL);
218       g_signal_connect (the_syntax_pasteboard, "delete-event", G_CALLBACK (on_delete),
219                         &the_syntax_pasteboard);
220     }
221
222   buffer = GTK_TEXT_BUFFER (PSPPIRE_SYNTAX_WINDOW (the_syntax_pasteboard)->buffer);
223
224   gtk_text_buffer_begin_user_action (buffer);
225   gtk_text_buffer_insert_at_cursor (buffer, syntax, -1);
226   gtk_text_buffer_insert_at_cursor (buffer, "\n", 1);
227   gtk_text_buffer_end_user_action (buffer);
228
229   gtk_widget_show (the_syntax_pasteboard);
230
231   return syntax;
232 }