| 1 | #include "config.h" |
| 2 | |
| 3 | #include <sys/types.h> |
| 4 | #include <sys/stat.h> |
| 5 | #include <unistd.h> |
| 6 | #include <string.h> |
| 7 | |
| 8 | #include <gtk/gtk.h> |
| 9 | |
| 10 | #include "support.h" |
| 11 | |
| 12 | /* This is an internally used function to check if a pixmap file exists. */ |
| 13 | static gchar* check_file_exists (const gchar *directory, |
| 14 | const gchar *filename); |
| 15 | |
| 16 | /* This is an internally used function to create pixmaps. */ |
| 17 | static GtkWidget* create_dummy_pixmap (GtkWidget *widget); |
| 18 | |
| 19 | GtkWidget* |
| 20 | lookup_widget (GtkWidget *widget, |
| 21 | const gchar *widget_name) |
| 22 | { |
| 23 | GtkWidget *parent, *found_widget; |
| 24 | |
| 25 | for (;;) |
| 26 | { |
| 27 | if (GTK_IS_MENU (widget)) |
| 28 | parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); |
| 29 | else |
| 30 | parent = widget->parent; |
| 31 | if (parent == NULL) |
| 32 | break; |
| 33 | widget = parent; |
| 34 | } |
| 35 | |
| 36 | found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), |
| 37 | widget_name); |
| 38 | if (!found_widget) |
| 39 | g_warning ("Widget not found: %s", widget_name); |
| 40 | return found_widget; |
| 41 | } |
| 42 | |
| 43 | /* This is a dummy pixmap we use when a pixmap can't be found. */ |
| 44 | static char *dummy_pixmap_xpm[] = { |
| 45 | /* columns rows colors chars-per-pixel */ |
| 46 | "1 1 1 1", |
| 47 | " c None", |
| 48 | /* pixels */ |
| 49 | " " |
| 50 | }; |
| 51 | |
| 52 | /* This is an internally used function to create pixmaps. */ |
| 53 | static GtkWidget* |
| 54 | create_dummy_pixmap (GtkWidget *widget) |
| 55 | { |
| 56 | GdkColormap *colormap; |
| 57 | GdkPixmap *gdkpixmap; |
| 58 | GdkBitmap *mask; |
| 59 | GtkWidget *pixmap; |
| 60 | |
| 61 | colormap = gtk_widget_get_colormap (widget); |
| 62 | gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, |
| 63 | NULL, dummy_pixmap_xpm); |
| 64 | if (gdkpixmap == NULL) |
| 65 | g_error ("Couldn't create replacement pixmap."); |
| 66 | pixmap = gtk_pixmap_new (gdkpixmap, mask); |
| 67 | gdk_pixmap_unref (gdkpixmap); |
| 68 | gdk_bitmap_unref (mask); |
| 69 | return pixmap; |
| 70 | } |
| 71 | |
| 72 | static GList *pixmaps_directories = NULL; |
| 73 | |
| 74 | /* Use this function to set the directory containing installed pixmaps. */ |
| 75 | void |
| 76 | add_pixmap_directory (const gchar *directory) |
| 77 | { |
| 78 | pixmaps_directories = g_list_prepend (pixmaps_directories, |
| 79 | g_strdup (directory)); |
| 80 | } |
| 81 | |
| 82 | /* This is an internally used function to create pixmaps. */ |
| 83 | GtkWidget* |
| 84 | create_pixmap (GtkWidget *widget, |
| 85 | const gchar *filename) |
| 86 | { |
| 87 | gchar *found_filename = NULL; |
| 88 | GdkColormap *colormap; |
| 89 | GdkPixmap *gdkpixmap; |
| 90 | GdkBitmap *mask; |
| 91 | GtkWidget *pixmap; |
| 92 | GList *elem; |
| 93 | |
| 94 | if (!filename || !filename[0]) |
| 95 | return create_dummy_pixmap (widget); |
| 96 | |
| 97 | /* We first try any pixmaps directories set by the application. */ |
| 98 | elem = pixmaps_directories; |
| 99 | while (elem) |
| 100 | { |
| 101 | found_filename = check_file_exists ((gchar*)elem->data, filename); |
| 102 | if (found_filename) |
| 103 | break; |
| 104 | elem = elem->next; |
| 105 | } |
| 106 | |
| 107 | /* If we haven't found the pixmap, try the source directory. */ |
| 108 | if (!found_filename) |
| 109 | { |
| 110 | found_filename = check_file_exists ("../pixmaps", filename); |
| 111 | } |
| 112 | |
| 113 | if (!found_filename) |
| 114 | { |
| 115 | g_warning ("Couldn't find pixmap file: %s", filename); |
| 116 | return create_dummy_pixmap (widget); |
| 117 | } |
| 118 | |
| 119 | colormap = gtk_widget_get_colormap (widget); |
| 120 | gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, |
| 121 | NULL, found_filename); |
| 122 | if (gdkpixmap == NULL) |
| 123 | { |
| 124 | g_warning ("Error loading pixmap file: %s", found_filename); |
| 125 | g_free (found_filename); |
| 126 | return create_dummy_pixmap (widget); |
| 127 | } |
| 128 | g_free (found_filename); |
| 129 | pixmap = gtk_pixmap_new (gdkpixmap, mask); |
| 130 | gdk_pixmap_unref (gdkpixmap); |
| 131 | gdk_bitmap_unref (mask); |
| 132 | return pixmap; |
| 133 | } |
| 134 | |
| 135 | /* This is an internally used function to check if a pixmap file exists. */ |
| 136 | gchar* |
| 137 | check_file_exists (const gchar *directory, |
| 138 | const gchar *filename) |
| 139 | { |
| 140 | gchar *full_filename; |
| 141 | struct stat s; |
| 142 | gint status; |
| 143 | |
| 144 | full_filename = (gchar*) g_malloc (strlen (directory) + 1 |
| 145 | + strlen (filename) + 1); |
| 146 | strcpy (full_filename, directory); |
| 147 | strcat (full_filename, G_DIR_SEPARATOR_S); |
| 148 | strcat (full_filename, filename); |
| 149 | |
| 150 | status = stat (full_filename, &s); |
| 151 | if (status == 0 && S_ISREG (s.st_mode)) |
| 152 | return full_filename; |
| 153 | g_free (full_filename); |
| 154 | return NULL; |
| 155 | } |