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