1 /* gdict-utils.c - Utility functions for Gdict
2 *
3 * Copyright (C) 2005 Emmanuele Bassi <ebassi@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <netdb.h>
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33
34 #include <glib.h>
35 #include <glib/gi18n-lib.h>
36 #include <gtk/gtk.h>
37
38 #include "gdict-context-private.h"
39 #include "gdict-debug.h"
40 #include "gdict-utils.h"
41 #include "gdict-private.h"
42
43 guint gdict_major_version = GDICT_MAJOR_VERSION;
44 guint gdict_minor_version = GDICT_MINOR_VERSION;
45 guint gdict_micro_version = GDICT_MICRO_VERSION;
46
47 guint gdict_debug_flags = 0; /* global gdict debug flag */
48
49 #ifdef GDICT_ENABLE_DEBUG
50 static const GDebugKey gdict_debug_keys[] = {
51 { "misc", GDICT_DEBUG_MISC },
52 { "context", GDICT_DEBUG_CONTEXT },
53 { "dict", GDICT_DEBUG_DICT },
54 { "source", GDICT_DEBUG_SOURCE },
55 { "loader", GDICT_DEBUG_LOADER },
56 { "chooser", GDICT_DEBUG_CHOOSER },
57 { "defbux", GDICT_DEBUG_DEFBOX },
58 { "speller", GDICT_DEBUG_SPELLER },
59 };
60 #endif /* GDICT_ENABLE_DEBUG */
61
62 static gboolean gdict_is_initialized = FALSE;
63
64 #ifdef GDICT_ENABLE_DEBUG
65 static gboolean
gdict_arg_debug_cb(const char * key,const char * value,gpointer user_data)66 gdict_arg_debug_cb (const char *key,
67 const char *value,
68 gpointer user_data)
69 {
70 gdict_debug_flags |=
71 g_parse_debug_string (value,
72 gdict_debug_keys,
73 G_N_ELEMENTS (gdict_debug_keys));
74 return TRUE;
75 }
76
77 static gboolean
gdict_arg_no_debug_cb(const char * key,const char * value,gpointer user_data)78 gdict_arg_no_debug_cb (const char *key,
79 const char *value,
80 gpointer user_data)
81 {
82 gdict_debug_flags &=
83 ~g_parse_debug_string (value,
84 gdict_debug_keys,
85 G_N_ELEMENTS (gdict_debug_keys));
86 return TRUE;
87 }
88 #endif /* GDICT_ENABLE_DEBUG */
89
90 static GOptionEntry gdict_args[] = {
91 #ifdef GDICT_ENABLE_DEBUG
92 { "gdict-debug", 0, 0, G_OPTION_ARG_CALLBACK, gdict_arg_debug_cb,
93 N_("GDict debugging flags to set"), N_("FLAGS") },
94 { "gdict-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, gdict_arg_no_debug_cb,
95 N_("GDict debugging flags to unset"), N_("FLAGS") },
96 #endif /* GDICT_ENABLE_DEBUG */
97 { NULL, },
98 };
99
100 static gboolean
pre_parse_hook(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)101 pre_parse_hook (GOptionContext *context,
102 GOptionGroup *group,
103 gpointer data,
104 GError **error)
105 {
106 if (gdict_is_initialized)
107 return TRUE;
108
109 #ifdef GDICT_ENABLE_DEBUG
110 const char *env_string = g_getenv ("GDICT_DEBUG");
111 if (env_string != NULL)
112 {
113 gdict_debug_flags =
114 g_parse_debug_string (env_string,
115 gdict_debug_keys,
116 G_N_ELEMENTS (gdict_debug_keys));
117 }
118 #endif /* GDICT_ENABLE_DEBUG */
119
120 return TRUE;
121 }
122
123 static gboolean
post_parse_hook(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)124 post_parse_hook (GOptionContext *context,
125 GOptionGroup *group,
126 gpointer data,
127 GError **error)
128 {
129 if (gdict_is_initialized)
130 return TRUE;
131
132 return TRUE;
133 }
134
135 /**
136 * gdict_get_option_group: (skip)
137 *
138 * FIXME
139 *
140 * Return value: (transfer full): FIXME
141 *
142 * Since: 0.12
143 */
144 GOptionGroup *
gdict_get_option_group(void)145 gdict_get_option_group (void)
146 {
147 GOptionGroup *group;
148
149 group = g_option_group_new ("gdict",
150 _("GDict Options"),
151 _("Show GDict Options"),
152 NULL,
153 NULL);
154
155 g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
156 g_option_group_add_entries (group, gdict_args);
157 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
158
159 return group;
160 }
161
162 /**
163 * gdict_debug_init:
164 * @argc: FIXME
165 * @argv: FIXME
166 *
167 * FIXME
168 *
169 * Since: 0.12
170 */
171 void
gdict_debug_init(gint * argc,gchar *** argv)172 gdict_debug_init (gint *argc,
173 gchar ***argv)
174 {
175 GOptionContext *option_context;
176 GOptionGroup *gdict_group;
177 GError *error = NULL;
178
179 if (gdict_is_initialized)
180 return;
181
182 option_context = g_option_context_new (NULL);
183 g_option_context_set_ignore_unknown_options (option_context, TRUE);
184 g_option_context_set_help_enabled (option_context, FALSE);
185
186 gdict_group = gdict_get_option_group ();
187 g_option_context_set_main_group (option_context, gdict_group);
188
189 if (!g_option_context_parse (option_context, argc, argv, &error))
190 {
191 g_warning ("%s", error->message);
192 g_error_free (error);
193 }
194
195 g_option_context_free (option_context);
196 }
197
198 gboolean
gdict_check_version(guint required_major,guint required_minor,guint required_micro)199 gdict_check_version (guint required_major,
200 guint required_minor,
201 guint required_micro)
202 {
203 gint gdict_effective_micro = 100 * GDICT_MINOR_VERSION + GDICT_MICRO_VERSION;
204 gint required_effective_micro = 100 * required_minor + required_micro;
205
206 if (required_major > GDICT_MAJOR_VERSION)
207 return FALSE;
208
209 if (required_major < GDICT_MAJOR_VERSION)
210 return FALSE;
211
212 if (required_effective_micro < gdict_effective_micro)
213 return FALSE;
214
215 if (required_effective_micro > gdict_effective_micro)
216 return FALSE;
217
218 return TRUE;
219 }
220 /* gdict_has_ipv6: checks for the existence of the IPv6 extensions; if
221 * IPv6 support was not enabled, this function always return false
222 */
223 gboolean
_gdict_has_ipv6(void)224 _gdict_has_ipv6 (void)
225 {
226 #ifdef ENABLE_IPV6
227 int s;
228
229 s = socket (AF_INET6, SOCK_STREAM, 0);
230 if (s != -1)
231 {
232 close(s);
233
234 return TRUE;
235 }
236 #endif
237
238 return FALSE;
239 }
240
241 /* shows an error dialog making it transient for @parent */
242 static void
show_error_dialog(GtkWindow * parent,const gchar * message,const gchar * detail)243 show_error_dialog (GtkWindow *parent,
244 const gchar *message,
245 const gchar *detail)
246 {
247 GtkWidget *dialog;
248
249 dialog = gtk_message_dialog_new (parent,
250 GTK_DIALOG_DESTROY_WITH_PARENT,
251 GTK_MESSAGE_ERROR,
252 GTK_BUTTONS_OK,
253 "%s", message);
254 gtk_window_set_title (GTK_WINDOW (dialog), "");
255
256 if (detail)
257 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
258 "%s", detail);
259
260 if (parent && gtk_window_get_group (parent))
261 gtk_window_group_add_window (gtk_window_get_group (parent), GTK_WINDOW (dialog));
262
263 gtk_dialog_run (GTK_DIALOG (dialog));
264
265 gtk_widget_destroy (dialog);
266 }
267
268 /* find the toplevel widget for @widget */
269 static GtkWindow *
get_toplevel_window(GtkWidget * widget)270 get_toplevel_window (GtkWidget *widget)
271 {
272 GtkWidget *toplevel;
273
274 toplevel = gtk_widget_get_toplevel (widget);
275 if (!gtk_widget_is_toplevel (toplevel))
276 return NULL;
277 else
278 return GTK_WINDOW (toplevel);
279 }
280
281 /**
282 * gdict_show_error_dialog:
283 * @widget: the widget that emits the error
284 * @title: the primary error message
285 * @message: (nullable): the secondary error message or %NULL
286 *
287 * Creates and shows an error dialog bound to @widget.
288 *
289 * Since: 1.0
290 */
291 void
_gdict_show_error_dialog(GtkWidget * widget,const gchar * title,const gchar * detail)292 _gdict_show_error_dialog (GtkWidget *widget,
293 const gchar *title,
294 const gchar *detail)
295 {
296 g_return_if_fail (GTK_IS_WIDGET (widget));
297 g_return_if_fail (title != NULL);
298
299 show_error_dialog (get_toplevel_window (widget), title, detail);
300 }
301
302 /**
303 * gdict_show_gerror_dialog:
304 * @widget: the widget that emits the error
305 * @title: the primary error message
306 * @error: a #GError
307 *
308 * Creates and shows an error dialog bound to @widget, using @error
309 * to fill the secondary text of the message dialog with the error
310 * message. Also takes care of freeing @error.
311 *
312 * Since: 1.0
313 */
314 void
_gdict_show_gerror_dialog(GtkWidget * widget,const gchar * title,GError * error)315 _gdict_show_gerror_dialog (GtkWidget *widget,
316 const gchar *title,
317 GError *error)
318 {
319 g_return_if_fail (GTK_IS_WIDGET (widget));
320 g_return_if_fail (title != NULL);
321 g_return_if_fail (error != NULL);
322
323 show_error_dialog (get_toplevel_window (widget), title, error->message);
324
325 g_error_free (error);
326 }
327
328 /**
329 * gdict_init:
330 * @argc: FIXME
331 * @argv: FIXME
332 *
333 * FIXME
334 *
335 * Since: 0.12
336 */
337 void
gdict_init(gint * argc,gchar *** argv)338 gdict_init (gint *argc,
339 gchar ***argv)
340 {
341 if (gdict_is_initialized)
342 return;
343
344 gdict_debug_init (argc, argv);
345
346 gdict_is_initialized = TRUE;
347 }
348