diff options
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c new file mode 100644 index 00000000..0c101866 --- /dev/null +++ b/src/util.c @@ -0,0 +1,417 @@ +/* + * util.c + * + * Copyright (C) 2002 Sun Microsystems, Inc. + * (C) 1999, 2000 Red Hat Inc. + * (C) 1998 James Henstridge + * (C) 1995-2002 Free Software Foundation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * Authors: Glynn Foster <glynn.foster@sun.com> + * Havoc Pennington <hp@redhat.com> + * James Henstridge <james@daa.com.au> + * Tom Tromey <tromey@redhat.com> + */ + +#include "config.h" + +#include "config.h" +#include "util.h" +#include "zenity.h" +#include <errno.h> +#include <locale.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef GDK_WINDOWING_X11 +#include <gdk/gdkx.h> +#endif + +#define ZENITY_OK_DEFAULT 0 +#define ZENITY_CANCEL_DEFAULT 1 +#define ZENITY_ESC_DEFAULT 1 +#define ZENITY_ERROR_DEFAULT -1 +#define ZENITY_EXTRA_DEFAULT 127 + +GtkBuilder * +zenity_util_load_ui_file (const gchar *root_widget, ...) { + va_list args; + gchar *arg = NULL; + GPtrArray *ptrarray; + GtkBuilder *builder = gtk_builder_new (); + GError *error = NULL; + gchar **objects; + guint result = 0; + + gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); + + /* We have at least the root_widget and a NULL */ + ptrarray = g_ptr_array_sized_new (2); + + g_ptr_array_add (ptrarray, g_strdup (root_widget)); + + va_start (args, root_widget); + + arg = va_arg (args, gchar *); + + while (arg) { + g_ptr_array_add (ptrarray, g_strdup (arg)); + arg = va_arg (args, gchar *); + } + va_end (args); + + /* Enforce terminating NULL */ + g_ptr_array_add (ptrarray, NULL); + objects = (gchar **) g_ptr_array_free (ptrarray, FALSE); + + if (g_file_test (ZENITY_UI_FILE_RELATIVEPATH, G_FILE_TEST_EXISTS)) { + /* Try current dir, for debugging */ + result = gtk_builder_add_objects_from_file ( + builder, ZENITY_UI_FILE_RELATIVEPATH, objects, NULL); + } + + if (result == 0) + result = gtk_builder_add_objects_from_file ( + builder, ZENITY_UI_FILE_FULLPATH, objects, &error); + + g_strfreev (objects); + + if (result == 0) { + g_warning ("Could not load ui file %s: %s", + ZENITY_UI_FILE_FULLPATH, + error->message); + g_error_free (error); + g_object_unref (builder); + return NULL; + } + + return builder; +} +gchar * +zenity_util_strip_newline (gchar *string) { + gsize len; + + g_return_val_if_fail (string != NULL, NULL); + + len = strlen (string); + while (len--) { + if (string[len] == '\n') + string[len] = '\0'; + else + break; + } + + return string; +} + +gboolean +zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const gchar *filename) { + GtkTextIter iter, end; + FILE *f; + gchar buf[2048]; + gint remaining = 0; + + if (filename == NULL) + return FALSE; + + f = fopen (filename, "r"); + + if (f == NULL) { + g_warning ("Cannot open file '%s': %s", filename, g_strerror (errno)); + return FALSE; + } + + gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0); + + while (!feof (f)) { + gint count; + const char *leftover; + int to_read = 2047 - remaining; + + count = fread (buf + remaining, 1, to_read, f); + buf[count + remaining] = '\0'; + + g_utf8_validate (buf, count + remaining, &leftover); + + g_assert (g_utf8_validate (buf, leftover - buf, NULL)); + gtk_text_buffer_insert (buffer, &iter, buf, leftover - buf); + + remaining = (buf + remaining + count) - leftover; + g_memmove (buf, leftover, remaining); + + if (remaining > 6 || count < to_read) + break; + } + + if (remaining) { + g_warning ( + "Invalid UTF-8 data encountered reading file '%s'", filename); + return FALSE; + } + + /* We had a newline in the buffer to begin with. (The buffer always contains + * a newline, so we delete to the end of the buffer to clean up. + */ + + gtk_text_buffer_get_end_iter (buffer, &end); + gtk_text_buffer_delete (buffer, &iter, &end); + + gtk_text_buffer_set_modified (buffer, FALSE); + + return TRUE; +} + +const gchar * +zenity_util_icon_name_from_filename (const gchar *filename) { + if (!filename || !filename[0]) + return "dialog-warning"; /* default */ + + if (!g_ascii_strcasecmp (filename, "warning")) + return "dialog-warning"; + if (!g_ascii_strcasecmp (filename, "info")) + return "dialog-information"; + if (!g_ascii_strcasecmp (filename, "question")) + return "dialog-question"; + if (!g_ascii_strcasecmp (filename, "error")) + return "dialog-error"; + return NULL; +} + +void +zenity_util_set_window_icon_from_file ( + GtkWidget *widget, const gchar *filename) { + GdkPixbuf *pixbuf; + const gchar *icon_name; + + icon_name = zenity_util_icon_name_from_filename (filename); + if (icon_name) { + gtk_window_set_icon_name (GTK_WINDOW (widget), icon_name); + } else { + pixbuf = gdk_pixbuf_new_from_file (filename, NULL); + gtk_window_set_icon (GTK_WINDOW (widget), pixbuf); + g_object_unref (pixbuf); + } +} + +void +zenity_util_set_window_icon ( + GtkWidget *widget, const gchar *filename, const gchar *default_file) { + GdkPixbuf *pixbuf; + + if (filename != NULL) { + zenity_util_set_window_icon_from_file (widget, filename); + } else { + pixbuf = gdk_pixbuf_new_from_file (default_file, NULL); + if (pixbuf != NULL) { + gtk_window_set_icon (GTK_WINDOW (widget), pixbuf); + g_object_unref (pixbuf); + } + } +} + +void +zenity_util_set_window_icon_from_icon_name ( + GtkWidget *widget, const gchar *filename, const gchar *default_icon_name) { + if (filename != NULL) + zenity_util_set_window_icon_from_file (widget, filename); + else + gtk_window_set_icon_name (GTK_WINDOW (widget), default_icon_name); +} + +void +zenity_util_show_help (GError **error) { + gchar *tmp; + tmp = g_find_program_in_path ("yelp"); + + if (tmp) { + g_free (tmp); + g_spawn_command_line_async ("yelp help:zenity", error); + } +} + +gint +zenity_util_return_exit_code (ZenityExitCode value) { + + const gchar *env_var = NULL; + gint retval; + + switch (value) { + + case ZENITY_OK: + env_var = g_getenv ("ZENITY_OK"); + if (!env_var) + env_var = g_getenv ("DIALOG_OK"); + if (!env_var) + retval = ZENITY_OK_DEFAULT; + break; + + case ZENITY_CANCEL: + env_var = g_getenv ("ZENITY_CANCEL"); + if (!env_var) + env_var = g_getenv ("DIALOG_CANCEL"); + if (!env_var) + retval = ZENITY_CANCEL_DEFAULT; + break; + + case ZENITY_ESC: + env_var = g_getenv ("ZENITY_ESC"); + if (!env_var) + env_var = g_getenv ("DIALOG_ESC"); + if (!env_var) + retval = ZENITY_ESC_DEFAULT; + break; + + case ZENITY_EXTRA: + env_var = g_getenv ("ZENITY_EXTRA"); + if (!env_var) + env_var = g_getenv ("DIALOG_EXTRA"); + if (!env_var) + retval = ZENITY_EXTRA_DEFAULT; + break; + + case ZENITY_ERROR: + env_var = g_getenv ("ZENITY_ERROR"); + if (!env_var) + env_var = g_getenv ("DIALOG_ERROR"); + if (!env_var) + retval = ZENITY_ERROR_DEFAULT; + break; + + case ZENITY_TIMEOUT: + env_var = g_getenv ("ZENITY_TIMEOUT"); + if (!env_var) + env_var = g_getenv ("DIALOG_TIMEOUT"); + if (!env_var) + retval = ZENITY_TIMEOUT; + break; + + default: + retval = 1; + } + + if (env_var) + retval = atoi (env_var); + return retval; +} + +void +zenity_util_exit_code_with_data (ZenityExitCode value, ZenityData *zen_data) { + zen_data->exit_code = zenity_util_return_exit_code (value); +} + +#ifdef GDK_WINDOWING_X11 + +static Window +transient_get_xterm (void) { + const char *wid_str = g_getenv ("WINDOWID"); + if (wid_str) { + char *wid_str_end; + int ret; + Window wid = strtoul (wid_str, &wid_str_end, 10); + if (*wid_str != '\0' && *wid_str_end == '\0' && wid != 0) { + XWindowAttributes attrs; + gdk_error_trap_push (); + ret = XGetWindowAttributes ( + GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), wid, &attrs); + gdk_flush (); + if (gdk_error_trap_pop () != 0 || ret == 0) { + return None; + } + return wid; + } + } + return None; +} + +static void +transient_x_free (void *ptr) { + if (ptr) + XFree (ptr); +} + +static gboolean +transient_is_toplevel (Window wid) { + XTextProperty prop; + Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + if (!XGetWMName (dpy, wid, &prop)) + return FALSE; + transient_x_free (prop.value); + return !!prop.value; +} + +/* + * GNOME Terminal doesn't give us its toplevel window, but the WM needs a + * toplevel XID for proper stacking. Other terminals work fine without this + * magic. We can't use GDK here since "xterm" is a foreign window. + */ + +static Window +transient_get_xterm_toplevel (void) { + Window xterm = transient_get_xterm (); + Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + while (xterm != None && !transient_is_toplevel (xterm)) { + Window root, parent, *children; + unsigned nchildren; + XQueryTree (dpy, xterm, &root, &parent, &children, &nchildren); + transient_x_free (children); + if (parent == root) + xterm = None; + else + xterm = parent; + } + return xterm; +} + +static void +zenity_util_make_transient (GdkWindow *window, Window parent) { + Window parent_window = parent; + if (parent_window == 0) + parent_window = transient_get_xterm_toplevel (); + if (parent_window != None) { + XSetTransientForHint (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), + GDK_WINDOW_XID (window), + parent_window); + } +} + +#endif /* GDK_WINDOWING_X11 */ + +void +zenity_util_show_dialog (GtkWidget *dialog, guintptr parent) { + gtk_widget_realize (dialog); +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + g_assert (gtk_widget_get_window (dialog)); + zenity_util_make_transient (gtk_widget_get_window (dialog), parent); + } +#endif + gtk_widget_show (dialog); +} + +gboolean +zenity_util_timeout_handle (gpointer data) { + GtkDialog *dialog = GTK_DIALOG (data); + if (dialog != NULL) + gtk_dialog_response (dialog, ZENITY_TIMEOUT); + else { + gtk_main_quit (); + exit (ZENITY_TIMEOUT); + } + return FALSE; +} |