1998-12-06 02:19:57 +03:00
|
|
|
/*
|
|
|
|
* Icon loading support for the Midnight Commander
|
|
|
|
*
|
|
|
|
* Author:
|
|
|
|
* Miguel de Icaza (miguel@gnu.org)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "dir.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "dialog.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <gnome.h>
|
|
|
|
#include "gicon.h"
|
|
|
|
|
|
|
|
static GHashTable *icon_hash;
|
|
|
|
static int gicon_inited = FALSE;
|
|
|
|
|
|
|
|
/* These are some default images used in the Icon View */
|
|
|
|
static GdkImlibImage *icon_view_directory;
|
1998-12-11 04:57:01 +03:00
|
|
|
static GdkImlibImage *icon_view_dirclosed;
|
1998-12-06 02:19:57 +03:00
|
|
|
static GdkImlibImage *icon_view_executable;
|
|
|
|
static GdkImlibImage *icon_view_symlink;
|
|
|
|
static GdkImlibImage *icon_view_regular;
|
|
|
|
static GdkImlibImage *icon_view_core;
|
|
|
|
static GdkImlibImage *icon_view_sock;
|
|
|
|
static GdkImlibImage *icon_view_char_dev;
|
|
|
|
static GdkImlibImage *icon_view_block_dev;
|
|
|
|
static GdkImlibImage *icon_view_stalled;
|
|
|
|
|
1998-12-11 04:57:01 +03:00
|
|
|
/* Our UID and GID */
|
|
|
|
static uid_t our_uid;
|
|
|
|
static gid_t our_gid;
|
|
|
|
|
1998-12-12 03:55:54 +03:00
|
|
|
/*
|
|
|
|
* If true, we choose the icon in a way that might be a bit slow
|
|
|
|
*/
|
1999-01-28 08:48:02 +03:00
|
|
|
int we_can_afford_the_speed = 0;
|
1998-12-12 03:55:54 +03:00
|
|
|
|
1998-12-06 02:19:57 +03:00
|
|
|
/**
|
|
|
|
* gicon_init:
|
|
|
|
*
|
|
|
|
* Initializes the hash tables for the icons used in the IconList
|
|
|
|
* view
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
gicon_init (void)
|
|
|
|
{
|
|
|
|
g_assert (gicon_inited == FALSE);
|
|
|
|
|
|
|
|
icon_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
gicon_inited = TRUE;
|
|
|
|
|
1998-12-11 04:57:01 +03:00
|
|
|
our_uid = getuid ();
|
|
|
|
our_gid = getgid ();
|
|
|
|
|
1998-12-06 02:19:57 +03:00
|
|
|
/* Recursive call to load the stock images */
|
|
|
|
icon_view_directory = gicon_stock_load ("i-directory.png");
|
1998-12-11 04:57:01 +03:00
|
|
|
icon_view_dirclosed = gicon_stock_load ("i-dirclosed.png");
|
1998-12-06 02:19:57 +03:00
|
|
|
icon_view_executable = gicon_stock_load ("i-executable.png");
|
|
|
|
icon_view_symlink = gicon_stock_load ("i-symlink.png");
|
|
|
|
icon_view_regular = gicon_stock_load ("i-regular.png");
|
|
|
|
icon_view_core = gicon_stock_load ("i-core.png");
|
|
|
|
icon_view_sock = gicon_stock_load ("i-sock.png");
|
|
|
|
icon_view_char_dev = gicon_stock_load ("i-chardev.png");
|
|
|
|
icon_view_block_dev = gicon_stock_load ("i-blockdev.png");
|
|
|
|
icon_view_stalled = gicon_stock_load ("i-stalled.png");
|
|
|
|
|
|
|
|
if (icon_view_directory == NULL ||
|
1998-12-11 04:57:01 +03:00
|
|
|
icon_view_dirclosed == NULL ||
|
1998-12-06 02:19:57 +03:00
|
|
|
icon_view_executable == NULL ||
|
|
|
|
icon_view_symlink == NULL ||
|
|
|
|
icon_view_regular == NULL ||
|
|
|
|
icon_view_core == NULL ||
|
|
|
|
icon_view_sock == NULL ||
|
|
|
|
icon_view_char_dev == NULL ||
|
|
|
|
icon_view_block_dev == NULL ||
|
|
|
|
icon_view_stalled == NULL){
|
|
|
|
message (1, _("Error"), _("Default set of icons not found, check your installation"));
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gicon_get_by_filename:
|
|
|
|
*
|
|
|
|
* Fetches an icon given an absolute pathname
|
|
|
|
*/
|
|
|
|
GdkImlibImage *
|
|
|
|
gicon_get_by_filename (char *fname)
|
|
|
|
{
|
|
|
|
GdkImlibImage *icon;
|
|
|
|
|
|
|
|
g_return_val_if_fail (fname != NULL, NULL);
|
|
|
|
|
|
|
|
if (!gicon_inited)
|
|
|
|
gicon_init ();
|
|
|
|
|
|
|
|
icon = g_hash_table_lookup (icon_hash, fname);
|
|
|
|
|
|
|
|
if (icon)
|
|
|
|
return icon;
|
|
|
|
|
|
|
|
icon = gdk_imlib_load_image (fname);
|
|
|
|
|
|
|
|
if (icon)
|
|
|
|
g_hash_table_insert (icon_hash, g_strdup (fname), icon);
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gicon_stock_load:
|
|
|
|
*
|
|
|
|
* Loads an icon from the Midnight Commander installation directory
|
|
|
|
*/
|
|
|
|
GdkImlibImage *
|
|
|
|
gicon_stock_load (char *basename)
|
|
|
|
{
|
|
|
|
GdkImlibImage *im;
|
|
|
|
char *fullname;
|
|
|
|
|
|
|
|
g_return_val_if_fail (basename != NULL, NULL);
|
|
|
|
|
|
|
|
fullname = concat_dir_and_file (ICONDIR, basename);
|
|
|
|
im = gicon_get_by_filename (fullname);
|
|
|
|
g_free (fullname);
|
|
|
|
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gnome_file_entry_color:
|
|
|
|
*
|
|
|
|
* Returns an Imlib image appropiate for use in the icon list
|
|
|
|
* based on the file_entry stat field and the filename. This
|
|
|
|
* routine always succeeds.x
|
|
|
|
*/
|
|
|
|
static GdkImlibImage *
|
|
|
|
gnome_file_entry_color (file_entry *fe)
|
|
|
|
{
|
|
|
|
mode_t mode = fe->buf.st_mode;
|
1998-12-11 04:57:01 +03:00
|
|
|
|
1998-12-06 02:19:57 +03:00
|
|
|
if (S_ISSOCK (mode))
|
|
|
|
return icon_view_sock;
|
|
|
|
|
|
|
|
if (S_ISCHR (mode))
|
|
|
|
return icon_view_char_dev;
|
|
|
|
|
|
|
|
if (S_ISBLK (mode))
|
|
|
|
return icon_view_block_dev;
|
|
|
|
|
|
|
|
if (S_ISFIFO (mode))
|
|
|
|
return icon_view_sock;
|
|
|
|
|
|
|
|
if (is_exe (mode))
|
|
|
|
return icon_view_executable;
|
|
|
|
|
|
|
|
if (fe->fname && (!strcmp (fe->fname, "core") || !strcmp (extension (fe->fname), "core")))
|
|
|
|
return icon_view_core;
|
|
|
|
|
|
|
|
return icon_view_regular;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gicon_get_icon_for_file:
|
|
|
|
*
|
|
|
|
* Given a filename and its stat information, we return the optimal
|
|
|
|
* icon for it. Including a lookup in the metadata.
|
|
|
|
*/
|
|
|
|
GdkImlibImage *
|
1999-01-20 13:40:21 +03:00
|
|
|
gicon_get_icon_for_file_speed (char *directory, file_entry *fe, gboolean do_quick)
|
1998-12-06 02:19:57 +03:00
|
|
|
{
|
|
|
|
GdkImlibImage *image;
|
|
|
|
int size;
|
1998-12-12 03:55:54 +03:00
|
|
|
char *buf, *mime_type;
|
1998-12-11 05:58:48 +03:00
|
|
|
mode_t mode;
|
1998-12-06 02:19:57 +03:00
|
|
|
|
1999-01-20 13:40:21 +03:00
|
|
|
g_return_val_if_fail (directory != NULL, NULL);
|
1998-12-06 02:19:57 +03:00
|
|
|
g_return_val_if_fail (fe != NULL, NULL);
|
|
|
|
|
|
|
|
if (!gicon_inited)
|
|
|
|
gicon_init ();
|
1998-12-11 05:58:48 +03:00
|
|
|
|
|
|
|
mode = fe->buf.st_mode;
|
1998-12-06 02:19:57 +03:00
|
|
|
|
|
|
|
/*
|
1998-12-11 05:58:48 +03:00
|
|
|
* 1. First test for it being a directory or a link to a directory.
|
|
|
|
*/
|
|
|
|
if (S_ISDIR (mode)){
|
|
|
|
if (fe->buf.st_uid != our_uid){
|
1999-01-21 06:44:03 +03:00
|
|
|
{
|
|
|
|
static int reported;
|
|
|
|
|
|
|
|
if (!reported){
|
|
|
|
g_warning ("Getgroups should be used here\n");
|
|
|
|
reported = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME:
|
|
|
|
* Use getgroups to fetch the list of groups
|
|
|
|
* to which I belong and test against those
|
|
|
|
*/
|
1998-12-11 05:58:48 +03:00
|
|
|
if (fe->buf.st_gid != our_gid){
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We do not share the UID or the GID,
|
|
|
|
* test for read/execute permissions
|
|
|
|
*/
|
|
|
|
if ((mode & (S_IROTH | S_IXOTH)) != (S_IROTH | S_IXOTH))
|
|
|
|
return icon_view_dirclosed;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Same group, check if we have permissions
|
|
|
|
*/
|
|
|
|
if ((mode & (S_IRGRP | S_IXGRP)) != (S_IRGRP | S_IXGRP))
|
|
|
|
return icon_view_dirclosed;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((mode & (S_IRUSR | S_IXUSR)) != (S_IRUSR | S_IXUSR))
|
|
|
|
return icon_view_dirclosed;
|
|
|
|
}
|
|
|
|
|
|
|
|
return icon_view_directory;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (S_ISLNK (mode)){
|
|
|
|
if (fe->f.link_to_dir)
|
|
|
|
return icon_view_directory;
|
|
|
|
|
|
|
|
if (fe->f.stalled_link)
|
|
|
|
return icon_view_stalled;
|
|
|
|
|
1999-01-06 07:03:15 +03:00
|
|
|
/* BEtter effect; do not use the symlink icon */
|
|
|
|
#if 0
|
1998-12-11 05:58:48 +03:00
|
|
|
return icon_view_symlink;
|
1999-01-06 07:03:15 +03:00
|
|
|
#endif
|
1998-12-11 05:58:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1998-12-12 03:55:54 +03:00
|
|
|
* 2. Expensive tests
|
1998-12-06 02:19:57 +03:00
|
|
|
*/
|
1999-01-28 08:48:02 +03:00
|
|
|
if (!do_quick || we_can_afford_the_speed) {
|
1999-01-20 13:40:21 +03:00
|
|
|
char *full_name;
|
|
|
|
|
|
|
|
full_name = g_concat_dir_and_file (directory, fe->fname);
|
|
|
|
|
1998-12-12 03:55:54 +03:00
|
|
|
/*
|
|
|
|
* 2.1 Try to fetch the icon as an inline png from the metadata.
|
|
|
|
*/
|
1999-01-20 13:40:21 +03:00
|
|
|
if (gnome_metadata_get (full_name, "icon-inline-png", &size, &buf) == 0){
|
1998-12-12 03:55:54 +03:00
|
|
|
image = gdk_imlib_inlined_png_to_image (buf, size);
|
|
|
|
|
1999-01-06 07:03:15 +03:00
|
|
|
g_free (buf);
|
1998-12-12 03:55:54 +03:00
|
|
|
|
1999-01-20 13:40:21 +03:00
|
|
|
if (image) {
|
|
|
|
g_free (full_name);
|
1998-12-12 03:55:54 +03:00
|
|
|
return image;
|
1999-01-20 13:40:21 +03:00
|
|
|
}
|
1998-12-12 03:55:54 +03:00
|
|
|
}
|
1998-12-11 20:58:43 +03:00
|
|
|
|
1998-12-12 03:55:54 +03:00
|
|
|
/*
|
|
|
|
* 2.2. Try to fetch the icon from the metadata.
|
|
|
|
*/
|
1999-01-20 13:40:21 +03:00
|
|
|
if (gnome_metadata_get (full_name, "icon-filename", &size, &buf) == 0){
|
1998-12-12 03:55:54 +03:00
|
|
|
image = gicon_get_by_filename (buf);
|
1998-12-17 07:51:24 +03:00
|
|
|
|
1999-01-06 07:03:15 +03:00
|
|
|
g_free (buf);
|
1998-12-12 03:55:54 +03:00
|
|
|
|
1999-01-20 13:40:21 +03:00
|
|
|
if (image) {
|
|
|
|
g_free (full_name);
|
1998-12-12 03:55:54 +03:00
|
|
|
return image;
|
1999-01-20 13:40:21 +03:00
|
|
|
}
|
1998-12-12 03:55:54 +03:00
|
|
|
}
|
1999-01-20 13:40:21 +03:00
|
|
|
|
|
|
|
g_free (full_name);
|
1998-12-06 02:19:57 +03:00
|
|
|
}
|
1998-12-12 03:55:54 +03:00
|
|
|
|
1998-12-06 02:19:57 +03:00
|
|
|
/*
|
1998-12-12 03:55:54 +03:00
|
|
|
* 3. Mime-type based
|
1998-12-06 02:19:57 +03:00
|
|
|
*/
|
1998-12-12 03:55:54 +03:00
|
|
|
mime_type = gnome_mime_type_or_default (fe->fname, NULL);
|
|
|
|
if (mime_type){
|
|
|
|
char *icon;
|
1998-12-06 02:19:57 +03:00
|
|
|
|
1998-12-15 22:53:55 +03:00
|
|
|
icon = gnome_mime_get_value (mime_type, "icon-filename");
|
1998-12-06 02:19:57 +03:00
|
|
|
|
1998-12-12 03:55:54 +03:00
|
|
|
if (icon){
|
|
|
|
image = gicon_get_by_filename (icon);
|
|
|
|
|
|
|
|
if (image)
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-12-06 02:19:57 +03:00
|
|
|
/*
|
1998-12-11 05:58:48 +03:00
|
|
|
* 4. Try to find an appropiate icon from the stat information or
|
1998-12-06 02:19:57 +03:00
|
|
|
* the hard coded filename.
|
|
|
|
*/
|
|
|
|
image = gnome_file_entry_color (fe);
|
1998-12-12 03:55:54 +03:00
|
|
|
|
1998-12-06 02:19:57 +03:00
|
|
|
g_assert (image != NULL);
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
1998-12-17 07:51:24 +03:00
|
|
|
|
|
|
|
GdkImlibImage *
|
1999-01-20 13:40:21 +03:00
|
|
|
gicon_get_icon_for_file (char *directory, file_entry *fe)
|
1998-12-17 07:51:24 +03:00
|
|
|
{
|
1999-01-20 13:40:21 +03:00
|
|
|
return gicon_get_icon_for_file_speed (directory, fe, TRUE);
|
1998-12-17 07:51:24 +03:00
|
|
|
}
|
1999-01-18 23:07:27 +03:00
|
|
|
|
1999-01-19 01:37:39 +03:00
|
|
|
typedef struct {
|
1999-01-18 23:07:27 +03:00
|
|
|
char *name;
|
|
|
|
void *image;
|
1999-01-19 00:25:55 +03:00
|
|
|
} lookup_name_closure_t;
|
1999-01-18 23:07:27 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
search_image (gpointer key, gpointer value, gpointer user_data)
|
|
|
|
{
|
|
|
|
lookup_name_closure_t *closure = user_data;
|
|
|
|
|
|
|
|
if (value == closure->image)
|
|
|
|
closure->name = key;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the file name that maps to this given GdkImlibImage
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
gicon_image_to_name (GdkImlibImage *image)
|
|
|
|
{
|
|
|
|
lookup_name_closure_t closure;
|
|
|
|
|
|
|
|
closure.image = image;
|
|
|
|
closure.name = NULL;
|
|
|
|
|
1999-01-19 00:25:55 +03:00
|
|
|
g_hash_table_foreach (icon_hash, &search_image, &closure);
|
1999-01-18 23:07:27 +03:00
|
|
|
if (closure.name == NULL)
|
|
|
|
return g_strdup (ICONDIR "i-regular.png");
|
|
|
|
|
|
|
|
return g_strdup (closure.name);
|
|
|
|
}
|