From 2bd31c9e6c6159a5ef0a92ea567b48649256ab43 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 9 Jun 2008 16:45:19 +0000 Subject: [PATCH] Sync with upstream svn path=/trunk/; revision=6975 --- gio/ChangeLog | 13 ++ gio/xdgmime/test-mime.c | 56 ++++++++- gio/xdgmime/xdgmime.c | 67 +++++++++- gio/xdgmime/xdgmime.h | 15 ++- gio/xdgmime/xdgmimealias.h | 10 +- gio/xdgmime/xdgmimecache.c | 300 +++++++++++++++++++++++++++++--------------- gio/xdgmime/xdgmimecache.h | 29 +++-- gio/xdgmime/xdgmimeglob.c | 235 +++++++++++++++++++++------------- gio/xdgmime/xdgmimeglob.h | 17 +-- gio/xdgmime/xdgmimeicon.c | 183 +++++++++++++++++++++++++++ gio/xdgmime/xdgmimeicon.h | 50 ++++++++ gio/xdgmime/xdgmimeint.c | 37 ++++++ gio/xdgmime/xdgmimeint.h | 14 ++- gio/xdgmime/xdgmimemagic.h | 12 +- gio/xdgmime/xdgmimeparent.h | 10 +- 15 files changed, 808 insertions(+), 240 deletions(-) create mode 100644 gio/xdgmime/xdgmimeicon.c create mode 100644 gio/xdgmime/xdgmimeicon.h diff --git a/gio/ChangeLog b/gio/ChangeLog index 6c20add..9abf8a2 100644 --- a/gio/ChangeLog +++ b/gio/ChangeLog @@ -1,3 +1,9 @@ +2008-06-09 Matthias Clasen + + * xdgmime/*: Sync with upstream. This brings support for + glob weights, generic icons, and changes the cache format to + version 1.1. + 2008-05-28 Michael Natterer * Makefile.am: don't define G_DISABLE_SINGLE_INCLUDES, it's in @@ -51,6 +57,13 @@ 2008-05-17 Matthias Clasen + * gcontenttype.h: + * gcontenttype.c: (g_content_type_from_mime_type): + New function to create a content type from a mime type. (#527175, + Milan Crha) + +2008-05-17 Matthias Clasen + Bug 532965 – Should not return filesystem::free for certain file systems * glocalfile.c (g_local_file_query_filesystem_info) Don't return diff --git a/gio/xdgmime/test-mime.c b/gio/xdgmime/test-mime.c index 7cff59b..d9a5b53 100644 --- a/gio/xdgmime/test-mime.c +++ b/gio/xdgmime/test-mime.c @@ -113,7 +113,59 @@ test_subclassing (void) test_subclass ("image/vnd.djvu", "image/x-djvu", 1); test_subclass ("image/vnd.djvu", "text/plain", 0); test_subclass ("image/vnd.djvu", "text/*", 0); - test_subclass ("text/*", "text/plain", 0); + test_subclass ("text/*", "text/plain", 1); +} + +static void +test_one_match (const char *filename, const char *expected) +{ + const char *actual; + + actual = xdg_mime_get_mime_type_from_file_name (filename); + + if (strcmp (actual, expected) != 0) + { + printf ("Test Failed: mime type of %s is %s, expected %s\n", + filename, actual, expected); + } +} + +static void +test_matches (void) +{ + test_one_match ("foo.bar.epub", "application/epub+zip"); + test_one_match ("core", "application/x-core"); + test_one_match ("README.in", "text/x-readme"); + test_one_match ("README.gz", "application/x-gzip"); + test_one_match ("blabla.cs", "text/x-csharp"); + test_one_match ("blabla.f90", "text/x-fortran"); + test_one_match ("blabla.F95", "text/x-fortran"); + test_one_match ("tarball.tar.gz", "application/x-compressed-tar"); + test_one_match ("file.gz", "application/x-gzip"); + test_one_match ("file.tar.lzo", "application/x-tzo"); + test_one_match ("file.lzo", "application/x-lzop"); +} + +static void +test_one_icon (const char *mimetype, const char *expected) +{ + const char *actual; + + actual = xdg_mime_get_icon (mimetype); + + if (actual != expected && strcmp (actual, expected) != 0) + { + printf ("Test Failed: icon of %s is %s, expected %s\n", + mimetype, actual, expected); + } +} + +static void +test_icons (void) +{ + test_one_icon ("application/x-font-ttx", "font-x-generic"); + test_one_icon ("application/mathematica", "x-office-document"); + test_one_icon ("text/plain", NULL); } int @@ -126,6 +178,8 @@ main (int argc, char *argv[]) test_glob_type (); test_aliasing (); test_subclassing (); + test_matches (); + test_icons (); for (i = 1; i < argc; i++) { diff --git a/gio/xdgmime/xdgmime.c b/gio/xdgmime/xdgmime.c index 332c165..e1c943f 100644 --- a/gio/xdgmime/xdgmime.c +++ b/gio/xdgmime/xdgmime.c @@ -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; @@ -155,8 +158,8 @@ xdg_mime_init_from_directory (const char *directory) } 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); @@ -165,6 +168,17 @@ xdg_mime_init_from_directory (const char *directory) 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); @@ -189,6 +203,16 @@ xdg_mime_init_from_directory (const char *directory) _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 */ } @@ -423,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); @@ -796,10 +822,18 @@ xdg_mime_get_mime_parents (const char *mime) 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 (); } @@ -853,3 +887,32 @@ xdg_mime_remove_callback (int callback_id) } } } + +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 --git a/gio/xdgmime/xdgmime.h b/gio/xdgmime/xdgmime.h index fde7cfe..d3031a3 100644 --- a/gio/xdgmime/xdgmime.h +++ b/gio/xdgmime/xdgmime.h @@ -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); @@ -53,20 +57,23 @@ typedef void (*XdgMimeDestroy) (void *user_data); #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[]; @@ -96,6 +103,8 @@ int xdg_mime_mime_type_subclass (const char *mime_a, 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); diff --git a/gio/xdgmime/xdgmimealias.h b/gio/xdgmime/xdgmimealias.h index d0aaed0..3c28012 100644 --- a/gio/xdgmime/xdgmimealias.h +++ b/gio/xdgmime/xdgmimealias.h @@ -33,11 +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_list_dump XDG_ENTRY(alias_list_dump) +#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 --git a/gio/xdgmime/xdgmimecache.c b/gio/xdgmime/xdgmimecache.c index 8e762a1..290bfe3 100644 --- a/gio/xdgmime/xdgmimecache.c +++ b/gio/xdgmime/xdgmimecache.c @@ -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 { @@ -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 *file_name, { 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 *file_name, 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 *file_name, 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 *file_name, 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,86 +436,86 @@ cache_glob_lookup_fnmatch (const char *file_name, } 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; - if (mimetype_offset) - 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; @@ -517,7 +529,8 @@ cache_glob_lookup_suffix (const char *suffix, 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) @@ -527,41 +540,12 @@ cache_glob_lookup_suffix (const char *suffix, 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); + const MimeWeight *aa = (const MimeWeight *)a; + const MimeWeight *bb = (const MimeWeight *)b; - 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++; - } - } - - offset += 16; - } - } - - stopchars[k] = '\0'; + return aa->weight - bb->weight; } static int @@ -569,36 +553,40 @@ cache_glob_lookup_file_name (const char *file_name, 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); - - /* 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; + ucs4 = _xdg_convert_to_ucs4 (file_name, &len); + n = cache_glob_lookup_suffix (ucs4, len, FALSE, mimes, n_mimes); - 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 @@ -677,7 +665,7 @@ _xdg_mime_cache_get_mime_type_for_file (const char *file_name, 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; @@ -693,7 +681,7 @@ _xdg_mime_cache_get_mime_type_for_file (const char *file_name, 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]; @@ -918,3 +906,107 @@ _xdg_mime_cache_list_mime_parents (const char *mime) 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 --git a/gio/xdgmime/xdgmimecache.h b/gio/xdgmime/xdgmimecache.h index 1cd978f..27f42d0 100644 --- a/gio/xdgmime/xdgmimecache.h +++ b/gio/xdgmime/xdgmimecache.h @@ -32,18 +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_get_max_buffer_extents XDG_ENTRY(cache_get_max_buffer_extents) -#define _xdg_mime_cache_get_mime_type_for_data XDG_ENTRY(cache_get_mime_type_for_data) -#define _xdg_mime_cache_get_mime_type_for_file XDG_ENTRY(cache_get_mime_type_for_file) -#define _xdg_mime_cache_get_mime_type_from_file_name XDG_ENTRY(cache_get_mime_type_from_file_name) -#define _xdg_mime_cache_get_mime_types_from_file_name XDG_ENTRY(cache_get_mime_types_from_file_name) -#define _xdg_mime_cache_list_mime_parents XDG_ENTRY(cache_list_mime_parents) -#define _xdg_mime_cache_mime_type_subclass XDG_ENTRY(cache_mime_type_subclass) -#define _xdg_mime_cache_unalias_mime_type XDG_ENTRY(cache_unalias_mime_type) - +#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; @@ -72,5 +74,8 @@ int _xdg_mime_cache_mime_type_subclass (const char *mime_a, 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 --git a/gio/xdgmime/xdgmimeglob.c b/gio/xdgmime/xdgmimeglob.c index 3aad611..4d786d0 100644 --- a/gio/xdgmime/xdgmimeglob.c +++ b/gio/xdgmime/xdgmimeglob.c @@ -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_list) 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_list, 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_list, 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 (XdgGlobHashNode *glob_hash_node, 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 (XdgGlobHashNode *glob_hash_node, } 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 (XdgGlobHashNode *glob_hash_node, } } - 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 (XdgGlobHashNode *glob_hash_node, 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 (XdgGlobHashNode *glob_hash_node, 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 (XdgGlobHashNode *glob_hash_node, 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 (XdgGlobHashNode *glob_hash_node, 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 (XdgGlobHashNode *glob_hash_node, 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 (XdgGlobHash *glob_hash, 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 (XdgGlobHash *glob_hash, } } - 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 *glob) 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 *glob) 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 *glob_hash, 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_hash) { 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 (XdgGlobHash *glob_hash, * 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 --git a/gio/xdgmime/xdgmimeglob.h b/gio/xdgmime/xdgmimeglob.h index 25a1f20..df8dc79 100644 --- a/gio/xdgmime/xdgmimeglob.h +++ b/gio/xdgmime/xdgmimeglob.h @@ -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_name (XdgGlobHash *glob_hash, 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 --git a/gio/xdgmime/xdgmimeicon.c b/gio/xdgmime/xdgmimeicon.c new file mode 100644 index 0000000..05c9473 --- /dev/null +++ b/gio/xdgmime/xdgmimeicon.c @@ -0,0 +1,183 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* xdgmimeicon.c: Private file. Datastructure for storing the aliases. + * + * More info can be found at http://www.freedesktop.org/standards/ + * + * Copyright (C) 2008 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.0 + * Or under the following terms: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "xdgmimeicon.h" +#include "xdgmimeint.h" +#include +#include +#include +#include +#include + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +typedef struct XdgIcon XdgIcon; + +struct XdgIcon +{ + char *mime_type; + char *icon_name; +}; + +struct XdgIconList +{ + struct XdgIcon *icons; + int n_icons; +}; + +XdgIconList * +_xdg_mime_icon_list_new (void) +{ + XdgIconList *list; + + list = malloc (sizeof (XdgIconList)); + + list->icons = NULL; + list->n_icons = 0; + + return list; +} + +void +_xdg_mime_icon_list_free (XdgIconList *list) +{ + int i; + + if (list->icons) + { + for (i = 0; i < list->n_icons; i++) + { + free (list->icons[i].mime_type); + free (list->icons[i].icon_name); + } + free (list->icons); + } + free (list); +} + +static int +icon_entry_cmp (const void *v1, const void *v2) +{ + return strcmp (((XdgIcon *)v1)->mime_type, ((XdgIcon *)v2)->mime_type); +} + +const char * +_xdg_mime_icon_list_lookup (XdgIconList *list, + const char *mime_type) +{ + XdgIcon *entry; + XdgIcon key; + + if (list->n_icons > 0) + { + key.mime_type = (char *)mime_type; + key.icon_name = NULL; + + entry = bsearch (&key, list->icons, list->n_icons, + sizeof (XdgIcon), icon_entry_cmp); + if (entry) + return entry->icon_name; + } + + return NULL; +} + +void +_xdg_mime_icon_read_from_file (XdgIconList *list, + const char *file_name) +{ + FILE *file; + char line[255]; + int alloc; + + file = fopen (file_name, "r"); + + if (file == NULL) + return; + + /* FIXME: Not UTF-8 safe. Doesn't work if lines are greater than 255 chars. + * Blah */ + alloc = list->n_icons + 16; + list->icons = realloc (list->icons, alloc * sizeof (XdgIcon)); + while (fgets (line, 255, file) != NULL) + { + char *sep; + if (line[0] == '#') + continue; + + sep = strchr (line, ':'); + if (sep == NULL) + continue; + *(sep++) = '\000'; + sep[strlen (sep) -1] = '\000'; + if (list->n_icons == alloc) + { + alloc <<= 1; + list->icons = realloc (list->icons, + alloc * sizeof (XdgIcon)); + } + list->icons[list->n_icons].mime_type = strdup (line); + list->icons[list->n_icons].icon_name = strdup (sep); + list->n_icons++; + } + list->icons = realloc (list->icons, + list->n_icons * sizeof (XdgIcon)); + + fclose (file); + + if (list->n_icons > 1) + qsort (list->icons, list->n_icons, + sizeof (XdgIcon), icon_entry_cmp); +} + + +void +_xdg_mime_icon_list_dump (XdgIconList *list) +{ + int i; + + if (list->icons) + { + for (i = 0; i < list->n_icons; i++) + { + printf ("%s %s\n", + list->icons[i].mime_type, + list->icons[i].icon_name); + } + } +} + + diff --git a/gio/xdgmime/xdgmimeicon.h b/gio/xdgmime/xdgmimeicon.h new file mode 100644 index 0000000..b5f2583 --- /dev/null +++ b/gio/xdgmime/xdgmimeicon.h @@ -0,0 +1,50 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* xdgmimeicon.h: Private file. Datastructure for storing the aliases. + * + * More info can be found at http://www.freedesktop.org/standards/ + * + * Copyright (C) 2008 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.0 + * Or under the following terms: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __XDG_MIME_ICON_H__ +#define __XDG_MIME_ICON_H__ + +#include "xdgmime.h" + +typedef struct XdgIconList XdgIconList; + +#ifdef XDG_PREFIX +#define _xdg_mime_icon_read_from_file XDG_ENTRY(icon_read_from_file) +#define _xdg_mime_icon_list_new XDG_ENTRY(icon_list_new) +#define _xdg_mime_icon_list_free XDG_ENTRY(icon_list_free) +#define _xdg_mime_icon_list_lookup XDG_ENTRY(icon_list_lookup) +#define _xdg_mime_icon_list_dump XDG_ENTRY(icon_list_dump) +#endif + +void _xdg_mime_icon_read_from_file (XdgIconList *list, + const char *file_name); +XdgIconList *_xdg_mime_icon_list_new (void); +void _xdg_mime_icon_list_free (XdgIconList *list); +const char *_xdg_mime_icon_list_lookup (XdgIconList *list, + const char *mime); +void _xdg_mime_icon_list_dump (XdgIconList *list); + +#endif /* __XDG_MIME_ICON_H__ */ diff --git a/gio/xdgmime/xdgmimeint.c b/gio/xdgmime/xdgmimeint.c index 4a0ac4c..d372d2c 100644 --- a/gio/xdgmime/xdgmimeint.c +++ b/gio/xdgmime/xdgmimeint.c @@ -152,3 +152,40 @@ _xdg_get_base_name (const char *file_name) 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 --git a/gio/xdgmime/xdgmimeint.h b/gio/xdgmime/xdgmimeint.h index 2881487..232c808 100644 --- a/gio/xdgmime/xdgmimeint.h +++ b/gio/xdgmime/xdgmimeint.h @@ -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 --git a/gio/xdgmime/xdgmimemagic.h b/gio/xdgmime/xdgmimemagic.h index 8f11305..35c8039 100644 --- a/gio/xdgmime/xdgmimemagic.h +++ b/gio/xdgmime/xdgmimemagic.h @@ -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 diff --git a/gio/xdgmime/xdgmimeparent.h b/gio/xdgmime/xdgmimeparent.h index 257ea04..b564f41 100644 --- a/gio/xdgmime/xdgmimeparent.h +++ b/gio/xdgmime/xdgmimeparent.h @@ -33,11 +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_list_dump XDG_ENTRY(parent_list_dump) +#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, -- 2.7.4