summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c478
1 files changed, 284 insertions, 194 deletions
diff --git a/src/util.c b/src/util.c
index 2887fd9..1cc21af 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,22 +1,25 @@
+/* vim: colorcolumn=80 ts=4 sw=4
+ */
/*
* util.c
*
- * Copyright (C) 2002 Sun Microsystems, Inc.
- * (C) 1999, 2000 Red Hat Inc.
- * (C) 1998 James Henstridge
- * (C) 1995-2002 Free Software Foundation
+ * Copyright © 2002 Sun Microsystems, Inc.
+ * © 1999, 2000 Red Hat Inc.
+ * © 1998 James Henstridge
+ * © 1995-2002 Free Software Foundation
+ * © 2021-2023 Logan Rathbone
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser 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.
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser 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.
@@ -27,11 +30,9 @@
* 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>
@@ -39,25 +40,49 @@
#include <stdlib.h>
#include <string.h>
-#ifdef GDK_WINDOWING_X11
-#include <gdk/gdkx.h>
-#endif
+#include "config.h"
#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
+#define ZENITY_UI_RESOURCE_PATH RESOURCE_BASE_PATH "/zenity.ui"
+
+GIcon *
+zenity_util_gicon_from_string (const char *str)
+{
+ GIcon *icon = NULL;
+ g_autoptr(GFile) icon_file = NULL;
+
+ if (str)
+ {
+ icon_file = g_file_new_for_path (str);
+
+ if (g_file_query_exists (icon_file, NULL))
+ {
+ icon = g_file_icon_new (icon_file);
+ }
+ else
+ {
+ g_debug (_("Icon filename %s not found; trying theme icon."), str);
+ icon = g_themed_icon_new_with_default_fallbacks (str);
+ }
+ }
+
+ return icon;
+}
GtkBuilder *
-zenity_util_load_ui_file (const gchar *root_widget, ...) {
+zenity_util_load_ui_file (const char *root_widget, ...)
+{
va_list args;
- gchar *arg = NULL;
+ char *arg = NULL;
GPtrArray *ptrarray;
GtkBuilder *builder = gtk_builder_new ();
- GError *error = NULL;
- gchar **objects;
- guint result = 0;
+ g_autoptr(GError) error = NULL;
+ char **objects;
+ gboolean result = FALSE;
gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
@@ -68,43 +93,43 @@ zenity_util_load_ui_file (const gchar *root_widget, ...) {
va_start (args, root_widget);
- arg = va_arg (args, gchar *);
+ arg = va_arg (args, char *);
while (arg) {
g_ptr_array_add (ptrarray, g_strdup (arg));
- arg = va_arg (args, gchar *);
+ arg = va_arg (args, char *);
}
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);
- }
+ objects = (char **)g_ptr_array_free (ptrarray, FALSE);
- if (result == 0)
- result = gtk_builder_add_objects_from_file (
- builder, ZENITY_UI_FILE_FULLPATH, objects, &error);
+ result = gtk_builder_add_objects_from_resource (builder,
+ ZENITY_UI_RESOURCE_PATH,
+ (const char **)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;
+ if (! result) {
+ g_error ("Could not load ui resource %s: %s",
+ ZENITY_UI_RESOURCE_PATH,
+ error->message);
+ }
+
+ /* This should never happen, but if an unexpected error is logged, print
+ * it for debugging purposes. */
+ if (error) {
+ g_debug ("%s: Error generated: %s",
+ __func__, error->message);
}
return builder;
}
-gchar *
-zenity_util_strip_newline (gchar *string) {
+
+char *
+zenity_util_strip_newline (char *string) {
gsize len;
g_return_val_if_fail (string != NULL, NULL);
@@ -121,11 +146,11 @@ zenity_util_strip_newline (gchar *string) {
}
gboolean
-zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const gchar *filename) {
+zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const char *filename) {
GtkTextIter iter, end;
FILE *f;
- gchar buf[2048];
- gint remaining = 0;
+ char buf[2048];
+ int remaining = 0;
if (filename == NULL)
return FALSE;
@@ -140,7 +165,7 @@ zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const gchar *filename) {
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
while (!feof (f)) {
- gint count;
+ int count;
const char *leftover;
int to_read = 2047 - remaining;
@@ -153,7 +178,7 @@ zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const gchar *filename) {
gtk_text_buffer_insert (buffer, &iter, buf, leftover - buf);
remaining = (buf + remaining + count) - leftover;
- memmove (buf, leftover, remaining);
+ memmove(buf, leftover, remaining);
if (remaining > 6 || count < to_read)
break;
@@ -177,79 +202,19 @@ zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const gchar *filename) {
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");
+ g_autofree char *tmp = g_find_program_in_path ("yelp");
- if (tmp) {
- g_free (tmp);
+ if (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;
+int
+zenity_util_return_exit_code (ZenityExitCode value)
+{
+ const char *env_var = NULL;
+ int retval;
switch (value) {
@@ -311,108 +276,233 @@ zenity_util_return_exit_code (ZenityExitCode value) {
}
void
-zenity_util_exit_code_with_data (ZenityExitCode value, ZenityData *zen_data) {
+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;
- GdkDisplay *display;
- display = gdk_display_get_default ();
- gdk_x11_display_error_trap_push (display);
- ret = XGetWindowAttributes (
- GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), wid, &attrs);
- if (gdk_x11_display_error_trap_pop (display) != 0 || ret == 0) {
- return None;
- }
- return wid;
+/* This function was written by Matthias Clasen and is included somewhere in
+ * the GTK source tree.. I believe it is also included in libdazzle, but I
+ * didn't want to include a whole dependency just for one function. LGPL, but
+ * credit where credit is due!
+ */
+char *
+zenity_util_pango_font_description_to_css (PangoFontDescription *desc)
+{
+ GString *s;
+ PangoFontMask set;
+
+ s = g_string_new ("* { ");
+
+ set = pango_font_description_get_set_fields (desc);
+ if (set & PANGO_FONT_MASK_FAMILY)
+ {
+ g_string_append (s, "font-family: ");
+ g_string_append (s, pango_font_description_get_family (desc));
+ g_string_append (s, "; ");
+ }
+ if (set & PANGO_FONT_MASK_STYLE)
+ {
+ switch (pango_font_description_get_style (desc))
+ {
+ case PANGO_STYLE_NORMAL:
+ g_string_append (s, "font-style: normal; ");
+ break;
+ case PANGO_STYLE_OBLIQUE:
+ g_string_append (s, "font-style: oblique; ");
+ break;
+ case PANGO_STYLE_ITALIC:
+ g_string_append (s, "font-style: italic; ");
+ break;
}
}
- return None;
-}
+ if (set & PANGO_FONT_MASK_VARIANT)
+ {
+ switch (pango_font_description_get_variant (desc))
+ {
+ case PANGO_VARIANT_NORMAL:
+ g_string_append (s, "font-variant: normal; ");
+ break;
+ case PANGO_VARIANT_SMALL_CAPS:
+ g_string_append (s, "font-variant: small-caps; ");
+ break;
+ default:
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_WEIGHT)
+ {
+ switch (pango_font_description_get_weight (desc))
+ {
+ case PANGO_WEIGHT_THIN:
+ g_string_append (s, "font-weight: 100; ");
+ break;
+ case PANGO_WEIGHT_ULTRALIGHT:
+ g_string_append (s, "font-weight: 200; ");
+ break;
+ case PANGO_WEIGHT_LIGHT:
+ case PANGO_WEIGHT_SEMILIGHT:
+ g_string_append (s, "font-weight: 300; ");
+ break;
+ case PANGO_WEIGHT_BOOK:
+ case PANGO_WEIGHT_NORMAL:
+ g_string_append (s, "font-weight: 400; ");
+ break;
+ case PANGO_WEIGHT_MEDIUM:
+ g_string_append (s, "font-weight: 500; ");
+ break;
+ case PANGO_WEIGHT_SEMIBOLD:
+ g_string_append (s, "font-weight: 600; ");
+ break;
+ case PANGO_WEIGHT_BOLD:
+ g_string_append (s, "font-weight: 700; ");
+ break;
+ case PANGO_WEIGHT_ULTRABOLD:
+ g_string_append (s, "font-weight: 800; ");
+ break;
+ case PANGO_WEIGHT_HEAVY:
+ case PANGO_WEIGHT_ULTRAHEAVY:
+ g_string_append (s, "font-weight: 900; ");
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_STRETCH)
+ {
+ switch (pango_font_description_get_stretch (desc))
+ {
+ case PANGO_STRETCH_ULTRA_CONDENSED:
+ g_string_append (s, "font-stretch: ultra-condensed; ");
+ break;
+ case PANGO_STRETCH_EXTRA_CONDENSED:
+ g_string_append (s, "font-stretch: extra-condensed; ");
+ break;
+ case PANGO_STRETCH_CONDENSED:
+ g_string_append (s, "font-stretch: condensed; ");
+ break;
+ case PANGO_STRETCH_SEMI_CONDENSED:
+ g_string_append (s, "font-stretch: semi-condensed; ");
+ break;
+ case PANGO_STRETCH_NORMAL:
+ g_string_append (s, "font-stretch: normal; ");
+ break;
+ case PANGO_STRETCH_SEMI_EXPANDED:
+ g_string_append (s, "font-stretch: semi-expanded; ");
+ break;
+ case PANGO_STRETCH_EXPANDED:
+ g_string_append (s, "font-stretch: expanded; ");
+ break;
+ case PANGO_STRETCH_EXTRA_EXPANDED:
+ g_string_append (s, "font-stretch: extra-expanded; ");
+ break;
+ case PANGO_STRETCH_ULTRA_EXPANDED:
+ g_string_append (s, "font-stretch: ultra-expanded; ");
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_SIZE)
+ {
+ g_string_append_printf (s, "font-size: %dpt; ",
+ pango_font_description_get_size (desc) / PANGO_SCALE);
+ }
-static void
-transient_x_free (void *ptr) {
- if (ptr)
- XFree (ptr);
-}
+ g_string_append (s, "}");
-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;
+ return g_string_free (s, FALSE);
}
-/*
- * 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.
- */
+void
+zenity_util_show_dialog (GtkWidget *dialog)
+{
+ gtk_widget_show (dialog);
+}
-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;
+gboolean
+zenity_util_timeout_handle (AdwMessageDialog *dialog)
+{
+ if (dialog) {
+ adw_message_dialog_response (dialog, "timeout");
+ }
+ else {
+ exit (ZENITY_TIMEOUT);
}
- return xterm;
+ return FALSE;
}
-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);
+void
+zenity_util_gapp_main (GtkWindow *window)
+{
+ GApplication *app = g_application_get_default ();
+
+ if (window)
+ {
+ /* As this behaves quite differently if a window is provided vs. not,
+ * let's ensure any window passed is valid.
+ */
+ g_assert (GTK_IS_WINDOW (window));
+
+ gtk_application_add_window (GTK_APPLICATION(app), window);
+ }
+ else {
+ g_application_hold (g_application_get_default ());
}
}
-#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);
+zenity_util_gapp_quit (GtkWindow *window, ZenityData *data)
+{
+ /* This is a bit hack-ish, but GApplication doesn't really allow for
+ * customized exit statuses within that API.
+ */
+ if (data->exit_code != 0)
+ exit (data->exit_code);
+
+ if (window)
+ {
+ g_assert (GTK_IS_WINDOW (window));
+ gtk_window_destroy (window);
+ }
+ else {
+ g_application_release (g_application_get_default ());
}
-#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);
+int
+zenity_util_parse_dialog_response (const char *response)
+{
+ if (g_strcmp0 (response, "ok") == 0 || g_strcmp0 (response, "yes") == 0)
+ {
+ return ZENITY_OK;
}
- return FALSE;
+ else if (g_strcmp0 (response, "cancel") == 0 || g_strcmp0 (response, "no") == 0)
+ {
+ return ZENITY_CANCEL;
+ }
+ else if (g_strcmp0 (response, "timeout") == 0)
+ {
+ return ZENITY_TIMEOUT;
+ }
+ else if (response[0] >= '0' && response[0] <= '9')
+ {
+ /* FIXME - atoi returns 0 on error, so this *could* mean the function
+ * failed - but that would be a programmer error, so we'll leave this
+ * in place.
+ */
+ return atoi (response);
+ }
+ else
+ {
+ return ZENITY_ESC;
+ }
+}
+
+GtkWidget *
+zenity_util_add_button (AdwMessageDialog *dialog, const char *button_text,
+ ZenityExitCode response_id)
+{
+ GtkWidget *w = GTK_WIDGET(dialog);
+ g_autofree char *response_str = g_strdup_printf ("%d", response_id);
+
+ adw_message_dialog_add_response (dialog, response_str, button_text);
+
+ return w;
}