diff -uNr rox-2.1.4/ROX-Filer/src/diritem.c rox-2.1.4-r1/ROX-Filer/src/diritem.c --- rox-2.1.4/ROX-Filer/src/diritem.c 2004-09-21 16:44:32.000000000 +0000 +++ rox-2.1.4-r1/ROX-Filer/src/diritem.c 2004-11-02 14:42:35.000000000 +0000 @@ -264,7 +264,8 @@ { struct stat info; static GString *tmp = NULL; - + MaskedPixmap *orig_image; + if (!tmp) tmp = g_string_new(NULL); @@ -282,12 +283,15 @@ * - If it contains an AppRun then it's an application * - If it contains an AppRun but no .DirIcon then try to * use AppIcon.xpm as the icon. + * - If it contains a .DirEmblem then combine it + * - with current directory's icon * * .DirIcon and AppRun must have the same owner as the * directory itself, to prevent abuse of /tmp, etc. * For symlinks, we want the symlink's owner. */ + orig_image = item->_image; g_string_printf(tmp, "%s/.DirIcon", path); if (item->_image) @@ -312,17 +316,17 @@ g_string_append(tmp, "AppRun"); if (mc_lstat(tmp->str, &info) != 0 || info.st_uid != uid) - goto out; /* Missing, or wrong owner */ + goto no_appicon; /* Missing, or wrong owner */ if (!(info.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - goto out; /* Not executable */ + goto no_appicon; /* Not executable */ item->flags |= ITEM_FLAG_APPDIR; /* Try to load AppIcon.xpm... */ if (item->_image) - goto out; /* Already got an icon */ + goto no_appicon; /* Already got an icon */ g_string_truncate(tmp, tmp->len - 3); g_string_append(tmp, "Icon.xpm"); @@ -332,15 +336,15 @@ */ if (mc_stat(tmp->str, &info) != 0) - goto out; /* Missing, or broken symlink */ + goto no_appicon; /* Missing, or broken symlink */ if (info.st_size > MAX_ICON_SIZE || !S_ISREG(info.st_mode)) - goto out; /* Too big, or non-regular file */ + goto no_appicon; /* Too big, or non-regular file */ /* Try to load image; may still get NULL... */ item->_image = g_fscache_lookup(pixmap_cache, tmp->str); -out: +no_appicon: if ((item->flags & ITEM_FLAG_APPDIR) && !item->_image) { @@ -348,4 +352,28 @@ item->_image = im_appdir; g_object_ref(item->_image); } + + /* Check for .DirEmblem */ + g_string_printf(tmp, "%s/.DirEmblem", path); + if (mc_lstat(tmp->str, &info) != 0 || info.st_uid != uid) + goto out; /* Missing, or wrong owner */ + + if (S_ISLNK(info.st_mode) && mc_stat(tmp->str, &info) != 0) + goto out; /* Bad symlink */ + + if (info.st_size > MAX_ICON_SIZE || !S_ISREG(info.st_mode)) + goto out; /* Too big, or non-regular file */ + + if (!item->_image || item->_image != orig_image) { + MaskedPixmap *im_base, *im_emblem; + + im_base = item->_image ? item->_image : type_to_icon(inode_directory); + im_emblem = g_fscache_lookup(pixmap_cache, tmp->str); + item->_image = pixmap_combine(im_base, im_emblem); + g_object_unref(im_base); + g_object_unref(im_emblem); + } + + out: + return; } diff -uNr rox-2.1.4/ROX-Filer/src/pixmaps.c rox-2.1.4-r1/ROX-Filer/src/pixmaps.c --- rox-2.1.4/ROX-Filer/src/pixmaps.c 2004-09-01 15:06:05.000000000 +0000 +++ rox-2.1.4-r1/ROX-Filer/src/pixmaps.c 2004-11-02 14:37:34.000000000 +0000 @@ -1015,3 +1015,53 @@ return g_list_append(NULL, align); } + + + +MaskedPixmap * +pixmap_combine(MaskedPixmap *im_base, MaskedPixmap *im_emblem) +{ + GdkPixbuf *res; + int dx, dy; + double offset_x, offset_y, scale_x, scale_y, ew, eh, tmp, dw, dh; + MaskedPixmap *image; + + g_return_val_if_fail(im_base != NULL, NULL); + + if (!im_emblem) { + g_object_ref(im_base); + return im_base; + } + res = gdk_pixbuf_copy(im_base->src_pixbuf); + dx = (float) gdk_pixbuf_get_width(res) * EMBLEM_SHIFT_X; + dy = (float) gdk_pixbuf_get_height(res) * EMBLEM_SHIFT_Y; + dw = gdk_pixbuf_get_width(res) - dx; + dh = gdk_pixbuf_get_height(res) - dy; + offset_x = dx; + offset_y = dy; + ew = gdk_pixbuf_get_width(im_emblem->src_pixbuf); + eh = gdk_pixbuf_get_height(im_emblem->src_pixbuf); + scale_x = (float) dw / ew; + scale_y = (float) dh / eh; + if (scale_x < scale_y) { + tmp = eh * scale_x; + dy += (dh - tmp) / 2; + dh = tmp; + } else { + scale_x = scale_y; + tmp = ew * scale_x; + dx += (dw - tmp) / 2; + dw = tmp; + } + gdk_pixbuf_composite(im_emblem->src_pixbuf, res, + dx, dy, + dw, dh, + //offset_x, offset_y, + dx, dy, + scale_x, scale_x, + GDK_INTERP_HYPER, 255); + + image = masked_pixmap_new(res); + g_object_unref(res); + return image; +} diff -uNr rox-2.1.4/ROX-Filer/src/pixmaps.h rox-2.1.4-r1/ROX-Filer/src/pixmaps.h --- rox-2.1.4/ROX-Filer/src/pixmaps.h 2003-03-23 14:32:30.000000000 +0000 +++ rox-2.1.4-r1/ROX-Filer/src/pixmaps.h 2004-11-02 14:38:11.000000000 +0000 @@ -31,6 +31,10 @@ #define SMALL_HEIGHT 18 #define SMALL_WIDTH 22 +#define EMBLEM_SHIFT_X 0.3 +#define EMBLEM_SHIFT_Y 0.3 + + typedef struct _MaskedPixmapClass MaskedPixmapClass; struct _MaskedPixmapClass { @@ -73,5 +77,6 @@ void pixmap_background_thumb(const gchar *path, GFunc callback, gpointer data); MaskedPixmap *masked_pixmap_new(GdkPixbuf *full_size); GdkPixbuf *scale_pixbuf(GdkPixbuf *src, int max_w, int max_h); - +MaskedPixmap *pixmap_combine(MaskedPixmap *im_base, MaskedPixmap *im_emblem); + #endif /* _PIXMAP_H */