diff -up gnome-vfs-2.22.0/libgnomevfs/gnome-vfs-mime.c.xdgmime gnome-vfs-2.22.0/libgnomevfs/gnome-vfs-mime.c --- gnome-vfs-2.22.0/libgnomevfs/gnome-vfs-mime.c.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/gnome-vfs-mime.c 2008-07-24 10:35:59.000000000 -0400 @@ -236,6 +236,7 @@ _gnome_vfs_read_mime_from_buffer (GnomeV int max_extents; GnomeVFSResult result = GNOME_VFS_OK; const char *mime_type; + int prio; G_LOCK (gnome_vfs_mime_mutex); max_extents = xdg_mime_get_max_buffer_extents (); @@ -250,7 +251,7 @@ _gnome_vfs_read_mime_from_buffer (GnomeV } G_LOCK (gnome_vfs_mime_mutex); - mime_type = xdg_mime_get_mime_type_for_data (buffer->buffer, buffer->buffer_length); + mime_type = xdg_mime_get_mime_type_for_data (buffer->buffer, buffer->buffer_length, &prio); G_UNLOCK (gnome_vfs_mime_mutex); diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimealias.c.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimealias.c --- gnome-vfs-2.22.0/libgnomevfs/xdgmimealias.c.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimealias.c 2008-07-24 10:42:39.000000000 -0400 @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include "config.h" #endif #include "xdgmimealias.h" @@ -105,7 +105,7 @@ _xdg_mime_alias_list_lookup (XdgAliasLis if (list->n_aliases > 0) { key.alias = (char *)alias; - key.mime_type = 0; + key.mime_type = NULL; entry = bsearch (&key, list->aliases, list->n_aliases, sizeof (XdgAlias), alias_entry_cmp); diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimealias.h.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimealias.h --- gnome-vfs-2.22.0/libgnomevfs/xdgmimealias.h.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimealias.h 2008-07-24 10:42:39.000000000 -0400 @@ -33,10 +33,11 @@ typedef struct XdgAliasList XdgAliasList; #ifdef XDG_PREFIX -#define _xdg_mime_alias_read_from_file XDG_ENTRY(alias_read_from_file) -#define _xdg_mime_alias_list_new XDG_ENTRY(alias_list_new) -#define _xdg_mime_alias_list_free XDG_ENTRY(alias_list_free) -#define _xdg_mime_alias_list_lookup XDG_ENTRY(alias_list_lookup) +#define _xdg_mime_alias_read_from_file XDG_RESERVED_ENTRY(alias_read_from_file) +#define _xdg_mime_alias_list_new XDG_RESERVED_ENTRY(alias_list_new) +#define _xdg_mime_alias_list_free XDG_RESERVED_ENTRY(alias_list_free) +#define _xdg_mime_alias_list_lookup XDG_RESERVED_ENTRY(alias_list_lookup) +#define _xdg_mime_alias_list_dump XDG_RESERVED_ENTRY(alias_list_dump) #endif void _xdg_mime_alias_read_from_file (XdgAliasList *list, diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimecache.c.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimecache.c --- gnome-vfs-2.22.0/libgnomevfs/xdgmimecache.c.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimecache.c 2008-07-24 10:42:40.000000000 -0400 @@ -25,7 +25,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include "config.h" #endif #include @@ -41,6 +41,8 @@ #ifdef HAVE_MMAP #include +#else +#warning Building xdgmime without MMAP support. Binary "mime.info" cache files will not be used. #endif #include @@ -70,7 +72,7 @@ #endif #define MAJOR_VERSION 1 -#define MINOR_VERSION 0 +#define MINOR_VERSION 1 struct _XdgMimeCache { @@ -297,7 +299,7 @@ cache_magic_lookup_data (XdgMimeCache *c for (n = 0; n < n_mime_types; n++) { if (mime_types[n] && - xdg_mime_mime_type_equal (mime_types[n], non_match)) + _xdg_mime_mime_type_equal (mime_types[n], non_match)) mime_types[n] = NULL; } } @@ -344,6 +346,11 @@ cache_alias_lookup (const char *alias) return NULL; } +typedef struct { + const char *mime; + int weight; +} MimeWeight; + static int cache_glob_lookup_literal (const char *file_name, const char *mime_types[], @@ -365,7 +372,7 @@ cache_glob_lookup_literal (const char *f { mid = (min + max) / 2; - offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid); + offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid); ptr = cache->buffer + offset; cmp = strcmp (ptr, file_name); @@ -375,7 +382,7 @@ cache_glob_lookup_literal (const char *f max = mid - 1; else { - offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid + 4); + offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid + 4); mime_types[0] = (const char *)(cache->buffer + offset); return 1; @@ -388,7 +395,7 @@ cache_glob_lookup_literal (const char *f static int cache_glob_lookup_fnmatch (const char *file_name, - const char *mime_types[], + MimeWeight mime_types[], int n_mime_types) { const char *mime_type; @@ -406,14 +413,19 @@ cache_glob_lookup_fnmatch (const char *f for (j = 0; j < n_entries && n < n_mime_types; j++) { - xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j); - xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j + 4); + xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j); + xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j + 4); + int weight = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j + 8); ptr = cache->buffer + offset; mime_type = cache->buffer + mimetype_offset; /* FIXME: Not UTF-8 safe */ if (fnmatch (ptr, file_name, 0) == 0) - mime_types[n++] = mime_type; + { + mime_types[n].mime = mime_type; + mime_types[n].weight = weight; + n++; + } } if (n > 0) @@ -424,85 +436,86 @@ cache_glob_lookup_fnmatch (const char *f } static int -cache_glob_node_lookup_suffix (XdgMimeCache *cache, - xdg_uint32_t n_entries, - xdg_uint32_t offset, - const char *suffix, - int ignore_case, - const char *mime_types[], - int n_mime_types) +cache_glob_node_lookup_suffix (XdgMimeCache *cache, + xdg_uint32_t n_entries, + xdg_uint32_t offset, + xdg_unichar_t *file_name, + int len, + int ignore_case, + MimeWeight mime_types[], + int n_mime_types) { xdg_unichar_t character; xdg_unichar_t match_char; xdg_uint32_t mimetype_offset; xdg_uint32_t n_children; xdg_uint32_t child_offset; + int weight; int min, max, mid, n, i; - character = _xdg_utf8_to_ucs4 (suffix); + character = file_name[len - 1]; if (ignore_case) character = _xdg_ucs4_to_lower (character); + assert (character != 0); + min = 0; max = n_entries - 1; while (max >= min) { mid = (min + max) / 2; - - match_char = GET_UINT32 (cache->buffer, offset + 16 * mid); - + match_char = GET_UINT32 (cache->buffer, offset + 12 * mid); if (match_char < character) min = mid + 1; else if (match_char > character) max = mid - 1; else { - suffix = _xdg_utf8_next_char (suffix); - if (*suffix == '\0') - { - mimetype_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 4); - n = 0; - mime_types[n++] = cache->buffer + mimetype_offset; - - n_children = GET_UINT32 (cache->buffer, offset + 16 * mid + 8); - child_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 12); + len--; + n = 0; + n_children = GET_UINT32 (cache->buffer, offset + 12 * mid + 4); + child_offset = GET_UINT32 (cache->buffer, offset + 12 * mid + 8); + + if (len > 0) + { + n = cache_glob_node_lookup_suffix (cache, + n_children, child_offset, + file_name, len, + ignore_case, + mime_types, + n_mime_types); + } + if (n == 0) + { i = 0; while (n < n_mime_types && i < n_children) { - match_char = GET_UINT32 (cache->buffer, child_offset + 16 * i); - mimetype_offset = GET_UINT32 (cache->buffer, offset + 16 * i + 4); + match_char = GET_UINT32 (cache->buffer, child_offset + 12 * i); if (match_char != 0) break; - mime_types[n++] = cache->buffer + mimetype_offset; + mimetype_offset = GET_UINT32 (cache->buffer, child_offset + 12 * i + 4); + weight = GET_UINT32 (cache->buffer, child_offset + 12 * i + 8); + + mime_types[n].mime = cache->buffer + mimetype_offset; + mime_types[n].weight = weight; + n++; i++; } - - return n; - } - else - { - n_children = GET_UINT32 (cache->buffer, offset + 16 * mid + 8); - child_offset = GET_UINT32 (cache->buffer, offset + 16 * mid + 12); - - return cache_glob_node_lookup_suffix (cache, - n_children, child_offset, - suffix, ignore_case, - mime_types, - n_mime_types); } + return n; } } - return 0; } static int -cache_glob_lookup_suffix (const char *suffix, - int ignore_case, - const char *mime_types[], - int n_mime_types) +cache_glob_lookup_suffix (xdg_unichar_t *file_name, + int len, + int ignore_case, + MimeWeight mime_types[], + int n_mime_types) { int i, n; @@ -516,7 +529,8 @@ cache_glob_lookup_suffix (const char *su n = cache_glob_node_lookup_suffix (cache, n_entries, offset, - suffix, ignore_case, + file_name, len, + ignore_case, mime_types, n_mime_types); if (n > 0) @@ -526,41 +540,12 @@ cache_glob_lookup_suffix (const char *su return 0; } -static void -find_stopchars (char *stopchars) +static int compare_mime_weight (const void *a, const void *b) { - int i, j, k, l; - - k = 0; - for (i = 0; _caches[i]; i++) - { - XdgMimeCache *cache = _caches[i]; - - xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, 16); - xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset); - xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4); - - for (j = 0; j < n_entries; j++) - { - xdg_uint32_t match_char = GET_UINT32 (cache->buffer, offset); - - if (match_char < 128) - { - for (l = 0; l < k; l++) - if (stopchars[l] == match_char) - break; - if (l == k) - { - stopchars[k] = (char) match_char; - k++; - } - } + const MimeWeight *aa = (const MimeWeight *)a; + const MimeWeight *bb = (const MimeWeight *)b; - offset += 16; - } - } - - stopchars[k] = '\0'; + return aa->weight - bb->weight; } static int @@ -568,36 +553,40 @@ cache_glob_lookup_file_name (const char const char *mime_types[], int n_mime_types) { - const char *ptr; - char stopchars[128]; int n; + MimeWeight mimes[10]; + int n_mimes = 10; + int i; + xdg_unichar_t *ucs4; + int len; - assert (file_name != NULL); + assert (file_name != NULL && n_mime_types > 0); /* First, check the literals */ n = cache_glob_lookup_literal (file_name, mime_types, n_mime_types); if (n > 0) return n; - find_stopchars (stopchars); + ucs4 = _xdg_convert_to_ucs4 (file_name, &len); + n = cache_glob_lookup_suffix (ucs4, len, FALSE, mimes, n_mimes); - /* Next, check suffixes */ - ptr = strpbrk (file_name, stopchars); - while (ptr) - { - n = cache_glob_lookup_suffix (ptr, FALSE, mime_types, n_mime_types); - if (n > 0) - return n; - - n = cache_glob_lookup_suffix (ptr, TRUE, mime_types, n_mime_types); - if (n > 0) - return n; - - ptr = strpbrk (ptr + 1, stopchars); - } + if (n == 0) + n = cache_glob_lookup_suffix (ucs4, len, TRUE, mimes, n_mimes); + free(ucs4); /* Last, try fnmatch */ - return cache_glob_lookup_fnmatch (file_name, mime_types, n_mime_types); + if (n == 0) + n = cache_glob_lookup_fnmatch (file_name, mimes, n_mimes); + + qsort (mimes, n, sizeof (MimeWeight), compare_mime_weight); + + if (n_mime_types < n) + n = n_mime_types; + + for (i = 0; i < n; i++) + mime_types[i] = mimes[i].mime; + + return n; } int @@ -622,6 +611,7 @@ _xdg_mime_cache_get_max_buffer_extents ( static const char * cache_get_mime_type_for_data (const void *data, size_t len, + int *result_prio, const char *mime_types[], int n_mime_types) { @@ -646,11 +636,15 @@ cache_get_mime_type_for_data (const void } } + if (result_prio) + *result_prio = priority; + if (priority > 0) return mime_type; for (n = 0; n < n_mime_types; n++) { + if (mime_types[n]) return mime_types[n]; } @@ -660,9 +654,10 @@ cache_get_mime_type_for_data (const void const char * _xdg_mime_cache_get_mime_type_for_data (const void *data, - size_t len) + size_t len, + int *result_prio) { - return cache_get_mime_type_for_data (data, len, NULL, 0); + return cache_get_mime_type_for_data (data, len, result_prio, NULL, 0); } const char * @@ -670,7 +665,7 @@ _xdg_mime_cache_get_mime_type_for_file ( struct stat *statbuf) { const char *mime_type; - const char *mime_types[2]; + const char *mime_types[10]; FILE *file; unsigned char *data; int max_extent; @@ -686,7 +681,7 @@ _xdg_mime_cache_get_mime_type_for_file ( return NULL; base_name = _xdg_get_base_name (file_name); - n = cache_glob_lookup_file_name (base_name, mime_types, 2); + n = cache_glob_lookup_file_name (base_name, mime_types, 10); if (n == 1) return mime_types[0]; @@ -725,7 +720,7 @@ _xdg_mime_cache_get_mime_type_for_file ( return XDG_MIME_TYPE_UNKNOWN; } - mime_type = cache_get_mime_type_for_data (data, bytes_read, + mime_type = cache_get_mime_type_for_data (data, bytes_read, NULL, mime_types, n); free (data); @@ -745,6 +740,14 @@ _xdg_mime_cache_get_mime_type_from_file_ return XDG_MIME_TYPE_UNKNOWN; } +int +_xdg_mime_cache_get_mime_types_from_file_name (const char *file_name, + const char *mime_types[], + int n_mime_types) +{ + return cache_glob_lookup_file_name (file_name, mime_types, n_mime_types); +} + #if 1 static int is_super_type (const char *mime) @@ -850,10 +853,12 @@ _xdg_mime_cache_unalias_mime_type (const char ** _xdg_mime_cache_list_mime_parents (const char *mime) { - int i, j, p; + int i, j, k, l, p; char *all_parents[128]; /* we'll stop at 128 */ char **result; + mime = xdg_mime_unalias_mime_type (mime); + p = 0; for (i = 0; _caches[i]; i++) { @@ -864,21 +869,36 @@ _xdg_mime_cache_list_mime_parents (const for (j = 0; j < n_entries; j++) { - xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * i); - xdg_uint32_t parents_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * i + 4); - + xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j); + xdg_uint32_t parents_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * j + 4); + if (strcmp (cache->buffer + mimetype_offset, mime) == 0) { + xdg_uint32_t parent_mime_offset; xdg_uint32_t n_parents = GET_UINT32 (cache->buffer, parents_offset); - - for (j = 0; j < n_parents; j++) - all_parents[p++] = cache->buffer + parents_offset + 4 + 4 * j; + + for (k = 0; k < n_parents && p < 127; k++) + { + parent_mime_offset = GET_UINT32 (cache->buffer, parents_offset + 4 + 4 * k); + + /* Don't add same parent multiple times. + * This can happen for instance if the same type is listed in multiple directories + */ + for (l = 0; l < p; l++) + { + if (strcmp (all_parents[l], cache->buffer + parent_mime_offset) == 0) + break; + } + + if (l == p) + all_parents[p++] = cache->buffer + parent_mime_offset; + } break; } } } - all_parents[p++] = 0; + all_parents[p++] = NULL; result = (char **) malloc (p * sizeof (char *)); memcpy (result, all_parents, p * sizeof (char *)); @@ -886,3 +906,107 @@ _xdg_mime_cache_list_mime_parents (const return result; } +static const char * +cache_lookup_icon (const char *mime, int header) +{ + const char *ptr; + int i, min, max, mid, cmp; + + for (i = 0; _caches[i]; i++) + { + XdgMimeCache *cache = _caches[i]; + xdg_uint32_t list_offset = GET_UINT32 (cache->buffer, header); + xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset); + xdg_uint32_t offset; + + min = 0; + max = n_entries - 1; + while (max >= min) + { + mid = (min + max) / 2; + + offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid); + ptr = cache->buffer + offset; + cmp = strcmp (ptr, mime); + + if (cmp < 0) + min = mid + 1; + else if (cmp > 0) + max = mid - 1; + else + { + offset = GET_UINT32 (cache->buffer, list_offset + 4 + 8 * mid + 4); + return cache->buffer + offset; + } + } + } + + return NULL; +} + +const char * +_xdg_mime_cache_get_generic_icon (const char *mime) +{ + return cache_lookup_icon (mime, 36); +} + +const char * +_xdg_mime_cache_get_icon (const char *mime) +{ + const char *icon; + + icon = cache_lookup_icon (mime, 32); + + if (icon == NULL) + icon = _xdg_mime_cache_get_generic_icon (mime); + + return icon; +} + +static void +dump_glob_node (XdgMimeCache *cache, + xdg_uint32_t offset, + int depth) +{ + xdg_unichar_t character; + xdg_uint32_t mime_offset; + xdg_uint32_t n_children; + xdg_uint32_t child_offset; + int i; + + character = GET_UINT32 (cache->buffer, offset); + mime_offset = GET_UINT32 (cache->buffer, offset + 4); + n_children = GET_UINT32 (cache->buffer, offset + 8); + child_offset = GET_UINT32 (cache->buffer, offset + 12); + for (i = 0; i < depth; i++) + printf (" "); + printf ("%c", character); + if (mime_offset) + printf (" - %s", cache->buffer + mime_offset); + printf ("\n"); + if (child_offset) + { + for (i = 0; i < n_children; i++) + dump_glob_node (cache, child_offset + 20 * i, depth + 1); + } +} + +void +_xdg_mime_cache_glob_dump (void) +{ + int i, j; + for (i = 0; _caches[i]; i++) + { + XdgMimeCache *cache = _caches[i]; + xdg_uint32_t list_offset; + xdg_uint32_t n_entries; + xdg_uint32_t offset; + list_offset = GET_UINT32 (cache->buffer, 16); + n_entries = GET_UINT32 (cache->buffer, list_offset); + offset = GET_UINT32 (cache->buffer, list_offset + 4); + for (j = 0; j < n_entries; j++) + dump_glob_node (cache, offset + 20 * j, 0); + } +} + + diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimecache.h.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimecache.h --- gnome-vfs-2.22.0/libgnomevfs/xdgmimecache.h.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimecache.h 2008-07-24 10:42:40.000000000 -0400 @@ -32,9 +32,20 @@ typedef struct _XdgMimeCache XdgMimeCache; #ifdef XDG_PREFIX -#define _xdg_mime_cache_new_from_file XDG_ENTRY(cache_new_from_file) -#define _xdg_mime_cache_ref XDG_ENTRY(cache_ref) -#define _xdg_mime_cache_unref XDG_ENTRY(cache_unref) +#define _xdg_mime_cache_new_from_file XDG_RESERVED_ENTRY(cache_new_from_file) +#define _xdg_mime_cache_ref XDG_RESERVED_ENTRY(cache_ref) +#define _xdg_mime_cache_unref XDG_RESERVED_ENTRY(cache_unref) +#define _xdg_mime_cache_get_max_buffer_extents XDG_RESERVED_ENTRY(cache_get_max_buffer_extents) +#define _xdg_mime_cache_get_mime_type_for_data XDG_RESERVED_ENTRY(cache_get_mime_type_for_data) +#define _xdg_mime_cache_get_mime_type_for_file XDG_RESERVED_ENTRY(cache_get_mime_type_for_file) +#define _xdg_mime_cache_get_mime_type_from_file_name XDG_RESERVED_ENTRY(cache_get_mime_type_from_file_name) +#define _xdg_mime_cache_get_mime_types_from_file_name XDG_RESERVED_ENTRY(cache_get_mime_types_from_file_name) +#define _xdg_mime_cache_list_mime_parents XDG_RESERVED_ENTRY(cache_list_mime_parents) +#define _xdg_mime_cache_mime_type_subclass XDG_RESERVED_ENTRY(cache_mime_type_subclass) +#define _xdg_mime_cache_unalias_mime_type XDG_RESERVED_ENTRY(cache_unalias_mime_type) +#define _xdg_mime_cache_get_icon XDG_RESERVED_ENTRY(cache_get_icon) +#define _xdg_mime_cache_get_generic_icon XDG_RESERVED_ENTRY(cache_get_generic_icon) +#define _xdg_mime_cache_glob_dump XDG_RESERVED_ENTRY(cache_glob_dump) #endif extern XdgMimeCache **_caches; @@ -45,9 +56,13 @@ void _xdg_mime_cache_unref const char *_xdg_mime_cache_get_mime_type_for_data (const void *data, - size_t len); + size_t len, + int *result_prio); const char *_xdg_mime_cache_get_mime_type_for_file (const char *file_name, struct stat *statbuf); +int _xdg_mime_cache_get_mime_types_from_file_name (const char *file_name, + const char *mime_types[], + int n_mime_types); const char *_xdg_mime_cache_get_mime_type_from_file_name (const char *file_name); int _xdg_mime_cache_is_valid_mime_type (const char *mime_type); int _xdg_mime_cache_mime_type_equal (const char *mime_a, @@ -59,5 +74,8 @@ int _xdg_mime_cache_mime_type_s char **_xdg_mime_cache_list_mime_parents (const char *mime); const char *_xdg_mime_cache_unalias_mime_type (const char *mime); int _xdg_mime_cache_get_max_buffer_extents (void); +const char *_xdg_mime_cache_get_icon (const char *mime); +const char *_xdg_mime_cache_get_generic_icon (const char *mime); +void _xdg_mime_cache_glob_dump (void); #endif /* __XDG_MIME_CACHE_H__ */ diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmime.c.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmime.c --- gnome-vfs-2.22.0/libgnomevfs/xdgmime.c.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmime.c 2008-07-24 10:42:40.000000000 -0400 @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include "config.h" #endif #include "xdgmime.h" @@ -34,6 +34,7 @@ #include "xdgmimeglob.h" #include "xdgmimemagic.h" #include "xdgmimealias.h" +#include "xdgmimeicon.h" #include "xdgmimeparent.h" #include "xdgmimecache.h" #include @@ -56,6 +57,8 @@ static XdgAliasList *alias_list = NULL; static XdgParentList *parent_list = NULL; static XdgDirTimeList *dir_time_list = NULL; static XdgCallbackList *callback_list = NULL; +static XdgIconList *icon_list = NULL; +static XdgIconList *generic_icon_list = NULL; XdgMimeCache **_caches = NULL; static int n_caches = 0; @@ -93,17 +96,26 @@ struct XdgCallbackList typedef int (*XdgDirectoryFunc) (const char *directory, void *user_data); -static XdgDirTimeList * -xdg_dir_time_list_new (void) +static void +xdg_dir_time_list_add (char *file_name, + time_t mtime) { - XdgDirTimeList *retval; - - retval = calloc (1, sizeof (XdgDirTimeList)); - retval->checked = XDG_CHECKED_UNCHECKED; + XdgDirTimeList *list; - return retval; + for (list = dir_time_list; list; list = list->next) + { + if (strcmp (list->directory_name, file_name) == 0) + return; + } + + list = calloc (1, sizeof (XdgDirTimeList)); + list->checked = XDG_CHECKED_UNCHECKED; + list->directory_name = file_name; + list->mtime = mtime; + list->next = dir_time_list; + dir_time_list = list; } - + static void xdg_dir_time_list_free (XdgDirTimeList *list) { @@ -123,7 +135,6 @@ xdg_mime_init_from_directory (const char { char *file_name; struct stat st; - XdgDirTimeList *list; assert (directory != NULL); @@ -135,11 +146,7 @@ xdg_mime_init_from_directory (const char if (cache != NULL) { - list = xdg_dir_time_list_new (); - list->directory_name = file_name; - list->mtime = st.st_mtime; - list->next = dir_time_list; - dir_time_list = list; + xdg_dir_time_list_add (file_name, st.st_mtime); _caches = realloc (_caches, sizeof (XdgMimeCache *) * (n_caches + 2)); _caches[n_caches] = cache; @@ -151,21 +158,27 @@ xdg_mime_init_from_directory (const char } free (file_name); - file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1); - strcpy (file_name, directory); strcat (file_name, "/mime/globs"); + file_name = malloc (strlen (directory) + strlen ("/mime/globs2") + 1); + strcpy (file_name, directory); strcat (file_name, "/mime/globs2"); if (stat (file_name, &st) == 0) { _xdg_mime_glob_read_from_file (global_hash, file_name); - - list = xdg_dir_time_list_new (); - list->directory_name = file_name; - list->mtime = st.st_mtime; - list->next = dir_time_list; - dir_time_list = list; + xdg_dir_time_list_add (file_name, st.st_mtime); } else { free (file_name); + file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1); + strcpy (file_name, directory); strcat (file_name, "/mime/globs"); + if (stat (file_name, &st) == 0) + { + _xdg_mime_glob_read_from_file (global_hash, file_name); + xdg_dir_time_list_add (file_name, st.st_mtime); + } + else + { + free (file_name); + } } file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1); @@ -173,12 +186,7 @@ xdg_mime_init_from_directory (const char if (stat (file_name, &st) == 0) { _xdg_mime_magic_read_from_file (global_magic, file_name); - - list = xdg_dir_time_list_new (); - list->directory_name = file_name; - list->mtime = st.st_mtime; - list->next = dir_time_list; - dir_time_list = list; + xdg_dir_time_list_add (file_name, st.st_mtime); } else { @@ -195,6 +203,16 @@ xdg_mime_init_from_directory (const char _xdg_mime_parent_read_from_file (parent_list, file_name); free (file_name); + file_name = malloc (strlen (directory) + strlen ("/mime/icons") + 1); + strcpy (file_name, directory); strcat (file_name, "/mime/icons"); + _xdg_mime_icon_read_from_file (icon_list, file_name); + free (file_name); + + file_name = malloc (strlen (directory) + strlen ("/mime/generic-icons") + 1); + strcpy (file_name, directory); strcat (file_name, "/mime/generic-icons"); + _xdg_mime_icon_read_from_file (generic_icon_list, file_name); + free (file_name); + return FALSE; /* Keep processing */ } @@ -296,12 +314,11 @@ xdg_check_file (const char *file_path, for (list = dir_time_list; list; list = list->next) { - if (! strcmp (list->directory_name, file_path) && - st.st_mtime == list->mtime) + if (! strcmp (list->directory_name, file_path)) { - if (list->checked == XDG_CHECKED_UNCHECKED) + if (st.st_mtime == list->mtime) list->checked = XDG_CHECKED_VALID; - else if (list->checked == XDG_CHECKED_VALID) + else list->checked = XDG_CHECKED_INVALID; return (list->checked != XDG_CHECKED_VALID); @@ -430,6 +447,8 @@ xdg_mime_init (void) global_magic = _xdg_mime_magic_new (); alias_list = _xdg_mime_alias_list_new (); parent_list = _xdg_mime_parent_list_new (); + icon_list = _xdg_mime_icon_list_new (); + generic_icon_list = _xdg_mime_icon_list_new (); xdg_run_command_on_dirs ((XdgDirectoryFunc) xdg_mime_init_from_directory, NULL); @@ -440,16 +459,17 @@ xdg_mime_init (void) const char * xdg_mime_get_mime_type_for_data (const void *data, - size_t len) + size_t len, + int *result_prio) { const char *mime_type; xdg_mime_init (); if (_caches) - return _xdg_mime_cache_get_mime_type_for_data (data, len); + return _xdg_mime_cache_get_mime_type_for_data (data, len, result_prio); - mime_type = _xdg_mime_magic_lookup_data (global_magic, data, len, NULL, 0); + mime_type = _xdg_mime_magic_lookup_data (global_magic, data, len, result_prio, NULL, 0); if (mime_type) return mime_type; @@ -524,7 +544,7 @@ xdg_mime_get_mime_type_for_file (const c return XDG_MIME_TYPE_UNKNOWN; } - mime_type = _xdg_mime_magic_lookup_data (global_magic, data, bytes_read, + mime_type = _xdg_mime_magic_lookup_data (global_magic, data, bytes_read, NULL, mime_types, n); free (data); @@ -553,6 +573,19 @@ xdg_mime_get_mime_type_from_file_name (c } int +xdg_mime_get_mime_types_from_file_name (const char *file_name, + const char *mime_types[], + int n_mime_types) +{ + xdg_mime_init (); + + if (_caches) + return _xdg_mime_cache_get_mime_types_from_file_name (file_name, mime_types, n_mime_types); + + return _xdg_glob_hash_lookup_file_name (global_hash, file_name, mime_types, n_mime_types); +} + +int xdg_mime_is_valid_mime_type (const char *mime_type) { /* FIXME: We should make this a better test @@ -675,8 +708,6 @@ xdg_mime_media_type_equal (const char *m { char *sep; - xdg_mime_init (); - sep = strchr (mime_a, '/'); if (sep && strncmp (mime_a, mime_b, sep - mime_a + 1) == 0) @@ -791,10 +822,18 @@ xdg_mime_get_mime_parents (const char *m void xdg_mime_dump (void) { + xdg_mime_init(); + printf ("*** ALIASES ***\n\n"); _xdg_mime_alias_list_dump (alias_list); printf ("\n*** PARENTS ***\n\n"); _xdg_mime_parent_list_dump (parent_list); + printf ("\n*** CACHE ***\n\n"); + _xdg_glob_hash_dump (global_hash); + printf ("\n*** GLOBS ***\n\n"); + _xdg_glob_hash_dump (global_hash); + printf ("\n*** GLOBS REVERSE TREE ***\n\n"); + _xdg_mime_cache_glob_dump (); } @@ -848,3 +887,32 @@ xdg_mime_remove_callback (int callback_i } } } + +const char * +xdg_mime_get_icon (const char *mime) +{ + const char *icon; + + xdg_mime_init (); + + if (_caches) + return _xdg_mime_cache_get_icon (mime); + + icon = _xdg_mime_icon_list_lookup (icon_list, mime); + + if (!icon) + icon = xdg_mime_get_generic_icon (mime); + + return icon; +} + +const char * +xdg_mime_get_generic_icon (const char *mime) +{ + xdg_mime_init (); + + if (_caches) + return _xdg_mime_cache_get_generic_icon (mime); + + return _xdg_mime_icon_list_lookup (generic_icon_list, mime); +} diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimeglob.c.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimeglob.c --- gnome-vfs-2.22.0/libgnomevfs/xdgmimeglob.c.xdgmime 2008-07-24 10:35:59.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimeglob.c 2008-07-24 10:42:40.000000000 -0400 @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include "config.h" #endif #include "xdgmimeglob.h" @@ -52,6 +52,7 @@ struct XdgGlobHashNode { xdg_unichar_t character; const char *mime_type; + int weight; XdgGlobHashNode *next; XdgGlobHashNode *child; }; @@ -59,6 +60,7 @@ struct XdgGlobList { const char *data; const char *mime_type; + int weight; XdgGlobList *next; }; @@ -107,7 +109,8 @@ _xdg_glob_list_free (XdgGlobList *glob_l static XdgGlobList * _xdg_glob_list_append (XdgGlobList *glob_list, void *data, - const char *mime_type) + const char *mime_type, + int weight) { XdgGlobList *new_element; XdgGlobList *tmp_element; @@ -115,6 +118,7 @@ _xdg_glob_list_append (XdgGlobList *glob new_element = _xdg_glob_list_new (); new_element->data = data; new_element->mime_type = mime_type; + new_element->weight = weight; if (glob_list == NULL) return new_element; @@ -127,23 +131,6 @@ _xdg_glob_list_append (XdgGlobList *glob return glob_list; } -#if 0 -static XdgGlobList * -_xdg_glob_list_prepend (XdgGlobList *glob_list, - void *data, - const char *mime_type) -{ - XdgGlobList *new_element; - - new_element = _xdg_glob_list_new (); - new_element->data = data; - new_element->next = glob_list; - new_element->mime_type = mime_type; - - return new_element; -} -#endif - /* XdgGlobHashNode */ @@ -167,7 +154,7 @@ _xdg_glob_hash_node_dump (XdgGlobHashNod printf ("%c", (char)glob_hash_node->character); if (glob_hash_node->mime_type) - printf (" - %s\n", glob_hash_node->mime_type); + printf (" - %s %d\n", glob_hash_node->mime_type, glob_hash_node->weight); else printf ("\n"); if (glob_hash_node->child) @@ -177,14 +164,15 @@ _xdg_glob_hash_node_dump (XdgGlobHashNod } static XdgGlobHashNode * -_xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node, - const char *text, - const char *mime_type) +_xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node, + xdg_unichar_t *text, + const char *mime_type, + int weight) { XdgGlobHashNode *node; xdg_unichar_t character; - character = _xdg_utf8_to_ucs4 (text); + character = text[0]; if ((glob_hash_node == NULL) || (character < glob_hash_node->character)) @@ -238,8 +226,8 @@ _xdg_glob_hash_insert_text (XdgGlobHashN } } - text = _xdg_utf8_next_char (text); - if (*text == '\000') + text++; + if (*text == 0) { if (node->mime_type) { @@ -249,7 +237,7 @@ _xdg_glob_hash_insert_text (XdgGlobHashN int found_node = FALSE; child = node->child; - while (child && child->character == '\0') + while (child && child->character == 0) { if (strcmp (child->mime_type, mime_type) == 0) { @@ -262,8 +250,9 @@ _xdg_glob_hash_insert_text (XdgGlobHashN if (!found_node) { child = _xdg_glob_hash_node_new (); - child->character = '\000'; + child->character = 0; child->mime_type = strdup (mime_type); + child->weight = weight; child->child = NULL; child->next = node->child; node->child = child; @@ -273,20 +262,45 @@ _xdg_glob_hash_insert_text (XdgGlobHashN else { node->mime_type = strdup (mime_type); + node->weight = weight; } } else { - node->child = _xdg_glob_hash_insert_text (node->child, text, mime_type); + node->child = _xdg_glob_hash_insert_ucs4 (node->child, text, mime_type, weight); } return glob_hash_node; } +/* glob must be valid UTF-8 */ +static XdgGlobHashNode * +_xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node, + const char *text, + const char *mime_type, + int weight) +{ + XdgGlobHashNode *node; + xdg_unichar_t *unitext; + int len; + + unitext = _xdg_convert_to_ucs4 (text, &len); + _xdg_reverse_ucs4 (unitext, len); + node = _xdg_glob_hash_insert_ucs4 (glob_hash_node, unitext, mime_type, weight); + free (unitext); + return node; +} + +typedef struct { + const char *mime; + int weight; +} MimeWeight; + static int _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node, - const char *file_name, + xdg_unichar_t *file_name, + int len, int ignore_case, - const char *mime_types[], + MimeWeight mime_types[], int n_mime_types) { int n; @@ -296,36 +310,45 @@ _xdg_glob_hash_node_lookup_file_name (Xd if (glob_hash_node == NULL) return 0; - character = _xdg_utf8_to_ucs4 (file_name); + character = file_name[len - 1]; if (ignore_case) character = _xdg_ucs4_to_lower(character); for (node = glob_hash_node; node && character >= node->character; node = node->next) { if (character == node->character) - { - file_name = _xdg_utf8_next_char (file_name); - if (*file_name == '\000') + { + len--; + n = 0; + if (len > 0) + { + n = _xdg_glob_hash_node_lookup_file_name (node->child, + file_name, + len, + ignore_case, + mime_types, + n_mime_types); + } + if (n == 0) { - n = 0; if (node->mime_type) - mime_types[n++] = node->mime_type; + { + mime_types[n].mime = node->mime_type; + mime_types[n].weight = node->weight; + n++; + } node = node->child; while (n < n_mime_types && node && node->character == 0) { if (node->mime_type) - mime_types[n++] = node->mime_type; + { + mime_types[n].mime = node->mime_type; + mime_types[n].weight = node->weight; + n++; + } node = node->next; } } - else - { - n = _xdg_glob_hash_node_lookup_file_name (node->child, - file_name, - ignore_case, - mime_types, - n_mime_types); - } return n; } } @@ -333,6 +356,14 @@ _xdg_glob_hash_node_lookup_file_name (Xd return 0; } +static int compare_mime_weight (const void *a, const void *b) +{ + const MimeWeight *aa = (const MimeWeight *)a; + const MimeWeight *bb = (const MimeWeight *)b; + + return aa->weight - bb->weight; +} + int _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, const char *file_name, @@ -340,15 +371,18 @@ _xdg_glob_hash_lookup_file_name (XdgGlob int n_mime_types) { XdgGlobList *list; - const char *ptr; - char stopchars[128]; int i, n; - XdgGlobHashNode *node; + MimeWeight mimes[10]; + int n_mimes = 10; + xdg_unichar_t *ucs4; + int len; /* First, check the literals */ assert (file_name != NULL && n_mime_types > 0); + n = 0; + for (list = glob_hash->literal_list; list; list = list->next) { if (strcmp ((const char *)list->data, file_name) == 0) @@ -358,38 +392,36 @@ _xdg_glob_hash_lookup_file_name (XdgGlob } } - i = 0; - for (node = glob_hash->simple_node; node; node = node->next) - { - if (node->character < 128) - stopchars[i++] = (char)node->character; - } - stopchars[i] = '\0'; - - ptr = strpbrk (file_name, stopchars); - while (ptr) - { - n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, FALSE, - mime_types, n_mime_types); - if (n > 0) - return n; - - n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, TRUE, - mime_types, n_mime_types); - if (n > 0) - return n; - - ptr = strpbrk (ptr + 1, stopchars); - } + ucs4 = _xdg_convert_to_ucs4 (file_name, &len); + n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ucs4, len, FALSE, + mimes, n_mimes); + if (n == 0) + n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ucs4, len, TRUE, + mimes, n_mimes); + free(ucs4); /* FIXME: Not UTF-8 safe */ - n = 0; - for (list = glob_hash->full_list; list && n < n_mime_types; list = list->next) + if (n == 0) { - if (fnmatch ((const char *)list->data, file_name, 0) == 0) - mime_types[n++] = list->mime_type; + for (list = glob_hash->full_list; list && n < n_mime_types; list = list->next) + { + if (fnmatch ((const char *)list->data, file_name, 0) == 0) + { + mimes[n].mime = list->mime_type; + mimes[n].weight = list->weight; + n++; + } + } } + qsort (mimes, n, sizeof (MimeWeight), compare_mime_weight); + + if (n_mime_types < n) + n = n_mime_types; + + for (i = 0; i < n; i++) + mime_types[i] = mimes[i].mime; + return n; } @@ -442,7 +474,7 @@ _xdg_glob_determine_type (const char *gl ptr = glob; - while (*ptr != '\000') + while (*ptr != '\0') { if (*ptr == '*' && first_char) maybe_in_simple_glob = TRUE; @@ -462,7 +494,8 @@ _xdg_glob_determine_type (const char *gl void _xdg_glob_hash_append_glob (XdgGlobHash *glob_hash, const char *glob, - const char *mime_type) + const char *mime_type, + int weight) { XdgGlobType type; @@ -474,13 +507,13 @@ _xdg_glob_hash_append_glob (XdgGlobHash switch (type) { case XDG_GLOB_LITERAL: - glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type)); + glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type), weight); break; case XDG_GLOB_SIMPLE: - glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, mime_type); + glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, mime_type, weight); break; case XDG_GLOB_FULL: - glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type)); + glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type), weight); break; } } @@ -490,27 +523,34 @@ _xdg_glob_hash_dump (XdgGlobHash *glob_h { XdgGlobList *list; printf ("LITERAL STRINGS\n"); - if (glob_hash->literal_list == NULL) + if (!glob_hash || glob_hash->literal_list == NULL) { printf (" None\n"); } else { for (list = glob_hash->literal_list; list; list = list->next) - printf (" %s - %s\n", (char *)list->data, list->mime_type); + printf (" %s - %s %d\n", (char *)list->data, list->mime_type, list->weight); } printf ("\nSIMPLE GLOBS\n"); - _xdg_glob_hash_node_dump (glob_hash->simple_node, 4); + if (!glob_hash || glob_hash->simple_node == NULL) + { + printf (" None\n"); + } + else + { + _xdg_glob_hash_node_dump (glob_hash->simple_node, 4); + } printf ("\nFULL GLOBS\n"); - if (glob_hash->full_list == NULL) + if (!glob_hash || glob_hash->full_list == NULL) { printf (" None\n"); } else { for (list = glob_hash->full_list; list; list = list->next) - printf (" %s - %s\n", (char *)list->data, list->mime_type); + printf (" %s - %s %d\n", (char *)list->data, list->mime_type, list->weight); } } @@ -531,16 +571,33 @@ _xdg_mime_glob_read_from_file (XdgGlobHa * Blah */ while (fgets (line, 255, glob_file) != NULL) { - char *colon; + char *colon, *colon2; + char *mimetype, *glob; + int weight; + if (line[0] == '#') continue; colon = strchr (line, ':'); if (colon == NULL) continue; - *(colon++) = '\000'; - colon[strlen (colon) -1] = '\000'; - _xdg_glob_hash_append_glob (glob_hash, colon, line); + *(colon++) = '\0'; + colon[strlen (colon) -1] = '\0'; + colon2 = strchr (colon, ':'); + if (colon2) + { + *(colon2++) = '\000'; + weight = atoi (line); + mimetype = colon; + glob = colon2; + } + else + { + weight = 50; + mimetype = line; + glob = colon; + } + _xdg_glob_hash_append_glob (glob_hash, glob, mimetype, weight); } fclose (glob_file); diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimeglob.h.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimeglob.h --- gnome-vfs-2.22.0/libgnomevfs/xdgmimeglob.h.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimeglob.h 2008-07-24 10:42:40.000000000 -0400 @@ -41,13 +41,13 @@ typedef enum #ifdef XDG_PREFIX -#define _xdg_mime_glob_read_from_file XDG_ENTRY(glob_read_from_file) -#define _xdg_glob_hash_new XDG_ENTRY(hash_new) -#define _xdg_glob_hash_free XDG_ENTRY(hash_free) -#define _xdg_glob_hash_lookup_file_name XDG_ENTRY(hash_lookup_file_name) -#define _xdg_glob_hash_append_glob XDG_ENTRY(hash_append_glob) -#define _xdg_glob_determine_type XDG_ENTRY(determine_type) -#define _xdg_glob_hash_dump XDG_ENTRY(hash_dump) +#define _xdg_mime_glob_read_from_file XDG_RESERVED_ENTRY(glob_read_from_file) +#define _xdg_glob_hash_new XDG_RESERVED_ENTRY(hash_new) +#define _xdg_glob_hash_free XDG_RESERVED_ENTRY(hash_free) +#define _xdg_glob_hash_lookup_file_name XDG_RESERVED_ENTRY(hash_lookup_file_name) +#define _xdg_glob_hash_append_glob XDG_RESERVED_ENTRY(hash_append_glob) +#define _xdg_glob_determine_type XDG_RESERVED_ENTRY(determine_type) +#define _xdg_glob_hash_dump XDG_RESERVED_ENTRY(hash_dump) #endif void _xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash, @@ -60,7 +60,8 @@ int _xdg_glob_hash_lookup_file_ int n_mime_types); void _xdg_glob_hash_append_glob (XdgGlobHash *glob_hash, const char *glob, - const char *mime_type); + const char *mime_type, + int weight); XdgGlobType _xdg_glob_determine_type (const char *glob); void _xdg_glob_hash_dump (XdgGlobHash *glob_hash); diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmime.h.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmime.h --- gnome-vfs-2.22.0/libgnomevfs/xdgmime.h.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmime.h 2008-07-24 10:42:40.000000000 -0400 @@ -40,6 +40,10 @@ extern "C" { #define XDG_ENTRY(func) _XDG_ENTRY2(XDG_PREFIX,func) #define _XDG_ENTRY2(prefix,func) _XDG_ENTRY3(prefix,func) #define _XDG_ENTRY3(prefix,func) prefix##_##func + +#define XDG_RESERVED_ENTRY(func) _XDG_RESERVED_ENTRY2(XDG_PREFIX,func) +#define _XDG_RESERVED_ENTRY2(prefix,func) _XDG_RESERVED_ENTRY3(prefix,func) +#define _XDG_RESERVED_ENTRY3(prefix,func) _##prefix##_##func #endif typedef void (*XdgMimeCallback) (void *user_data); @@ -50,32 +54,40 @@ typedef void (*XdgMimeDestroy) (void *u #define xdg_mime_get_mime_type_for_data XDG_ENTRY(get_mime_type_for_data) #define xdg_mime_get_mime_type_for_file XDG_ENTRY(get_mime_type_for_file) #define xdg_mime_get_mime_type_from_file_name XDG_ENTRY(get_mime_type_from_file_name) +#define xdg_mime_get_mime_types_from_file_name XDG_ENTRY(get_mime_types_from_file_name) #define xdg_mime_is_valid_mime_type XDG_ENTRY(is_valid_mime_type) #define xdg_mime_mime_type_equal XDG_ENTRY(mime_type_equal) -#define _xdg_mime_mime_type_equal XDG_ENTRY(mime_type_equal_p) #define xdg_mime_media_type_equal XDG_ENTRY(media_type_equal) #define xdg_mime_mime_type_subclass XDG_ENTRY(mime_type_subclass) -#define _xdg_mime_mime_type_subclass XDG_ENTRY(mime_type_subclass_p) #define xdg_mime_get_mime_parents XDG_ENTRY(get_mime_parents) #define xdg_mime_list_mime_parents XDG_ENTRY(list_mime_parents) #define xdg_mime_unalias_mime_type XDG_ENTRY(unalias_mime_type) -#define _xdg_mime_unalias_mime_type XDG_ENTRY(unalias_mime_type_p) #define xdg_mime_get_max_buffer_extents XDG_ENTRY(get_max_buffer_extents) #define xdg_mime_shutdown XDG_ENTRY(shutdown) #define xdg_mime_dump XDG_ENTRY(dump) #define xdg_mime_register_reload_callback XDG_ENTRY(register_reload_callback) #define xdg_mime_remove_callback XDG_ENTRY(remove_callback) #define xdg_mime_type_unknown XDG_ENTRY(type_unknown) +#define xdg_mime_get_icon XDG_ENTRY(get_icon) +#define xdg_mime_get_generic_icon XDG_ENTRY(get_generic_icon) + +#define _xdg_mime_mime_type_equal XDG_RESERVED_ENTRY(mime_type_equal) +#define _xdg_mime_mime_type_subclass XDG_RESERVED_ENTRY(mime_type_subclass) +#define _xdg_mime_unalias_mime_type XDG_RESERVED_ENTRY(unalias_mime_type) #endif extern const char xdg_mime_type_unknown[]; #define XDG_MIME_TYPE_UNKNOWN xdg_mime_type_unknown const char *xdg_mime_get_mime_type_for_data (const void *data, - size_t len); + size_t len, + int *result_prio); const char *xdg_mime_get_mime_type_for_file (const char *file_name, struct stat *statbuf); const char *xdg_mime_get_mime_type_from_file_name (const char *file_name); +int xdg_mime_get_mime_types_from_file_name(const char *file_name, + const char *mime_types[], + int n_mime_types); int xdg_mime_is_valid_mime_type (const char *mime_type); int xdg_mime_mime_type_equal (const char *mime_a, const char *mime_b); @@ -91,6 +103,8 @@ int xdg_mime_mime_type_subclass const char **xdg_mime_get_mime_parents (const char *mime); char ** xdg_mime_list_mime_parents (const char *mime); const char *xdg_mime_unalias_mime_type (const char *mime); +const char *xdg_mime_get_icon (const char *mime); +const char *xdg_mime_get_generic_icon (const char *mime); int xdg_mime_get_max_buffer_extents (void); void xdg_mime_shutdown (void); void xdg_mime_dump (void); @@ -102,11 +116,9 @@ void xdg_mime_remove_callback /* Private versions of functions that don't call xdg_mime_init () */ int _xdg_mime_mime_type_equal (const char *mime_a, const char *mime_b); -int _xdg_mime_media_type_equal (const char *mime_a, - const char *mime_b); int _xdg_mime_mime_type_subclass (const char *mime, const char *base); -const char *_xdg_mime_unalias_mime_type (const char *mime); +const char *_xdg_mime_unalias_mime_type (const char *mime); #ifdef __cplusplus diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimeint.c.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimeint.c --- gnome-vfs-2.22.0/libgnomevfs/xdgmimeint.c.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimeint.c 2008-07-24 10:42:40.000000000 -0400 @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include "config.h" #endif #include "xdgmimeint.h" @@ -152,3 +152,40 @@ _xdg_get_base_name (const char *file_nam else return base_name + 1; } + +xdg_unichar_t * +_xdg_convert_to_ucs4 (const char *source, int *len) +{ + xdg_unichar_t *out; + int i; + const char *p; + + out = malloc (sizeof (xdg_unichar_t) * (strlen (source) + 1)); + + p = source; + i = 0; + while (*p) + { + out[i++] = _xdg_utf8_to_ucs4 (p); + p = _xdg_utf8_next_char (p); + } + out[i] = 0; + *len = i; + + return out; +} + +void +_xdg_reverse_ucs4 (xdg_unichar_t *source, int len) +{ + xdg_unichar_t c; + int i; + + for (i = 0; i < len - i - 1; i++) + { + c = source[i]; + source[i] = source[len - i - 1]; + source[len - i - 1] = c; + } +} + diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimeint.h.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimeint.h --- gnome-vfs-2.22.0/libgnomevfs/xdgmimeint.h.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimeint.h 2008-07-24 10:42:40.000000000 -0400 @@ -46,11 +46,13 @@ typedef unsigned short xdg_uint16_t; typedef unsigned int xdg_uint32_t; #ifdef XDG_PREFIX -#define _xdg_utf8_skip XDG_ENTRY(utf8_skip) -#define _xdg_utf8_to_ucs4 XDG_ENTRY(utf8_to_ucs4) -#define _xdg_ucs4_to_lower XDG_ENTRY(ucs4_to_lower) -#define _xdg_utf8_validate XDG_ENTRY(utf8_validate) -#define _xdg_get_base_name XDG_ENTRY(get_ase_name) +#define _xdg_utf8_skip XDG_RESERVED_ENTRY(utf8_skip) +#define _xdg_utf8_to_ucs4 XDG_RESERVED_ENTRY(utf8_to_ucs4) +#define _xdg_ucs4_to_lower XDG_RESERVED_ENTRY(ucs4_to_lower) +#define _xdg_utf8_validate XDG_RESERVED_ENTRY(utf8_validate) +#define _xdg_get_base_name XDG_RESERVED_ENTRY(get_base_name) +#define _xdg_convert_to_ucs4 XDG_RESERVED_ENTRY(convert_to_ucs4) +#define _xdg_reverse_ucs4 XDG_RESERVED_ENTRY(reverse_ucs4) #endif #define SWAP_BE16_TO_LE16(val) (xdg_uint16_t)(((xdg_uint16_t)(val) << 8)|((xdg_uint16_t)(val) >> 8)) @@ -68,6 +70,8 @@ extern const char *const _xdg_utf8_skip; xdg_unichar_t _xdg_utf8_to_ucs4 (const char *source); xdg_unichar_t _xdg_ucs4_to_lower (xdg_unichar_t source); int _xdg_utf8_validate (const char *source); +xdg_unichar_t *_xdg_convert_to_ucs4 (const char *source, int *len); +void _xdg_reverse_ucs4 (xdg_unichar_t *source, int len); const char *_xdg_get_base_name (const char *file_name); #endif /* __XDG_MIME_INT_H__ */ diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimemagic.c.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimemagic.c --- gnome-vfs-2.22.0/libgnomevfs/xdgmimemagic.c.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimemagic.c 2008-07-24 10:42:40.000000000 -0400 @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include "config.h" #endif #include @@ -47,6 +47,10 @@ #define TRUE (!FALSE) #endif +#if !defined getc_unlocked && !defined HAVE_GETC_UNLOCKED +# define getc_unlocked(fp) getc (fp) +#endif + typedef struct XdgMimeMagicMatch XdgMimeMagicMatch; typedef struct XdgMimeMagicMatchlet XdgMimeMagicMatchlet; @@ -472,9 +476,7 @@ _xdg_mime_magic_parse_magic_line (FILE /* We clean up the matchlet, byte swapping if needed */ if (matchlet->word_size > 1) { -#if LITTLE_ENDIAN int i; -#endif if (matchlet->value_length % matchlet->word_size != 0) { _xdg_mime_magic_matchlet_free (matchlet); @@ -654,34 +656,24 @@ const char * _xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic, const void *data, size_t len, + int *result_prio, const char *mime_types[], int n_mime_types) { XdgMimeMagicMatch *match; const char *mime_type; int n; - int priority; - int had_match; + int prio; + prio = 0; mime_type = NULL; - priority = 0; - had_match = 0; for (match = mime_magic->match_list; match; match = match->next) { if (_xdg_mime_magic_match_compare_to_data (match, data, len)) { - if (!had_match || match->priority > priority || - (mime_type != NULL && _xdg_mime_mime_type_subclass (match->mime_type, mime_type))) - { - mime_type = match->mime_type; - priority = match->priority; - } - else if (had_match && match->priority == priority) - /* multiple unrelated patterns with the same priority matched, - * so we can't tell what type this is. */ - mime_type = NULL; - - had_match = 1; + prio = match->priority; + mime_type = match->mime_type; + break; } else { @@ -702,6 +694,9 @@ _xdg_mime_magic_lookup_data (XdgMimeMagi mime_type = mime_types[n]; } } + + if (result_prio) + *result_prio = prio; return mime_type; } diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimemagic.h.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimemagic.h --- gnome-vfs-2.22.0/libgnomevfs/xdgmimemagic.h.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimemagic.h 2008-07-24 10:42:40.000000000 -0400 @@ -33,12 +33,12 @@ typedef struct XdgMimeMagic XdgMimeMagic; #ifdef XDG_PREFIX -#define _xdg_mime_glob_read_from_file XDG_ENTRY(glob_read_from_file) -#define _xdg_mime_magic_new XDG_ENTRY(magic_new) -#define _xdg_mime_magic_read_from_file XDG_ENTRY(magic_read_from_file) -#define _xdg_mime_magic_free XDG_ENTRY(magic_free) -#define _xdg_mime_magic_get_buffer_extents XDG_ENTRY(magic_get_buffer_extents) -#define _xdg_mime_magic_lookup_data XDG_ENTRY(magic_lookup_data) +#define _xdg_mime_glob_read_from_file XDG_RESERVED_ENTRY(glob_read_from_file) +#define _xdg_mime_magic_new XDG_RESERVED_ENTRY(magic_new) +#define _xdg_mime_magic_read_from_file XDG_RESERVED_ENTRY(magic_read_from_file) +#define _xdg_mime_magic_free XDG_RESERVED_ENTRY(magic_free) +#define _xdg_mime_magic_get_buffer_extents XDG_RESERVED_ENTRY(magic_get_buffer_extents) +#define _xdg_mime_magic_lookup_data XDG_RESERVED_ENTRY(magic_lookup_data) #endif @@ -50,6 +50,7 @@ int _xdg_mime_magic_get_buffer const char *_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic, const void *data, size_t len, + int *result_prio, const char *mime_types[], int n_mime_types); diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimeparent.c.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimeparent.c --- gnome-vfs-2.22.0/libgnomevfs/xdgmimeparent.c.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimeparent.c 2008-07-24 10:42:40.000000000 -0400 @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include "config.h" #endif #include "xdgmimeparent.h" diff -up gnome-vfs-2.22.0/libgnomevfs/xdgmimeparent.h.xdgmime gnome-vfs-2.22.0/libgnomevfs/xdgmimeparent.h --- gnome-vfs-2.22.0/libgnomevfs/xdgmimeparent.h.xdgmime 2008-03-10 15:12:45.000000000 -0400 +++ gnome-vfs-2.22.0/libgnomevfs/xdgmimeparent.h 2008-07-24 10:42:40.000000000 -0400 @@ -33,10 +33,11 @@ typedef struct XdgParentList XdgParentList; #ifdef XDG_PREFIX -#define _xdg_mime_parent_read_from_file XDG_ENTRY(parent_read_from_file) -#define _xdg_mime_parent_list_new XDG_ENTRY(parent_list_new) -#define _xdg_mime_parent_list_free XDG_ENTRY(parent_list_free) -#define _xdg_mime_parent_list_lookup XDG_ENTRY(parent_list_lookup) +#define _xdg_mime_parent_read_from_file XDG_RESERVED_ENTRY(parent_read_from_file) +#define _xdg_mime_parent_list_new XDG_RESERVED_ENTRY(parent_list_new) +#define _xdg_mime_parent_list_free XDG_RESERVED_ENTRY(parent_list_free) +#define _xdg_mime_parent_list_lookup XDG_RESERVED_ENTRY(parent_list_lookup) +#define _xdg_mime_parent_list_dump XDG_RESERVED_ENTRY(parent_list_dump) #endif void _xdg_mime_parent_read_from_file (XdgParentList *list,