1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2007, 2009, 2011 Free Software Foundation
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.
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.
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/>. */
19 #include "widget-io.h"
23 #include <gl/printf-parse.h>
27 #include <gl/gettext.h>
31 /* Create a GtkLabel and pack it into BOX.
32 The label is created using part of the string at S, and the directives
33 at DIRS[DIR_IDX] and subsequent.
35 After this function returns, *S points to the first unused character.
38 ship_label (GtkBox *box, const char **s,
39 const char_directives *dirs, size_t dir_idx)
42 GString *str = g_string_new (*s);
46 char_directive dir = dirs->dir[dir_idx];
49 while (dir_idx < dirs->count && dir.conversion == '%' )
51 g_string_erase (str, dir.dir_start - *s, 1);
52 dir = dirs->dir[++dir_idx];
56 g_string_truncate (str, dir.dir_start - *s - n);
58 if ( dir_idx >= dirs->count)
64 label = gtk_label_new (str->str);
66 g_string_free (str, TRUE);
68 gtk_box_pack_start (box, label, FALSE, FALSE, 0);
69 gtk_widget_show (label);
72 /* Returns a string generated from FMT and a list of GtkEntry widgets.
73 Each conversion in FMT will be replaced with the text from the
74 corresponding GtkEntry. The normal printf semantics will be ignored.
75 Note that the GtkEntry widgets may be GtkSpinbuttons or any other widget
76 derived from GtkEntry.
77 The returned string should be freed when no longer required.
80 widget_printf (const gchar *fmt, ...)
91 if ( 0 != printf_parse (fmt, &d, &a) )
94 widgets = xcalloc (sizeof (*widgets), d.count);
96 for (i = 0 ; i < d.count ; ++i )
98 if ( d.dir[i].conversion != '%')
99 widgets[i] = va_arg (ap, GtkWidget *);
103 if (a.arg != a.direct_alloc_arg)
106 output = g_string_sized_new (strlen (fmt));
108 for (i = 0 ; i < d.count ; ++i )
110 char_directive dir = d.dir[i];
112 const gchar *entry_text;
114 if ( dir.conversion == '%')
120 w = widgets [dir.arg_index];
121 entry_text = gtk_entry_get_text (GTK_ENTRY (w));
123 if ( dir.dir_start > s )
124 g_string_append_len (output, s, dir.dir_start - s);
128 g_string_append (output, entry_text);
132 if (d.dir != d.direct_alloc_dir)
136 g_string_append_len (output, s, -1);
139 g_string_free (output, FALSE);
144 Returns a GtkHBox populated with an GtkLabel and GtkEntry widgets.
145 Each conversion in FMT will cause a GtkEntry (possibly a GtkSpinButton) to
146 be created. Any text between conversions produces a GtkLabel.
147 There should be N arguments following FMT should be of type GtkEntry **,
148 where N is the number of conversions.
149 These arguments will be filled with a pointer to the corresponding widgets.
150 Their properties may be changed, but they should not be unrefed.
153 widget_scanf (const gchar *fmt, ...)
159 GtkWidget ***widgets = NULL;
160 GtkWidget *hbox = NULL;
164 if ( 0 != printf_parse (fmt, &d, &a) )
167 if (a.arg != a.direct_alloc_arg)
174 hbox = gtk_hbox_new (FALSE, 0);
175 widgets = calloc (sizeof (*widgets), d.count);
178 for (i = 0 ; i < d.count ; ++i )
180 if ( d.dir[i].conversion != '%')
181 widgets[i] = va_arg (ap, GtkWidget **);
187 for (i = 0 ; i < d.count ; ++i )
189 char_directive dir = d.dir[i];
194 if ( dir.precision_start && dir.precision_end)
195 precision = strtol (dir.precision_start + 1,
196 (char **) &dir.precision_end, 10);
198 if ( dir.width_start && dir.width_end )
199 width = strtol (dir.width_start, (char **) &dir.width_end, 10);
201 if ( dir.dir_start > s )
202 ship_label (GTK_BOX (hbox), &s, &d, i);
204 if ( dir.conversion == '%')
210 w = widgets [dir.arg_index];
211 switch (dir.conversion)
217 *w = gtk_spin_button_new_with_range (0, 100.0, 1.0);
218 g_object_set (*w, "digits", precision, NULL);
222 *w = gtk_entry_new ();
226 g_object_set (*w, "width-chars", width, NULL);
227 gtk_box_pack_start (GTK_BOX (hbox), *w, FALSE, FALSE, 0);
228 gtk_widget_show (*w);
232 ship_label (GTK_BOX (hbox), &s, NULL, 0);
238 if (d.dir != d.direct_alloc_dir)