r126: Added better ref counting for file icons.
[rox-filer.git] / ROX-Filer / src / pixmaps.c
blobccf8e27c45121cb0c7b5380f44af0477fa60f6d8
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 1999, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* pixmaps.c - code for handling pixmaps */
24 /* Remove pixmaps from the cache when they haven't been accessed for
25 * this period of time (seconds).
27 #define PIXMAP_PURGE_TIME 1200
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <errno.h>
33 #include <gtk/gtk.h>
34 #include "collection.h"
36 #include "fscache.h"
37 #include "support.h"
38 #include "gui_support.h"
39 #include "pixmaps.h"
41 static GFSCache *pixmap_cache = NULL;
43 static char * bad_xpm[] = {
44 "12 12 3 1",
45 " c #000000000000",
46 ". c #FFFF00000000",
47 "X c #FFFFFFFFFFFF",
48 " ",
49 " ..XXXXXX.. ",
50 " ...XXXX... ",
51 " X...XX...X ",
52 " XX......XX ",
53 " XXX....XXX ",
54 " XXX....XXX ",
55 " XX......XX ",
56 " X...XX...X ",
57 " ...XXXX... ",
58 " ..XXXXXX.. ",
59 " "};
61 MaskedPixmap default_pixmap[LAST_DEFAULT_PIXMAP];
63 /* Static prototypes */
65 static MaskedPixmap *load(char *pathname, gpointer data);
66 static void ref(MaskedPixmap *mp, gpointer data);
67 static void unref(MaskedPixmap *mp, gpointer data);
68 static gint purge(gpointer data);
71 /****************************************************************
72 * EXTERNAL INTERFACE *
73 ****************************************************************/
75 void pixmaps_init(void)
77 pixmap_cache = g_fscache_new((GFSLoadFunc) load,
78 (GFSFunc) ref,
79 (GFSFunc) unref,
80 NULL);
82 gtk_timeout_add(10000, purge, NULL);
85 /* Try to load the pixmap from the given path, allocate a MaskedPixmap
86 * structure for it and return a pointer to the structure. NULL on failure.
87 * Remember to pixmap_unref() the result afterwards.
89 MaskedPixmap *load_pixmap_from(GtkWidget *window, char *path)
91 MaskedPixmap *masked_pixmap;
93 pixmap_cache->user_data = window;
94 masked_pixmap = g_fscache_lookup(pixmap_cache, path);
95 pixmap_cache->user_data = NULL;
97 return masked_pixmap;
100 void load_pixmap(GdkWindow *window, char *name, MaskedPixmap *image)
102 image->pixmap = gdk_pixmap_create_from_xpm(window,
103 &image->mask,
105 make_path(getenv("APP_DIR"), name)->str);
107 if (!image->pixmap)
109 image->pixmap= gdk_pixmap_create_from_xpm_d(window,
110 &image->mask, NULL, bad_xpm);
113 image->ref = 1;
116 /* Load all the standard pixmaps */
117 void load_default_pixmaps(GdkWindow *window)
119 static gboolean loaded = FALSE;
121 if (loaded)
122 return;
124 load_pixmap(window, "pixmaps/error.xpm",
125 default_pixmap + TYPE_ERROR);
126 load_pixmap(window, "pixmaps/unknown.xpm",
127 default_pixmap + TYPE_UNKNOWN);
128 load_pixmap(window, "pixmaps/symlink.xpm",
129 default_pixmap + TYPE_SYMLINK);
130 load_pixmap(window, "pixmaps/file.xpm",
131 default_pixmap + TYPE_FILE);
132 load_pixmap(window, "pixmaps/directory.xpm",
133 default_pixmap + TYPE_DIRECTORY);
134 load_pixmap(window, "pixmaps/char.xpm",
135 default_pixmap + TYPE_CHAR_DEVICE);
136 load_pixmap(window, "pixmaps/block.xpm",
137 default_pixmap + TYPE_BLOCK_DEVICE);
138 load_pixmap(window, "pixmaps/pipe.xpm",
139 default_pixmap + TYPE_PIPE);
140 load_pixmap(window, "pixmaps/socket.xpm",
141 default_pixmap + TYPE_SOCKET);
143 load_pixmap(window, "pixmaps/mount.xpm",
144 default_pixmap + TYPE_UNMOUNTED);
145 load_pixmap(window, "pixmaps/mounted.xpm",
146 default_pixmap + TYPE_MOUNTED);
147 load_pixmap(window, "pixmaps/multiple.xpm",
148 default_pixmap + TYPE_MULTIPLE);
149 load_pixmap(window, "pixmaps/exec.xpm",
150 default_pixmap + TYPE_EXEC_FILE);
151 load_pixmap(window, "pixmaps/application.xpm",
152 default_pixmap + TYPE_APPDIR);
154 loaded = TRUE;
157 void pixmap_ref(MaskedPixmap *mp)
159 ref(mp, pixmap_cache->user_data);
162 void pixmap_unref(MaskedPixmap *mp)
164 unref(mp, pixmap_cache->user_data);
167 /****************************************************************
168 * INTERNAL FUNCTIONS *
169 ****************************************************************/
171 /* Try to load the pixmap from the given path, allocate a MaskedPixmap
172 * structure for it and return a pointer to the structure. NULL on failure.
174 static MaskedPixmap *load(char *pathname, gpointer user_data)
176 GtkWidget *window = (GtkWidget *) user_data;
177 GdkPixmap *pixmap;
178 GdkBitmap *mask;
179 GtkStyle *style;
180 MaskedPixmap *masked_pixmap;
182 style = gtk_widget_get_style(window);
184 pixmap = gdk_pixmap_create_from_xpm(window->window,
185 &mask,
186 &style->bg[GTK_STATE_NORMAL],
187 pathname);
188 if (!pixmap)
189 return NULL;
191 masked_pixmap = g_new(MaskedPixmap, 1);
192 masked_pixmap->pixmap = pixmap;
193 masked_pixmap->mask = mask;
194 masked_pixmap->ref = 1;
196 return masked_pixmap;
199 static void ref(MaskedPixmap *mp, gpointer data)
201 /* printf("[ ref %p %d->%d ]\n", mp, mp->ref, mp->ref + 1); */
203 if (mp)
205 gdk_pixmap_ref(mp->pixmap);
206 gdk_bitmap_ref(mp->mask);
207 mp->ref++;
211 static void unref(MaskedPixmap *mp, gpointer data)
213 /* printf("[ unref %p %d->%d ]\n", mp, mp->ref, mp->ref - 1); */
215 if (mp && --mp->ref == 0)
217 gdk_pixmap_unref(mp->pixmap);
218 gdk_bitmap_unref(mp->mask);
219 g_free(mp);
223 /* Called now and then to clear out old pixmaps */
224 static gint purge(gpointer data)
226 g_fscache_purge(pixmap_cache, PIXMAP_PURGE_TIME);
228 return TRUE;