summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c417
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;
+}
bgstack15