evolution-3.6.4/libevolution-utils/evolution-util.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Srinivasa Ragavan <sragavan@gnome.org>
 18  *
 19  * Copyright (C) 2012 Intel Corporation (www.intel.com)
 20  *
 21  */
 22 
 23 #include <stdlib.h>
 24 #include <stdio.h>
 25 #include <errno.h>
 26 #include <unistd.h>
 27 #include <ctype.h>
 28 #include <math.h>
 29 #include <string.h>
 30 #include <locale.h>
 31 
 32 #include "evolution-util.h"
 33 
 34 /**
 35  * e_flexible_strtod:
 36  * @nptr:    the string to convert to a numeric value.
 37  * @endptr:  if non-NULL, it returns the character after
 38  *           the last character used in the conversion.
 39  *
 40  * Converts a string to a gdouble value.  This function detects
 41  * strings either in the standard C locale or in the current locale.
 42  *
 43  * This function is typically used when reading configuration files or
 44  * other non-user input that should not be locale dependent, but may
 45  * have been in the past.  To handle input from the user you should
 46  * normally use the locale-sensitive system strtod function.
 47  *
 48  * To convert from a double to a string in a locale-insensitive way, use
 49  * @g_ascii_dtostr.
 50  *
 51  * Returns: the gdouble value
 52  **/
 53 
 54 gdouble
 55 e_flexible_strtod (const gchar *nptr,
 56                    gchar **endptr)
 57 {
 58 	gchar *fail_pos;
 59 	gdouble val;
 60 	struct lconv *locale_data;
 61 	const gchar *decimal_point;
 62 	gint decimal_point_len;
 63 	const gchar *p, *decimal_point_pos;
 64 	const gchar *end = NULL; /* Silence gcc */
 65 	gchar *copy, *c;
 66 
 67 	g_return_val_if_fail (nptr != NULL, 0);
 68 
 69 	fail_pos = NULL;
 70 
 71 	locale_data = localeconv ();
 72 	decimal_point = locale_data->decimal_point;
 73 	decimal_point_len = strlen (decimal_point);
 74 
 75 	g_return_val_if_fail (decimal_point_len != 0, 0);
 76 
 77 	decimal_point_pos = NULL;
 78 	if (!strcmp (decimal_point, "."))
 79 		return strtod (nptr, endptr);
 80 
 81 	p = nptr;
 82 
 83 	/* Skip leading space */
 84 	while (isspace ((guchar) * p))
 85 		p++;
 86 
 87 	/* Skip leading optional sign */
 88 	if (*p == '+' || *p == '-')
 89 		p++;
 90 
 91 	if (p[0] == '0' &&
 92 	    (p[1] == 'x' || p[1] == 'X')) {
 93 		p += 2;
 94 		/* HEX - find the (optional) decimal point */
 95 
 96 		while (isxdigit ((guchar) * p))
 97 			p++;
 98 
 99 		if (*p == '.') {
100 			decimal_point_pos = p++;
101 
102 			while (isxdigit ((guchar) * p))
103 				p++;
104 
105 			if (*p == 'p' || *p == 'P')
106 				p++;
107 			if (*p == '+' || *p == '-')
108 				p++;
109 			while (isdigit ((guchar) * p))
110 				p++;
111 			end = p;
112 		} else if (strncmp (p, decimal_point, decimal_point_len) == 0) {
113 			return strtod (nptr, endptr);
114 		}
115 	} else {
116 		while (isdigit ((guchar) * p))
117 			p++;
118 
119 		if (*p == '.') {
120 			decimal_point_pos = p++;
121 
122 			while (isdigit ((guchar) * p))
123 				p++;
124 
125 			if (*p == 'e' || *p == 'E')
126 				p++;
127 			if (*p == '+' || *p == '-')
128 				p++;
129 			while (isdigit ((guchar) * p))
130 				p++;
131 			end = p;
132 		} else if (strncmp (p, decimal_point, decimal_point_len) == 0) {
133 			return strtod (nptr, endptr);
134 		}
135 	}
136 	/* For the other cases, we need not convert the decimal point */
137 
138 	if (!decimal_point_pos)
139 		return strtod (nptr, endptr);
140 
141 	/* We need to convert the '.' to the locale specific decimal point */
142 	copy = g_malloc (end - nptr + 1 + decimal_point_len);
143 
144 	c = copy;
145 	memcpy (c, nptr, decimal_point_pos - nptr);
146 	c += decimal_point_pos - nptr;
147 	memcpy (c, decimal_point, decimal_point_len);
148 	c += decimal_point_len;
149 	memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
150 	c += end - (decimal_point_pos + 1);
151 	*c = 0;
152 
153 	val = strtod (copy, &fail_pos);
154 
155 	if (fail_pos) {
156 		if (fail_pos > decimal_point_pos)
157 			fail_pos =
158 				(gchar *) nptr + (fail_pos - copy) -
159 				(decimal_point_len - 1);
160 		else
161 			fail_pos = (gchar *) nptr + (fail_pos - copy);
162 	}
163 
164 	g_free (copy);
165 
166 	if (endptr)
167 		*endptr = fail_pos;
168 
169 	return val;
170 }
171 
172 /**
173  * e_ascii_dtostr:
174  * @buffer: A buffer to place the resulting string in
175  * @buf_len: The length of the buffer.
176  * @format: The printf-style format to use for the
177  *          code to use for converting.
178  * @d: The double to convert
179  *
180  * Converts a double to a string, using the '.' as
181  * decimal_point. To format the number you pass in
182  * a printf-style formating string. Allowed conversion
183  * specifiers are eEfFgG.
184  *
185  * If you want to generates enough precision that converting
186  * the string back using @g_strtod gives the same machine-number
187  * (on machines with IEEE compatible 64bit doubles) use the format
188  * string "%.17g". If you do this it is guaranteed that the size
189  * of the resulting string will never be larger than
190  * @G_ASCII_DTOSTR_BUF_SIZE bytes.
191  *
192  * Returns: the pointer to the buffer with the converted string
193  **/
194 gchar *
195 e_ascii_dtostr (gchar *buffer,
196                 gint buf_len,
197                 const gchar *format,
198                 gdouble d)
199 {
200 	struct lconv *locale_data;
201 	const gchar *decimal_point;
202 	gint decimal_point_len;
203 	gchar *p;
204 	gint rest_len;
205 	gchar format_char;
206 
207 	g_return_val_if_fail (buffer != NULL, NULL);
208 	g_return_val_if_fail (format[0] == '%', NULL);
209 	g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL);
210 
211 	format_char = format[strlen (format) - 1];
212 
213 	g_return_val_if_fail (format_char == 'e' || format_char == 'E' ||
214 			      format_char == 'f' || format_char == 'F' ||
215 			      format_char == 'g' || format_char == 'G',
216 			      NULL);
217 
218 	if (format[0] != '%')
219 		return NULL;
220 
221 	if (strpbrk (format + 1, "'l%"))
222 		return NULL;
223 
224 	if (!(format_char == 'e' || format_char == 'E' ||
225 	      format_char == 'f' || format_char == 'F' ||
226 	      format_char == 'g' || format_char == 'G'))
227 		return NULL;
228 
229 	g_snprintf (buffer, buf_len, format, d);
230 
231 	locale_data = localeconv ();
232 	decimal_point = locale_data->decimal_point;
233 	decimal_point_len = strlen (decimal_point);
234 
235 	g_return_val_if_fail (decimal_point_len != 0, NULL);
236 
237 	if (strcmp (decimal_point, ".")) {
238 		p = buffer;
239 
240 		if (*p == '+' || *p == '-')
241 			p++;
242 
243 		while (isdigit ((guchar) * p))
244 			p++;
245 
246 		if (strncmp (p, decimal_point, decimal_point_len) == 0) {
247 			*p = '.';
248 			p++;
249 			if (decimal_point_len > 1) {
250 				rest_len = strlen (p + (decimal_point_len - 1));
251 				memmove (
252 					p, p + (decimal_point_len - 1),
253 					rest_len);
254 				p[rest_len] = 0;
255 			}
256 		}
257 	}
258 
259 	return buffer;
260 }
261 
262 /**
263  * e_builder_get_widget:
264  * @builder: a #GtkBuilder
265  * @widget_name: name of a widget in @builder
266  *
267  * Gets the widget named @widget_name.  Note that this function does not
268  * increment the reference count of the returned widget.  If @widget_name
269  * could not be found in the @builder<!-- -->'s object tree, a run-time
270  * warning is emitted since this usually indicates a programming error.
271  *
272  * This is a convenience function to work around the awkwardness of
273  * #GtkBuilder returning #GObject pointers, when the vast majority of
274  * the time you want a #GtkWidget pointer.
275  *
276  * If you need something from @builder other than a #GtkWidget, or you
277  * want to test for the existence of some widget name without incurring
278  * a run-time warning, use gtk_builder_get_object().
279  *
280  * Returns: the widget named @widget_name, or %NULL
281  **/
282 GtkWidget *
283 e_builder_get_widget (GtkBuilder *builder,
284                       const gchar *widget_name)
285 {
286 	GObject *object;
287 
288 	g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
289 	g_return_val_if_fail (widget_name != NULL, NULL);
290 
291 	object = gtk_builder_get_object (builder, widget_name);
292 	if (object == NULL) {
293 		g_warning ("Could not find widget '%s'", widget_name);
294 		return NULL;
295 	}
296 
297 	return GTK_WIDGET (object);
298 }
299 
300 /**
301  * e_load_ui_builder_definition:
302  * @builder: a #GtkBuilder
303  * @basename: basename of the UI definition file
304  *
305  * Loads a UI definition into @builder from Evolution's UI directory.
306  * Failure here is fatal, since the application can't function without
307  * its UI definitions.
308  **/
309 void
310 e_load_ui_builder_definition (GtkBuilder *builder,
311                               const gchar *basename)
312 {
313 	gchar *filename;
314 	GError *error = NULL;
315 
316 	g_return_if_fail (GTK_IS_BUILDER (builder));
317 	g_return_if_fail (basename != NULL);
318 
319 	filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL);
320 	gtk_builder_add_from_file (builder, filename, &error);
321 	g_free (filename);
322 
323 	if (error != NULL) {
324 		g_error ("%s: %s", basename, error->message);
325 		g_assert_not_reached ();
326 	}
327 }