mc/gnome/gicon.c

351 lines
7.4 KiB
C
Raw Normal View History

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;
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;
/* 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
*/
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;
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");
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 ||
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-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 *
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;
mode_t mode;
1998-12-06 02:19:57 +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 ();
mode = fe->buf.st_mode;
1998-12-06 02:19:57 +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){
{
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
*/
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;
/* BEtter effect; do not use the symlink icon */
#if 0
return icon_view_symlink;
#endif
}
/*
1998-12-12 03:55:54 +03:00
* 2. Expensive tests
1998-12-06 02:19:57 +03:00
*/
if (!do_quick || we_can_afford_the_speed) {
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.
*/
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);
g_free (buf);
1998-12-12 03:55:54 +03:00
if (image) {
g_free (full_name);
1998-12-12 03:55:54 +03:00
return image;
}
1998-12-12 03:55:54 +03:00
}
1998-12-12 03:55:54 +03:00
/*
* 2.2. Try to fetch the icon from the metadata.
*/
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);
g_free (buf);
1998-12-12 03:55:54 +03:00
if (image) {
g_free (full_name);
1998-12-12 03:55:54 +03:00
return image;
}
1998-12-12 03:55:54 +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
/*
* 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;
}
GdkImlibImage *
gicon_get_icon_for_file (char *directory, file_entry *fe)
{
return gicon_get_icon_for_file_speed (directory, fe, TRUE);
}
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;
} 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;
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);
}