Added efreet_mime_type_icon_get which will retrieve a mimetype icon. This follows the loose specification described in the fdo icon spec. Also added efreet_icon_list_find which will search for a list of icons in a theme before falling back to inherited themes. Also made a slight modification to the fallback detection for efreet_mime. Tabs will no longer trigger the return of application/octet-stream.

SVN revision: 30875
This commit is contained in:
Nicholas Hughart 2007-07-17 19:21:20 +00:00
parent be190f1117
commit 0a4d1e3605
4 changed files with 386 additions and 62 deletions

View File

@ -34,6 +34,9 @@ const char *efreet_mime_magic_type_get(const char *file);
const char *efreet_mime_globs_type_get(const char *file);
const char *efreet_mime_special_type_get(const char *file);
const char *efreet_mime_fallback_type_get(const char *file);
const char *efreet_mime_type_icon_get(const char *mime, const char *theme,
const char *size);
/**
* @}

View File

@ -11,10 +11,26 @@ static Ecore_Hash *efreet_icon_themes = NULL;
Ecore_List *efreet_icon_extensions = NULL;
static Ecore_List *efreet_extra_icon_dirs = NULL;
static char *efreet_icon_remove_extension(const char *icon);
static Efreet_Icon_Theme *efreet_icon_find_theme_check(const char *theme_name);
static Efreet_Icon *efreet_icon_find_fallback(Efreet_Icon_Theme *theme,
const char *cache_key,
const char *icon,
const char *size);
static Efreet_Icon *efreet_icon_list_find_fallback(Efreet_Icon_Theme *theme,
Ecore_List *cache_keys,
Ecore_List *icons,
const char *size);
static Efreet_Icon *efreet_icon_find_helper(Efreet_Icon_Theme *theme,
const char *cache_key,
const char *icon,
const char *size);
static Efreet_Icon *efreet_icon_list_find_helper(Efreet_Icon_Theme *theme,
Ecore_List *cache_keys,
Ecore_List *icons,
const char *size);
static Efreet_Icon *efreet_icon_lookup_icon(Efreet_Icon_Theme *theme,
const char *icon_name,
const char *size);
@ -237,6 +253,63 @@ efreet_icon_theme_find(const char *theme_name)
return theme;
}
/**
* @internal
* @param icon: The icon name to strip extension
* @return Extension removed if in list of extensions, else untouched.
* @brief Removes extension from icon name if in list of extensions.
*/
static char *
efreet_icon_remove_extension(const char *icon)
{
char *tmp = NULL, *ext = NULL;
tmp = strdup(icon);
ext = strrchr(tmp, '.');
if (ext)
{
const char *ext2;
ecore_list_goto_first(efreet_icon_extensions);
while ((ext2 = ecore_list_next(efreet_icon_extensions)))
{
if (!strcmp(ext, ext2))
{
#ifdef STRICT_SPEC
printf("[Efreet]: Requesting an icon with an extension: %s\n",
icon);
#endif
*ext = '\0';
break;
}
}
}
return tmp;
}
/**
* @internal
* @param theme_name: The icon theme to look for
* @return Returns the Efreet_Icon_Theme structure representing this theme
* or a new blank theme if not found
* @brief Retrieves a theme, or creates a blank one if not found.
*/
static Efreet_Icon_Theme *
efreet_icon_find_theme_check(const char *theme_name)
{
Efreet_Icon_Theme *theme = NULL;
theme = efreet_icon_theme_find(theme_name);
if (!theme)
{
theme = efreet_icon_theme_new();
theme->fake = 1;
theme->name.internal = ecore_string_instance(theme_name);
ecore_hash_set(efreet_icon_themes, (void *)theme->name.internal, theme);
}
return theme;
}
/**
* @param theme_name: The icon theme to look for
* @param icon: The icon to look for
@ -254,50 +327,26 @@ efreet_icon_find(const char *theme_name, const char *icon, const char *size)
Efreet_Icon_Theme *theme;
const char *key_list[] = { icon, "@", size, NULL };
theme = efreet_icon_theme_find(theme_name);
if (!theme)
{
theme = efreet_icon_theme_new();
theme->fake = 1;
theme->name.internal = ecore_string_instance(theme_name);
ecore_hash_set(efreet_icon_themes, (void *)theme->name.internal, theme);
}
theme = efreet_icon_find_theme_check(theme_name);
efreet_array_cat(cache_key, sizeof(cache_key), key_list);
share_key = ecore_string_instance(cache_key);
#ifdef SLOPPY_SPEC
{
char *tmp, *ext;
tmp = strdup(icon);
ext = strrchr(tmp, '.');
if (ext)
{
const char *ext2;
ecore_list_goto_first(efreet_icon_extensions);
while ((ext2 = ecore_list_next(efreet_icon_extensions)))
{
if (!strcmp(ext, ext2))
{
#ifdef STRICT_SPEC
printf("[Efreet]: Requesting an icon with an extension: %s\n", icon);
#endif
*ext = '\0';
break;
}
}
}
char *tmp;
tmp = efreet_icon_remove_extension(icon);
value = efreet_icon_find_helper(theme, share_key, tmp, size);
free(tmp);
FREE(tmp);
}
#else
value = efreet_icon_find_helper(theme, share_key, icon, size);
#endif
/* we didn't find the icon in the theme or in the inherited directories
* then just look for a non theme icon */
* then just look for a non theme icon
*/
if (!value) value = efreet_icon_fallback_icon(icon);
efreet_icon_cache_set(theme, share_key, value);
@ -308,6 +357,80 @@ efreet_icon_find(const char *theme_name, const char *icon, const char *size)
return value;
}
/**
* @param theme_name: The icon theme to look for
* @param icon: List of icons to look for
* @param size; The icon size to look for
* @return Returns the Efreet_Icon structure representing first found icon or
* NULL if none of the icons are found
* @brief Retrieves all of the information about the first found icon in
* the list.
* @note This function will search the given theme for all icons before falling
* back. This is useful when searching for mimetype icons.
*/
Efreet_Icon *
efreet_icon_list_find(const char *theme_name, Ecore_List *icons,
const char *size)
{
Ecore_List *share_keys;
char cache_key[PATH_MAX];
const char *icon = NULL;
const char *share_key = NULL;
Efreet_Icon *value = NULL;
Efreet_Icon_Theme *theme;
theme = efreet_icon_find_theme_check(theme_name);
share_keys = ecore_list_new();
ecore_list_set_free_cb(share_keys,free);
ecore_list_goto_first(icons);
while ((icon = ecore_list_next(icons)))
{
snprintf(cache_key, sizeof(cache_key),"%s@%s", icon, size);
ecore_list_append(share_keys, strdup(cache_key));
}
#ifdef SLOPPY_SPEC
{
Ecore_List *tmps = NULL;
tmps = ecore_list_new();
ecore_list_set_free_cb(tmps, free);
ecore_list_goto_first(icons);
while ((icon = ecore_list_next(icons)))
ecore_list_append(tmps, efreet_icon_remove_extension(icon));
value = efreet_icon_list_find_helper(theme, share_keys, tmps, size);
ecore_list_destroy(tmps);
}
#else
value = efreet_icon_list_find_helper(theme, share_keys, icons, size);
#endif
/* we didn't find the icons in the theme or in the inherited directories
* then just look for a non theme icon
*/
if(!value)
{
ecore_list_goto_first(icons);
while ((icon = ecore_list_next(icons)))
{
if ((value = efreet_icon_fallback_icon(icon)))
break;
}
}
ecore_list_goto_first(share_keys);
while ((share_key = ecore_list_next(share_keys)))
efreet_icon_cache_set(theme, ecore_string_instance(share_key), value);
ecore_list_destroy(share_keys);
if (value == (void *)NO_MATCH_KEY)
value = NULL;
return value;
}
/**
* @param theme: The icon theme to look for
* @param icon: The icon to look for
@ -325,6 +448,53 @@ efreet_icon_path_find(const char *theme, const char *icon, const char *size)
return (ico ? ico->path : NULL);
}
/**
* @internal
* @param theme: The theme to search in
* @param cache_key: The cache key to use (icon\@sizexsize ecore_string)
* @param icon: The icon to search for
* @param size: The size to search for
* @return Returns the icon matching the given information or NULL if no
* icon found
* @brief Scans inheriting themes for the given icon
*/
static Efreet_Icon *
efreet_icon_find_fallback(Efreet_Icon_Theme *theme, const char *cache_key,
const char *icon, const char *size)
{
char *parent = NULL;
Efreet_Icon *value = NULL;
if (theme->inherits)
{
ecore_list_goto_first(theme->inherits);
while ((parent = ecore_list_next(theme->inherits)))
{
Efreet_Icon_Theme *parent_theme;
parent_theme = efreet_icon_theme_find(parent);
if ((!parent_theme) || (parent_theme == theme)) continue;
value = efreet_icon_find_helper(parent_theme, cache_key,
icon, size);
if (value) break;
}
}
/* if this isn't the hicolor theme, and we have no other fallbacks
* check hicolor */
else if (strcmp(theme->name.internal, "hicolor"))
{
Efreet_Icon_Theme *parent_theme;
parent_theme = efreet_icon_theme_find("hicolor");
if (parent_theme)
value = efreet_icon_find_helper(parent_theme, cache_key,
icon, size);
}
return value;
}
/**
* @internal
* @param theme: The theme to search in
@ -341,7 +511,7 @@ efreet_icon_find_helper(Efreet_Icon_Theme *theme, const char *cache_key,
const char *size)
{
Efreet_Icon *value;
static int recurse = 0;
static int recurse = 0;
efreet_icon_theme_cache_check(theme);
@ -360,36 +530,108 @@ efreet_icon_find_helper(Efreet_Icon_Theme *theme, const char *cache_key,
/* we didin't find the image check the inherited themes */
if (!value)
value = efreet_icon_find_fallback(theme, cache_key, icon, size);
recurse--;
return value;
}
/**
* @internal
* @param theme: The theme to search in
* @param cache_keys: The cache keys to use (icon\@sizexsize ecore_string)
* @param icons: The icons to search for
* @param size: The size to search for
* @return Returns the icon matching the given information or NULL if no
* icon found
* @brief Scans inheriting themes for the given icons
*/
static Efreet_Icon *
efreet_icon_list_find_fallback(Efreet_Icon_Theme *theme, Ecore_List *cache_keys,
Ecore_List *icons, const char *size)
{
char *parent = NULL;
Efreet_Icon *value = NULL;
if (theme->inherits)
{
char *parent;
if (theme->inherits)
{
ecore_list_goto_first(theme->inherits);
while ((parent = ecore_list_next(theme->inherits)))
{
Efreet_Icon_Theme *parent_theme;
parent_theme = efreet_icon_theme_find(parent);
if ((!parent_theme) || (parent_theme == theme)) continue;
value = efreet_icon_find_helper(parent_theme, cache_key,
icon, size);
if (value) break;
}
}
/* if this isn't the hicolor theme, and we have no other fallbacks
* check hicolor */
else if (strcmp(theme->name.internal, "hicolor"))
ecore_list_goto_first(theme->inherits);
while ((parent = ecore_list_next(theme->inherits)))
{
Efreet_Icon_Theme *parent_theme;
parent_theme = efreet_icon_theme_find("hicolor");
if (parent_theme)
value = efreet_icon_find_helper(parent_theme, cache_key,
icon, size);
parent_theme = efreet_icon_theme_find(parent);
if ((!parent_theme) || (parent_theme == theme)) continue;
value = efreet_icon_list_find_helper(parent_theme, cache_keys,
icons, size);
if (value) break;
}
}
/* if this isn't the hicolor theme, and we have no other fallbacks
* check hicolor
*/
else if (strcmp(theme->name.internal, "hicolor"))
{
Efreet_Icon_Theme *parent_theme;
parent_theme = efreet_icon_theme_find("hicolor");
if (parent_theme)
value = efreet_icon_list_find_helper(parent_theme, cache_keys,
icons, size);
}
return value;
}
/**
* @internal
* @param theme: The theme to search in
* @param cache_keys: The cache keys to use (icon\@sizexsize ecore_string)
* @param icons: The icons to search for
* @param size: The size to search for
* @return Returns the icon matching the given information or NULL if no
* icon found
* @brief Scans the theme and any inheriting themes for the given icons
*/
static Efreet_Icon *
efreet_icon_list_find_helper(Efreet_Icon_Theme *theme, Ecore_List *cache_keys,
Ecore_List *icons,
const char *size)
{
Efreet_Icon *value = NULL;
const char *icon = NULL;
const char *cache_key = NULL;
static int recurse = 0;
efreet_icon_theme_cache_check(theme);
/* see if this is in the cache already */
ecore_list_goto_first(cache_keys);
while ((cache_key = ecore_list_next(cache_keys)))
{
if ((value = efreet_icon_cache_get(theme, cache_key)))
return value;
}
/* go no further if this theme is fake */
if (theme->fake || !theme->valid) return NULL;
/* limit recursion in finding themes and inherited themes to 256 levels */
if (recurse > 256) return NULL;
recurse++;
ecore_list_goto_first(icons);
while ((icon = ecore_list_next(icons)))
{
if ((value = efreet_icon_lookup_icon(theme, icon, size)))
break;
}
/* we didn't find the image check the inherited themes */
if (!value)
value = efreet_icon_list_find_fallback(theme, cache_keys, icons, size);
recurse--;
return value;
@ -800,7 +1042,7 @@ efreet_icon_cache_set(Efreet_Icon_Theme *theme, const char *key, void *value)
/* XXX this is a bit inefficient as I'll end up adding back to the cache
* even if I found the item in the cache. Not a big deal at the moment
* tho. */
if (!value)
if (!value)
ecore_hash_set(theme->icon_cache, (void *)key, NO_MATCH_KEY);
else
{

View File

@ -167,7 +167,9 @@ Ecore_List *efreet_icon_theme_list_get(void);
Efreet_Icon_Theme *efreet_icon_theme_find(const char *theme_name);
Efreet_Icon *efreet_icon_find(const char *theme_name, const char *icon,
const char *size);
Efreet_Icon *efreet_icon_list_find(const char *theme_name,
Ecore_List *icons,
const char *size);
const char *efreet_icon_path_find(const char *theme, const char *icon,
const char *size);

View File

@ -109,6 +109,9 @@ efreet_mime_init(void)
if (!efreet_init())
return 0;
if (!efreet_icon_init())
return 0;
efreet_mime_endianess = efreet_mime_endian_check();
monitors = ecore_hash_new(ecore_str_hash, ecore_str_compare);
@ -133,13 +136,14 @@ efreet_mime_shutdown(void)
IF_FREE_LIST(magics);
IF_FREE_HASH(monitors);
efreet_icon_shutdown();
efreet_shutdown();
ecore_file_shutdown();
ecore_shutdown();
}
/**
* @param file: The file to check the mime type
* @param file: The file to find the mime type
* @return Returns mime type as a string
* @brief Retreive the mime type of a file
*/
@ -172,6 +176,76 @@ efreet_mime_type_get(const char *file)
return efreet_mime_fallback_check(file);
}
/**
* @param file: The file to find the mime type icon
* @return Returns mime type icon path as a string
* @brief Retreive the mime type icon for a file
*/
const char *
efreet_mime_type_icon_get(const char *mime, const char *theme, const char *size)
{
Efreet_Icon *icon = NULL;
Ecore_List *icons = NULL;
const char *env = NULL;
char *p = NULL, *pp = NULL, *ppp = NULL;
char buf[PATH_MAX];
if (!mime || !theme || !size)
return NULL;
icons = ecore_list_new();
ecore_list_set_free_cb(icons, free);
/* Standard icon name */
p = strdup(mime);
pp = p;
while (*pp)
{
if (*pp == '/')
*pp = '-';
pp++;
}
ecore_list_append(icons, p);
/* Environment Based icon names */
if ((env = efreet_desktop_environment_get()))
{
snprintf(buf, sizeof(buf), "%s-mime-%s", env, p);
ecore_list_append(icons, strdup(buf));
snprintf(buf, sizeof(buf), "%s-%s", env, p);
ecore_list_append(icons, strdup(buf));
}
/* Mime prefixed icon names */
snprintf(buf, sizeof(buf), "mime-%s", p);
ecore_list_append(icons, strdup(buf));
/* Generic icons */
pp = strdup(p);
while ((ppp = strrchr(pp, '-')))
{
*ppp = '\0';
snprintf(buf, sizeof(buf), "%s-generic", pp);
ecore_list_append(icons, strdup(buf));
snprintf(buf, sizeof(buf), "%s", pp);
ecore_list_append(icons, strdup(buf));
}
FREE(pp);
/* Search for icons using list */
icon = efreet_icon_list_find(theme, icons, size);
ecore_list_destroy(icons);
if (icon)
return icon->path;
return NULL;
}
/**
* @param file: The file to check the mime type
* @return Returns mime type as a string
@ -535,12 +609,15 @@ efreet_mime_fallback_check(const char *file)
return "application/octet-stream";
/*
* Check for ASCII control characters in the first 32 bytes.
* New lines and carriage returns are ignored as they are
* quite common in text files.
* Line Feeds, carriage returns, and tabs are ignored as they are
* quite common in text files in the first 32 chars.
*/
for (i -= 1; i >= 0; --i)
{
if ((buf[i] < 0x20) && (buf[i] != '\n') && (buf[i] != '\r'))
if ((buf[i] < 0x20) &&
(buf[i] != '\n') && /* Line Feed */
(buf[i] != '\r') && /* Carriage Return */
(buf[i] != '\t')) /* Tab */
return "application/octet-stream";
}