glib r6975 - in trunk/gio: . xdgmime



Author: matthiasc
Date: Mon Jun  9 16:45:19 2008
New Revision: 6975
URL: http://svn.gnome.org/viewvc/glib?rev=6975&view=rev

Log:
Sync with upstream


Added:
   trunk/gio/xdgmime/xdgmimeicon.c
   trunk/gio/xdgmime/xdgmimeicon.h
Modified:
   trunk/gio/ChangeLog
   trunk/gio/xdgmime/test-mime.c
   trunk/gio/xdgmime/xdgmime.c
   trunk/gio/xdgmime/xdgmime.h
   trunk/gio/xdgmime/xdgmimealias.h
   trunk/gio/xdgmime/xdgmimecache.c
   trunk/gio/xdgmime/xdgmimecache.h
   trunk/gio/xdgmime/xdgmimeglob.c
   trunk/gio/xdgmime/xdgmimeglob.h
   trunk/gio/xdgmime/xdgmimeint.c
   trunk/gio/xdgmime/xdgmimeint.h
   trunk/gio/xdgmime/xdgmimemagic.h
   trunk/gio/xdgmime/xdgmimeparent.h

Modified: trunk/gio/xdgmime/test-mime.c
==============================================================================
--- trunk/gio/xdgmime/test-mime.c	(original)
+++ trunk/gio/xdgmime/test-mime.c	Mon Jun  9 16:45:19 2008
@@ -113,7 +113,59 @@
   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 @@
   test_glob_type ();
   test_aliasing ();
   test_subclassing ();
+  test_matches ();
+  test_icons ();
 
   for (i = 1; i < argc; i++)
     {

Modified: trunk/gio/xdgmime/xdgmime.c
==============================================================================
--- trunk/gio/xdgmime/xdgmime.c	(original)
+++ trunk/gio/xdgmime/xdgmime.c	Mon Jun  9 16:45:19 2008
@@ -34,6 +34,7 @@
 #include "xdgmimeglob.h"
 #include "xdgmimemagic.h"
 #include "xdgmimealias.h"
+#include "xdgmimeicon.h"
 #include "xdgmimeparent.h"
 #include "xdgmimecache.h"
 #include <stdio.h>
@@ -56,6 +57,8 @@
 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 @@
     }
   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 @@
   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_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 @@
       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 @@
 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 @@
 	}
     }
 }
+
+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);
+}

Modified: trunk/gio/xdgmime/xdgmime.h
==============================================================================
--- trunk/gio/xdgmime/xdgmime.h	(original)
+++ trunk/gio/xdgmime/xdgmime.h	Mon Jun  9 16:45:19 2008
@@ -40,6 +40,10 @@
 #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 @@
 #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 @@
 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);

Modified: trunk/gio/xdgmime/xdgmimealias.h
==============================================================================
--- trunk/gio/xdgmime/xdgmimealias.h	(original)
+++ trunk/gio/xdgmime/xdgmimealias.h	Mon Jun  9 16:45:19 2008
@@ -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,

Modified: trunk/gio/xdgmime/xdgmimecache.c
==============================================================================
--- trunk/gio/xdgmime/xdgmimecache.c	(original)
+++ trunk/gio/xdgmime/xdgmimecache.c	Mon Jun  9 16:45:19 2008
@@ -41,6 +41,8 @@
 
 #ifdef HAVE_MMAP
 #include <sys/mman.h>
+#else
+#warning Building xdgmime without MMAP support. Binary "mime.info" cache files will not be used.
 #endif
 
 #include <sys/stat.h>
@@ -70,7 +72,7 @@
 #endif
 
 #define MAJOR_VERSION 1
-#define MINOR_VERSION 0
+#define MINOR_VERSION 1
 
 struct _XdgMimeCache
 {
@@ -344,6 +346,11 @@
   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 @@
 	{
 	  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 @@
 	    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 @@
 
 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 @@
 
       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 @@
 }
 
 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 @@
 
       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 @@
   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 @@
 			     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 @@
 					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 @@
     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 @@
   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);
+  }
+}
+
+

Modified: trunk/gio/xdgmime/xdgmimecache.h
==============================================================================
--- trunk/gio/xdgmime/xdgmimecache.h	(original)
+++ trunk/gio/xdgmime/xdgmimecache.h	Mon Jun  9 16:45:19 2008
@@ -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 @@
 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__ */

Modified: trunk/gio/xdgmime/xdgmimeglob.c
==============================================================================
--- trunk/gio/xdgmime/xdgmimeglob.c	(original)
+++ trunk/gio/xdgmime/xdgmimeglob.c	Mon Jun  9 16:45:19 2008
@@ -52,6 +52,7 @@
 {
   xdg_unichar_t character;
   const char *mime_type;
+  int weight;
   XdgGlobHashNode *next;
   XdgGlobHashNode *child;
 };
@@ -59,6 +60,7 @@
 {
   const char *data;
   const char *mime_type;
+  int weight;
   XdgGlobList *next;
 };
 
@@ -107,7 +109,8 @@
 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 @@
   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 @@
   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 @@
 
   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 @@
 }
 
 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 @@
 	}
     }
 
-  text = _xdg_utf8_next_char (text);
-  if (*text == '\000')
+  text++;
+  if (*text == 0)
     {
       if (node->mime_type)
 	{
@@ -249,7 +237,7 @@
 	      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 @@
 	      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 @@
       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 @@
   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 @@
   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 @@
 				 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 @@
 	}
     }
 
-  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 @@
 
   ptr = glob;
 
-  while (*ptr != '\000')
+  while (*ptr != '\0')
     {
       if (*ptr == '*' && first_char)
 	maybe_in_simple_glob = TRUE;
@@ -462,7 +494,8 @@
 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 @@
   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 @@
 {
   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 @@
    * 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);

Modified: trunk/gio/xdgmime/xdgmimeglob.h
==============================================================================
--- trunk/gio/xdgmime/xdgmimeglob.h	(original)
+++ trunk/gio/xdgmime/xdgmimeglob.h	Mon Jun  9 16:45:19 2008
@@ -41,13 +41,13 @@
 
   
 #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          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);
 

Added: trunk/gio/xdgmime/xdgmimeicon.c
==============================================================================
--- (empty file)
+++ trunk/gio/xdgmime/xdgmimeicon.c	Mon Jun  9 16:45:19 2008
@@ -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 <config.h>
+#endif
+
+#include "xdgmimeicon.h"
+#include "xdgmimeint.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <fnmatch.h>
+
+#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);
+	}
+    }
+}
+
+

Added: trunk/gio/xdgmime/xdgmimeicon.h
==============================================================================
--- (empty file)
+++ trunk/gio/xdgmime/xdgmimeicon.h	Mon Jun  9 16:45:19 2008
@@ -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__ */

Modified: trunk/gio/xdgmime/xdgmimeint.c
==============================================================================
--- trunk/gio/xdgmime/xdgmimeint.c	(original)
+++ trunk/gio/xdgmime/xdgmimeint.c	Mon Jun  9 16:45:19 2008
@@ -152,3 +152,40 @@
   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;
+    }
+}
+

Modified: trunk/gio/xdgmime/xdgmimeint.h
==============================================================================
--- trunk/gio/xdgmime/xdgmimeint.h	(original)
+++ trunk/gio/xdgmime/xdgmimeint.h	Mon Jun  9 16:45:19 2008
@@ -46,11 +46,13 @@
 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 @@
 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__ */

Modified: trunk/gio/xdgmime/xdgmimemagic.h
==============================================================================
--- trunk/gio/xdgmime/xdgmimemagic.h	(original)
+++ trunk/gio/xdgmime/xdgmimemagic.h	Mon Jun  9 16:45:19 2008
@@ -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
 
 

Modified: trunk/gio/xdgmime/xdgmimeparent.h
==============================================================================
--- trunk/gio/xdgmime/xdgmimeparent.h	(original)
+++ trunk/gio/xdgmime/xdgmimeparent.h	Mon Jun  9 16:45:19 2008
@@ -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,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]