]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkiconcache.c
GtkWidget::draw() - Document how to get the dirty region
[~andy/gtk] / gtk / gtkiconcache.c
index 021b64c898ef4502501ab69db3ff858c112f9b27..7d8b3fc7395815f5020726ab1f4a46035f87e535 100644 (file)
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library 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.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "config.h"
 
 #include "gtkdebug.h"
 #include "gtkiconcache.h"
 #include "gtkiconcachevalidator.h"
-#include "gtkalias.h"
 
 #include <glib/gstdio.h>
 #include <gdk-pixbuf/gdk-pixdata.h>
 #define GET_UINT16(cache, offset) (GUINT16_FROM_BE (*(guint16 *)((cache) + (offset))))
 #define GET_UINT32(cache, offset) (GUINT32_FROM_BE (*(guint32 *)((cache) + (offset))))
 
+
 struct _GtkIconCache {
   gint ref_count;
 
   GMappedFile *map;
   gchar *buffer;
+
+  guint32 last_chain_offset;
 };
 
 GtkIconCache *
@@ -74,7 +74,7 @@ _gtk_icon_cache_unref (GtkIconCache *cache)
                g_print ("unmapping icon cache\n"));
 
       if (cache->map)
-       g_mapped_file_free (cache->map);
+       g_mapped_file_unref (cache->map);
       g_free (cache);
     }
 }
@@ -87,9 +87,8 @@ _gtk_icon_cache_new_for_path (const gchar *path)
 
   gchar *cache_filename;
   gint fd = -1;
-  struct stat st;
-  struct stat path_st;
-  CacheInfo info;
+  GStatBuf st;
+  GStatBuf path_st;
 
    /* Check if we have a cache file */
   cache_filename = g_build_filename (path, "icon-theme.cache", NULL);
@@ -105,7 +104,18 @@ _gtk_icon_cache_new_for_path (const gchar *path)
 
   if (fd < 0)
     goto done;
-  
+
+#ifdef G_OS_WIN32
+
+/* Bug 660730: _fstat32 is only defined in msvcrt80.dll+/VS 2005+ */
+/*             or possibly in the msvcrt.dll linked to by the Windows DDK */
+/*             (will need to check on the Windows DDK part later) */
+#if (_MSC_VER >= 1400 || __MSVCRT_VERSION__ >= 0x0800)
+#undef fstat /* Just in case */
+#define fstat _fstat32  
+#endif
+#endif
+
   if (fstat (fd, &st) < 0 || st.st_size < 4)
     goto done;
 
@@ -122,17 +132,19 @@ _gtk_icon_cache_new_for_path (const gchar *path)
   if (!map)
     goto done;
 
-  info.cache = g_mapped_file_get_contents (map);
-  info.cache_size = g_mapped_file_get_length (map);
-  info.n_directories = 0;
-  info.flags = CHECK_OFFSETS|CHECK_STRINGS;
-
 #ifdef G_ENABLE_DEBUG
-  if (gtk_debug_flags & GTK_DEBUG_ICONTHEME)
+  if (gtk_get_debug_flags () & GTK_DEBUG_ICONTHEME)
     {
+      CacheInfo info;
+
+      info.cache = g_mapped_file_get_contents (map);
+      info.cache_size = g_mapped_file_get_length (map);
+      info.n_directories = 0;
+      info.flags = CHECK_OFFSETS|CHECK_STRINGS;
+
       if (!_gtk_icon_cache_validate (&info))
         {
-          g_mapped_file_free (map);
+          g_mapped_file_unref (map);
           g_warning ("Icon cache '%s' is invalid\n", cache_filename);
 
           goto done;
@@ -191,11 +203,11 @@ get_directory_index (GtkIconCache *cache,
   return -1;
 }
 
-gboolean
-_gtk_icon_cache_has_directory (GtkIconCache *cache,
-                              const gchar *directory)
+gint
+_gtk_icon_cache_get_directory_index (GtkIconCache *cache,
+                                    const gchar *directory)
 {
-  return get_directory_index (cache, directory) != -1;
+  return get_directory_index (cache, directory);
 }
 
 static guint
@@ -214,19 +226,27 @@ icon_name_hash (gconstpointer key)
 static gint
 find_image_offset (GtkIconCache *cache,
                   const gchar  *icon_name,
-                  const gchar  *directory)
+                  gint          directory_index)
 {
   guint32 hash_offset;
   guint32 n_buckets;
   guint32 chain_offset;
-  int hash, directory_index;
+  int hash;
   guint32 image_list_offset, n_images;
-  gboolean found = FALSE;
   int i;
-  
+
+  chain_offset = cache->last_chain_offset;
+  if (chain_offset)
+    {
+      guint32 name_offset = GET_UINT32 (cache->buffer, chain_offset + 4);
+      gchar *name = cache->buffer + name_offset;
+
+      if (strcmp (name, icon_name) == 0)
+        goto find_dir;
+    }
+
   hash_offset = GET_UINT32 (cache->buffer, 4);
   n_buckets = GET_UINT32 (cache->buffer, hash_offset);
-
   hash = icon_name_hash (icon_name) % n_buckets;
 
   chain_offset = GET_UINT32 (cache->buffer, hash_offset + 4 + 4 * hash);
@@ -236,20 +256,19 @@ find_image_offset (GtkIconCache *cache,
       gchar *name = cache->buffer + name_offset;
 
       if (strcmp (name, icon_name) == 0)
-       {
-         found = TRUE;
-         break;
+        {
+          cache->last_chain_offset = chain_offset;
+          goto find_dir;
        }
-         
+  
       chain_offset = GET_UINT32 (cache->buffer, chain_offset);
     }
 
-  if (!found) {
-    return 0;
-  }
+  cache->last_chain_offset = 0;
+  return 0;
 
+find_dir:
   /* We've found an icon list, now check if we have the right icon in it */
-  directory_index = get_directory_index (cache, directory);
   image_list_offset = GET_UINT32 (cache->buffer, chain_offset + 8);
   n_images = GET_UINT32 (cache->buffer, image_list_offset);
   
@@ -266,11 +285,11 @@ find_image_offset (GtkIconCache *cache,
 gint
 _gtk_icon_cache_get_icon_flags (GtkIconCache *cache,
                                const gchar  *icon_name,
-                               const gchar  *directory)
+                               gint          directory_index)
 {
   guint32 image_offset;
 
-  image_offset = find_image_offset (cache, icon_name, directory);
+  image_offset = find_image_offset (cache, icon_name, directory_index);
 
   if (!image_offset)
     return 0;
@@ -417,7 +436,7 @@ pixbuf_destroy_cb (guchar   *pixels,
 GdkPixbuf *
 _gtk_icon_cache_get_icon (GtkIconCache *cache,
                          const gchar  *icon_name,
-                         const gchar  *directory)
+                         gint          directory_index)
 {
   guint32 offset, image_data_offset, pixel_data_offset;
   guint32 length, type;
@@ -425,8 +444,11 @@ _gtk_icon_cache_get_icon (GtkIconCache *cache,
   GdkPixdata pixdata;
   GError *error = NULL;
 
-  offset = find_image_offset (cache, icon_name, directory);
+  offset = find_image_offset (cache, icon_name, directory_index);
   
+  if (!offset)
+    return NULL;
+
   image_data_offset = GET_UINT32 (cache->buffer, offset + 4);
   
   if (!image_data_offset)
@@ -478,13 +500,13 @@ _gtk_icon_cache_get_icon (GtkIconCache *cache,
 GtkIconData  *
 _gtk_icon_cache_get_icon_data  (GtkIconCache *cache,
                                const gchar  *icon_name,
-                               const gchar  *directory)
+                               gint          directory_index)
 {
   guint32 offset, image_data_offset, meta_data_offset;
   GtkIconData *data;
   int i;
 
-  offset = find_image_offset (cache, icon_name, directory);
+  offset = find_image_offset (cache, icon_name, directory_index);
   if (!offset)
     return NULL;