mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-23 12:56:51 +03:00
285 lines
6.1 KiB
C
285 lines
6.1 KiB
C
/*
|
|
* 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;
|
|
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;
|
|
|
|
/*
|
|
* If true, we choose the icon in a way that might be a bit slow
|
|
*/
|
|
static int we_can_affort_the_speed = 1;
|
|
|
|
/**
|
|
* 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 ();
|
|
|
|
/* 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");
|
|
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 ||
|
|
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;
|
|
|
|
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 (file_entry *fe)
|
|
{
|
|
GdkImlibImage *image;
|
|
int size;
|
|
char *buf, *mime_type;
|
|
mode_t mode;
|
|
|
|
g_return_val_if_fail (fe != NULL, NULL);
|
|
|
|
if (!gicon_inited)
|
|
gicon_init ();
|
|
|
|
mode = fe->buf.st_mode;
|
|
|
|
/*
|
|
* 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){
|
|
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;
|
|
|
|
return icon_view_symlink;
|
|
}
|
|
|
|
/*
|
|
* 2. Expensive tests
|
|
*/
|
|
if (we_can_affort_the_speed){
|
|
/*
|
|
* 2.1 Try to fetch the icon as an inline png from the metadata.
|
|
*/
|
|
if (gnome_metadata_get (fe->fname, "icon-inline-png", &size, &buf) == 0){
|
|
image = gdk_imlib_inlined_png_to_image (buf, size);
|
|
|
|
free (buf);
|
|
|
|
if (image)
|
|
return image;
|
|
}
|
|
|
|
/*
|
|
* 2.2. Try to fetch the icon from the metadata.
|
|
*/
|
|
if (gnome_metadata_get (fe->fname, "icon-filename", &size, &buf) == 0){
|
|
image = gicon_get_by_filename (buf);
|
|
|
|
free (buf);
|
|
|
|
if (image)
|
|
return image;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 3. Mime-type based
|
|
*/
|
|
mime_type = gnome_mime_type_or_default (fe->fname, NULL);
|
|
if (mime_type){
|
|
char *icon;
|
|
|
|
icon = gnome_mime_get_value (mime_type, "icon-filename");
|
|
|
|
if (icon){
|
|
image = gicon_get_by_filename (icon);
|
|
|
|
if (image)
|
|
return image;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 4. Try to find an appropiate icon from the stat information or
|
|
* the hard coded filename.
|
|
*/
|
|
image = gnome_file_entry_color (fe);
|
|
|
|
g_assert (image != NULL);
|
|
|
|
return image;
|
|
}
|