changeset 2529:299be5908480 trunk

[svn] - made new INI file parser - removed old-style read_ini_string() function - made skin routines use new INI parser
author mf0102
date Thu, 15 Feb 2007 15:17:36 -0800
parents 60f2787cc7fd
children 7c6ce705adda
files ChangeLog src/audacious/build_stamp.c src/audacious/util.c src/audacious/util.h src/audacious/widgets/skin.c
diffstat 5 files changed, 314 insertions(+), 192 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Feb 15 02:03:34 2007 -0800
+++ b/ChangeLog	Thu Feb 15 15:17:36 2007 -0800
@@ -1,3 +1,11 @@
+2007-02-15 10:03:34 +0000  William Pitcock <nenolod@sacredspiral.co.uk>
+  revision [4066]
+  - playlist editor: use SkinnedWindow widgetlist
+  
+  trunk/src/audacious/ui_playlist.c |   44 +++++++++++++++++---------------------
+  1 file changed, 20 insertions(+), 24 deletions(-)
+
+
 2007-02-15 08:45:32 +0000  William Pitcock <nenolod@sacredspiral.co.uk>
   revision [4064]
   - playlist editor: use SkinnedWindow provided GC.
--- a/src/audacious/build_stamp.c	Thu Feb 15 02:03:34 2007 -0800
+++ b/src/audacious/build_stamp.c	Thu Feb 15 15:17:36 2007 -0800
@@ -1,2 +1,2 @@
 #include <glib.h>
-const gchar *svn_stamp = "20070215-4064";
+const gchar *svn_stamp = "20070215-4066";
--- a/src/audacious/util.c	Thu Feb 15 02:03:34 2007 -0800
+++ b/src/audacious/util.c	Thu Feb 15 15:17:36 2007 -0800
@@ -365,141 +365,234 @@
 
 #endif                          /* ifdef HAVE_FTS */
 
-gchar *
-read_ini_string(const gchar * filename, const gchar * section,
-                const gchar * key)
+static void
+strip_string(GString *string)
+{
+    while (string->len > 0 && string->str[0] == ' ')
+        g_string_erase(string, 0, 1);
+
+    while (string->len > 0 && string->str[string->len - 1] == ' ')
+        g_string_erase(string, string->len - 1, 1);
+}
+
+static void
+strip_lower_string(GString *string)
+{
+    strip_string(string);
+    
+    gchar *lower = g_ascii_strdown(string->str, -1);
+    g_free(string->str);
+    string->str = lower;
+}
+
+INIFile *
+open_ini_file(const gchar *filename)
 {
-    static gchar *buffer = NULL;
-    static gchar *open_buffer = NULL;
-    gchar *ret_buffer = NULL;
-    gint found_section = 0, len = 0;
-    static gsize filesize = 0;
+    GHashTable *ini_file = g_hash_table_new(NULL, NULL);
+    GHashTable *section = g_hash_table_new(NULL, NULL);
+    GString *section_name, *key_name, *value;
+    gpointer section_hash, key_hash;
+    gchar *buffer = NULL;
     gsize off = 0;
-    gchar *outbuf;
+    gsize filesize = 0;
+
     unsigned char x[] = { 0xff, 0xfe, 0x00 };
-    guint counter;
+
+
+    g_return_val_if_fail(filename, NULL);
+
+    section_name = g_string_new("");
+    key_name = g_string_new(NULL);
+    value = g_string_new(NULL);
 
-    if (!filename)
+    /* make a nameless section which should store all entries that are not
+     * embedded in a section */
+    section_hash = GINT_TO_POINTER(g_string_hash(section_name));
+    g_hash_table_insert(ini_file, section_hash, section);
+
+    vfs_file_get_contents(filename, &buffer, &filesize);
+    if (buffer == NULL)
         return NULL;
 
-    /*
-     * We optimise for the condition that we may be reading from the
-     * same ini-file multiple times. This is fairly common; it happens
-     * on .pls playlist loads. To do otherwise would take entirely too
-     * long, as fstat() can be very slow when done 21,000 times too many.
-     *
-     * Therefore, we optimise by keeping the last ini file in memory.
-     * Yes, this is a memory leak, but it is not too bad, hopefully.
-     *      - nenolod
-     */
-    if (open_buffer == NULL || strcasecmp(filename, open_buffer))
-    {
-        if (buffer != NULL)
-        {
-            g_free(buffer);
-            buffer = NULL;
-        }
-
-        if (open_buffer != NULL)
-        {
-            g_free(open_buffer);
-            open_buffer = NULL;
-        }
-
-        vfs_file_get_contents(filename, &buffer, &filesize);
-
-        if (buffer == NULL)
-            return NULL;
-
-        open_buffer = g_strdup(filename);
-    }
 
     /*
      * Convert UTF-16 into something useful. Original implementation
      * by incomp@#audacious. Cleanups \nenolod
+     * FIXME: can't we use a GLib function for that? -- 01mf02
      */
-    if (!memcmp(&buffer[0],&x,2)) {
-        outbuf = g_malloc (filesize);   /* it's safe to waste memory. */
+    if (!memcmp(&buffer[0],&x,2))
+    {
+        gchar *outbuf = g_malloc (filesize);   /* it's safe to waste memory. */
+        guint counter;
 
         for (counter = 2; counter < filesize; counter += 2)
+        {
             if (!memcmp(&buffer[counter+1], &x[2], 1))
                 outbuf[(counter-2)/2] = buffer[counter];
             else
-        return NULL;
+                return NULL;
+        }
 
         outbuf[(counter-2)/2] = '\0';
 
-        if ((filesize - 2) / 2 == (counter - 2) / 2) {
+        if ((filesize - 2) / 2 == (counter - 2) / 2)
+        {
             g_free(buffer);
             buffer = outbuf;
-        } else {
+        }
+        else
+        {
             g_free(outbuf);
-        return NULL;    /* XXX wrong encoding */
+            return NULL;    /* XXX wrong encoding */
         }
     }
 
-    while (!ret_buffer && off < filesize) {
-        while (off < filesize &&
-               (buffer[off] == '\r' || buffer[off] == '\n' ||
-                buffer[off] == ' ' || buffer[off] == '\t'))
+    while (off < filesize)
+    {
+        /* ignore the following characters */
+        if (buffer[off] == '\r' || buffer[off] == '\n' ||
+            buffer[off] == ' '  || buffer[off] == '\t')
+        {
+            if (buffer[off] == '\n')
+            {
+                g_string_free(key_name, TRUE);
+                g_string_free(value, FALSE);
+                key_name = g_string_new(NULL);
+                value = g_string_new(NULL);
+            }
+
+            off++;
+            continue;
+        }
+
+        /* if we encounter a possible section statement */
+        if (buffer[off] == '[')
+        {
+            g_string_free(section_name, TRUE);
+            section_name = g_string_new(NULL);
             off++;
-        if (off >= filesize)
-            break;
-        if (buffer[off] == '[') {
-            gint slen = strlen(section);
-            off++;
-            found_section = 0;
-            if (off + slen + 1 < filesize &&
-                !strncasecmp(section, &buffer[off], slen)) {
-                off += slen;
-                if (buffer[off] == ']') {
-                    off++;
-                    found_section = 1;
+
+            if (off >= filesize)
+                goto return_sequence;
+
+            while (buffer[off] != ']')
+            {
+                /* if the section statement has not been closed before a
+                 * linebreak */
+                if (buffer[off] == '\n')
+                    break;
+
+                g_string_append_c(section_name, buffer[off]);
+                off++;
+                if (off >= filesize)
+                    goto return_sequence;
+            }
+            if (buffer[off] == '\n')
+                continue;
+            if (buffer[off] == ']')
+            {
+                off++;
+                if (off >= filesize)
+                    goto return_sequence;
+
+                strip_lower_string(section_name);
+                section_hash = GINT_TO_POINTER(g_string_hash(section_name));
+
+                /* if this section already exists, we don't make a new one,
+                 * but reuse the old one */
+                if (g_hash_table_lookup(ini_file, section_hash) != NULL)
+                    section = g_hash_table_lookup(ini_file, section_hash);
+                else
+                {
+                    section = g_hash_table_new(NULL, NULL);
+                    g_hash_table_insert(ini_file, section_hash, section);
                 }
+
+                continue;
             }
         }
-        else if (found_section && off + strlen(key) < filesize &&
-                 !strncasecmp(key, &buffer[off], strlen(key))) {
-            off += strlen(key);
-            while (off < filesize &&
-                   (buffer[off] == ' ' || buffer[off] == '\t'))
-                off++;
+
+        if (buffer[off] == '=')
+        {
+            off++;
             if (off >= filesize)
-                break;
-            if (buffer[off] == '=') {
+                goto return_sequence;
+
+            while (buffer[off] != '\n')
+            {
+                g_string_append_c(value, buffer[off]);
                 off++;
-                while (off < filesize &&
-                       (buffer[off] == ' ' || buffer[off] == '\t'))
-                    off++;
                 if (off >= filesize)
                     break;
-                len = 0;
-                while (off + len < filesize &&
-                       buffer[off + len] != '\r' &&
-                       buffer[off + len] != '\n' && buffer[off + len] != ';')
-                    len++;
-                ret_buffer = g_strndup(&buffer[off], len);
-                off += len;
             }
+
+            strip_lower_string(key_name);
+            key_hash = GINT_TO_POINTER(g_string_hash(key_name));
+            strip_string(value);
+
+            if (key_name->len > 0 && value->len > 0)
+                g_hash_table_insert(section, key_hash, value->str);
         }
-        while (off < filesize && buffer[off] != '\r' && buffer[off] != '\n')
+        else
+        {
+            g_string_append_c(key_name, buffer[off]);
             off++;
+            if (off >= filesize)
+                goto return_sequence;
+        }
     }
 
-    return ret_buffer;
+return_sequence:
+    g_string_free(section_name, TRUE);
+    g_string_free(key_name, TRUE);
+    g_string_free(value, TRUE);
+    g_free(buffer);
+    return ini_file;
+}
+
+void
+close_ini_file(INIFile *inifile)
+{
+    g_return_if_fail(inifile);
+
+    /* we don't have to destroy anything in the hash table manually, as the
+     * keys are represented as integers and the string values may be used in
+     * functions which have read the strings from the hash table
+     */
+    g_hash_table_destroy(inifile);
+}
+
+gchar *
+read_ini_string(INIFile *inifile, const gchar *section, const gchar *key)
+{
+    g_return_val_if_fail(inifile, NULL);
+
+    GString *section_string = g_string_new(section);
+    GString *key_string = g_string_new(key);
+    gchar *value = NULL;
+
+    strip_lower_string(section_string);
+    strip_lower_string(key_string);
+    gpointer section_hash = GINT_TO_POINTER(g_string_hash(section_string));
+    gpointer key_hash = GINT_TO_POINTER(g_string_hash(key_string));
+    g_string_free(section_string, FALSE);
+    g_string_free(key_string, FALSE);
+
+    GHashTable *section_table = g_hash_table_lookup(inifile, section_hash);
+    g_return_val_if_fail(section_table, NULL);
+
+    value = g_hash_table_lookup(section_table, GINT_TO_POINTER(key_hash));
+    return value;
 }
 
 GArray *
-read_ini_array(const gchar * filename, const gchar * section,
-               const gchar * key)
+read_ini_array(INIFile *inifile, const gchar *section, const gchar *key)
 {
     gchar *temp;
     GArray *a;
 
-    if ((temp = read_ini_string(filename, section, key)) == NULL) {
-        g_free(temp);
-        return NULL;
-    }
+    g_return_val_if_fail((temp = read_ini_string(inifile, section, key)), NULL);
+
     a = string_to_garray(temp);
     g_free(temp);
     return a;
--- a/src/audacious/util.h	Thu Feb 15 02:03:34 2007 -0800
+++ b/src/audacious/util.h	Thu Feb 15 15:17:36 2007 -0800
@@ -37,6 +37,8 @@
 
 #define SWAP(a, b)      { a^=b; b^=a; a^=b; }
 
+typedef GHashTable INIFile;
+
 typedef gboolean(*DirForeachFunc) (const gchar * path,
                                    const gchar * basename,
                                    gpointer user_data);
@@ -47,10 +49,13 @@
 gboolean dir_foreach(const gchar * path, DirForeachFunc function,
                      gpointer user_data, GError ** error);
 
-gchar *read_ini_string(const gchar * filename, const gchar * section,
-                       const gchar * key);
-GArray *read_ini_array(const gchar * filename, const gchar * section,
-                       const gchar * key);
+
+INIFile *open_ini_file(const gchar *filename);
+void close_ini_file(INIFile *key_file);
+gchar *read_ini_string(INIFile *key_file, const gchar *section,
+					   const gchar *key);
+GArray *read_ini_array(INIFile *key_file, const gchar *section,
+                       const gchar *key);
 
 GArray *string_to_garray(const gchar * str);
 
--- a/src/audacious/widgets/skin.c	Thu Feb 15 02:03:34 2007 -0800
+++ b/src/audacious/widgets/skin.c	Thu Feb 15 15:17:36 2007 -0800
@@ -48,8 +48,8 @@
 
 #define EXTENSION_TARGETS 7
 
-static gchar *ext_targets[EXTENSION_TARGETS] = { "bmp", "xpm", "png", "svg", 
-	"gif", "jpg", "jpeg" };
+static gchar *ext_targets[EXTENSION_TARGETS] =
+{ "bmp", "xpm", "png", "svg", "gif", "jpg", "jpeg" };
 
 struct _SkinPixmapIdMapping {
     SkinPixmapId id;
@@ -149,7 +149,7 @@
 gboolean
 bmp_active_skin_reload(void) 
 {
-    return bmp_active_skin_load(bmp_active_skin->path);	
+    return bmp_active_skin_load(bmp_active_skin->path); 
 }
 
 gboolean
@@ -277,10 +277,10 @@
     gint i;
 
     for (i = 0; basenames[i]; i++)
-	if (!(filename = find_file_recursively(dirname, basenames[i]))) 
-            g_free(filename);
-        else
-            return filename;
+    if (!(filename = find_file_recursively(dirname, basenames[i]))) 
+        g_free(filename);
+    else
+        return filename;
 
     /* can't find any targets -- sorry */
     return NULL;
@@ -320,7 +320,7 @@
     g_object_unref(pixbuf);
 
     gdk_draw_pixbuf(pixmap, SKINNED_WINDOW(mainwin)->gc, pixbuf2, 0, 0, 0, 0, width, height,
-		    GDK_RGB_DITHER_MAX, 0, 0);
+                    GDK_RGB_DITHER_MAX, 0, 0);
     g_object_unref(pixbuf2);
 
     return pixmap;
@@ -348,12 +348,13 @@
 
     for (i = 0, y = 0; i < EXTENSION_TARGETS; i++, y++)
     {
-        basenames[y] = g_strdup_printf("%s.%s", pixmap_id_mapping->name,
-			ext_targets[i]);
+        basenames[y] =
+            g_strdup_printf("%s.%s", pixmap_id_mapping->name, ext_targets[i]);
 
         if (pixmap_id_mapping->alt_name)
-            basenames[++y] = g_strdup_printf("%s.%s", 
-			pixmap_id_mapping->alt_name, ext_targets[i]);
+            basenames[++y] =
+                g_strdup_printf("%s.%s", pixmap_id_mapping->alt_name,
+                                ext_targets[i]);
     }
 
     path = path_p ? path_p : skin->path;
@@ -536,13 +537,15 @@
 skin_parse_hints(Skin * skin, gchar *path_p)
 {
     gchar *filename, *tmp;
+    INIFile *inifile;
 
     path_p = path_p ? path_p : skin->path;
 
     filename = find_file_recursively(path_p, "skin.hints");
+    inifile = open_ini_file(filename);
 
     skin->properties.mainwin_othertext = FALSE;
-    tmp = read_ini_string(filename, "skin", "mainwinOthertext");
+    tmp = read_ini_string(inifile, "skin", "mainwinOthertext");
 
     if (tmp != NULL)
     {
@@ -551,7 +554,7 @@
     }
 
     skin->properties.mainwin_vis_x = 24;
-    tmp = read_ini_string(filename, "skin", "mainwinVisX");
+    tmp = read_ini_string(inifile, "skin", "mainwinVisX");
 
     if (tmp != NULL)
     {
@@ -560,7 +563,7 @@
     }
 
     skin->properties.mainwin_vis_y = 43;
-    tmp = read_ini_string(filename, "skin", "mainwinVisY");
+    tmp = read_ini_string(inifile, "skin", "mainwinVisY");
 
     if (tmp != NULL)
     {
@@ -569,7 +572,7 @@
     }
 
     skin->properties.mainwin_vis_width = 76;
-    tmp = read_ini_string(filename, "skin", "mainwinVisWidth");
+    tmp = read_ini_string(inifile, "skin", "mainwinVisWidth");
 
     if (tmp != NULL)
     {
@@ -578,7 +581,7 @@
     }
 
     skin->properties.mainwin_text_x = 112;
-    tmp = read_ini_string(filename, "skin", "mainwinTextX");
+    tmp = read_ini_string(inifile, "skin", "mainwinTextX");
 
     if (tmp != NULL)
     {
@@ -587,7 +590,7 @@
     }
 
     skin->properties.mainwin_text_y = 27;
-    tmp = read_ini_string(filename, "skin", "mainwinTextY");
+    tmp = read_ini_string(inifile, "skin", "mainwinTextY");
 
     if (tmp != NULL)
     {
@@ -596,7 +599,7 @@
     }
 
     skin->properties.mainwin_text_width = 153;
-    tmp = read_ini_string(filename, "skin", "mainwinTextWidth");
+    tmp = read_ini_string(inifile, "skin", "mainwinTextWidth");
 
     if (tmp != NULL)
     {
@@ -605,7 +608,7 @@
     }
 
     skin->properties.mainwin_infobar_x = 112;
-    tmp = read_ini_string(filename, "skin", "mainwinInfoBarX");
+    tmp = read_ini_string(inifile, "skin", "mainwinInfoBarX");
 
     if (tmp != NULL)
     {
@@ -614,7 +617,7 @@
     }
 
     skin->properties.mainwin_infobar_y = 43;
-    tmp = read_ini_string(filename, "skin", "mainwinInfoBarY");
+    tmp = read_ini_string(inifile, "skin", "mainwinInfoBarY");
 
     if (tmp != NULL)
     {
@@ -623,7 +626,7 @@
     }
 
     skin->properties.mainwin_number_0_x = 36;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber0X");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber0X");
 
     if (tmp != NULL)
     {
@@ -632,7 +635,7 @@
     }
 
     skin->properties.mainwin_number_0_y = 26;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber0Y");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber0Y");
 
     if (tmp != NULL)
     {
@@ -641,7 +644,7 @@
     }
 
     skin->properties.mainwin_number_1_x = 48;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber1X");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber1X");
 
     if (tmp != NULL)
     {
@@ -650,7 +653,7 @@
     }
 
     skin->properties.mainwin_number_1_y = 26;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber1Y");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber1Y");
 
     if (tmp != NULL)
     {
@@ -659,7 +662,7 @@
     }
 
     skin->properties.mainwin_number_2_x = 60;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber2X");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber2X");
 
     if (tmp != NULL)
     {
@@ -668,7 +671,7 @@
     }
 
     skin->properties.mainwin_number_2_y = 26;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber2Y");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber2Y");
 
     if (tmp != NULL)
     {
@@ -677,7 +680,7 @@
     }
 
     skin->properties.mainwin_number_3_x = 78;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber3X");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber3X");
 
     if (tmp != NULL)
     {
@@ -686,7 +689,7 @@
     }
 
     skin->properties.mainwin_number_3_y = 26;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber3Y");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber3Y");
 
     if (tmp != NULL)
     {
@@ -695,7 +698,7 @@
     }
 
     skin->properties.mainwin_number_4_x = 90;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber4X");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber4X");
 
     if (tmp != NULL)
     {
@@ -704,7 +707,7 @@
     }
 
     skin->properties.mainwin_number_4_y = 26;
-    tmp = read_ini_string(filename, "skin", "mainwinNumber4Y");
+    tmp = read_ini_string(inifile, "skin", "mainwinNumber4Y");
 
     if (tmp != NULL)
     {
@@ -713,7 +716,7 @@
     }
 
     skin->properties.mainwin_playstatus_x = 24;
-    tmp = read_ini_string(filename, "skin", "mainwinPlayStatusX");
+    tmp = read_ini_string(inifile, "skin", "mainwinPlayStatusX");
 
     if (tmp != NULL)
     {
@@ -722,7 +725,7 @@
     }
 
     skin->properties.mainwin_playstatus_y = 28;
-    tmp = read_ini_string(filename, "skin", "mainwinPlayStatusY");
+    tmp = read_ini_string(inifile, "skin", "mainwinPlayStatusY");
 
     if (tmp != NULL)
     {
@@ -731,7 +734,7 @@
     }
 
     skin->properties.mainwin_menurow_visible = TRUE;
-    tmp = read_ini_string(filename, "skin", "mainwinMenurowVisible");
+    tmp = read_ini_string(inifile, "skin", "mainwinMenurowVisible");
 
     if (tmp != NULL)
     {
@@ -740,7 +743,7 @@
     }
 
     skin->properties.mainwin_volume_x = 107;
-    tmp = read_ini_string(filename, "skin", "mainwinVolumeX");
+    tmp = read_ini_string(inifile, "skin", "mainwinVolumeX");
 
     if (tmp != NULL)
     {
@@ -749,7 +752,7 @@
     }
 
     skin->properties.mainwin_volume_y = 57;
-    tmp = read_ini_string(filename, "skin", "mainwinVolumeY");
+    tmp = read_ini_string(inifile, "skin", "mainwinVolumeY");
 
     if (tmp != NULL)
     {
@@ -758,7 +761,7 @@
     }
 
     skin->properties.mainwin_balance_x = 177;
-    tmp = read_ini_string(filename, "skin", "mainwinBalanceX");
+    tmp = read_ini_string(inifile, "skin", "mainwinBalanceX");
 
     if (tmp != NULL)
     {
@@ -767,7 +770,7 @@
     }
 
     skin->properties.mainwin_balance_y = 57;
-    tmp = read_ini_string(filename, "skin", "mainwinBalanceY");
+    tmp = read_ini_string(inifile, "skin", "mainwinBalanceY");
 
     if (tmp != NULL)
     {
@@ -776,7 +779,7 @@
     }
 
     skin->properties.mainwin_position_x = 16;
-    tmp = read_ini_string(filename, "skin", "mainwinPositionX");
+    tmp = read_ini_string(inifile, "skin", "mainwinPositionX");
 
     if (tmp != NULL)
     {
@@ -785,7 +788,7 @@
     }
 
     skin->properties.mainwin_position_y = 72;
-    tmp = read_ini_string(filename, "skin", "mainwinPositionY");
+    tmp = read_ini_string(inifile, "skin", "mainwinPositionY");
 
     if (tmp != NULL)
     {
@@ -794,7 +797,7 @@
     }
 
     skin->properties.mainwin_othertext_is_status = FALSE;
-    tmp = read_ini_string(filename, "skin", "mainwinOthertextIsStatus");
+    tmp = read_ini_string(inifile, "skin", "mainwinOthertextIsStatus");
 
     if (tmp != NULL)
     {
@@ -803,7 +806,7 @@
     }
 
     skin->properties.mainwin_othertext_visible = skin->properties.mainwin_othertext;
-    tmp = read_ini_string(filename, "skin", "mainwinOthertextVisible");
+    tmp = read_ini_string(inifile, "skin", "mainwinOthertextVisible");
 
     if (tmp != NULL)
     {
@@ -812,7 +815,7 @@
     }
 
     skin->properties.mainwin_text_visible = TRUE;
-    tmp = read_ini_string(filename, "skin", "mainwinTextVisible");
+    tmp = read_ini_string(inifile, "skin", "mainwinTextVisible");
 
     if (tmp != NULL)
     {
@@ -821,7 +824,7 @@
     }
 
     skin->properties.mainwin_vis_visible = TRUE;
-    tmp = read_ini_string(filename, "skin", "mainwinVisVisible");
+    tmp = read_ini_string(inifile, "skin", "mainwinVisVisible");
 
     if (tmp != NULL)
     {
@@ -830,7 +833,7 @@
     }
 
     skin->properties.mainwin_previous_x = 16;
-    tmp = read_ini_string(filename, "skin", "mainwinPreviousX");
+    tmp = read_ini_string(inifile, "skin", "mainwinPreviousX");
 
     if (tmp != NULL)
     {
@@ -839,7 +842,7 @@
     }
 
     skin->properties.mainwin_previous_y = 88;
-    tmp = read_ini_string(filename, "skin", "mainwinPreviousY");
+    tmp = read_ini_string(inifile, "skin", "mainwinPreviousY");
 
     if (tmp != NULL)
     {
@@ -848,7 +851,7 @@
     }
 
     skin->properties.mainwin_play_x = 39;
-    tmp = read_ini_string(filename, "skin", "mainwinPlayX");
+    tmp = read_ini_string(inifile, "skin", "mainwinPlayX");
 
     if (tmp != NULL)
     {
@@ -857,7 +860,7 @@
     }
 
     skin->properties.mainwin_play_y = 88;
-    tmp = read_ini_string(filename, "skin", "mainwinPlayY");
+    tmp = read_ini_string(inifile, "skin", "mainwinPlayY");
 
     if (tmp != NULL)
     {
@@ -866,7 +869,7 @@
     }
 
     skin->properties.mainwin_pause_x = 62;
-    tmp = read_ini_string(filename, "skin", "mainwinPauseX");
+    tmp = read_ini_string(inifile, "skin", "mainwinPauseX");
 
     if (tmp != NULL)
     {
@@ -875,7 +878,7 @@
     }
 
     skin->properties.mainwin_pause_y = 88;
-    tmp = read_ini_string(filename, "skin", "mainwinPauseY");
+    tmp = read_ini_string(inifile, "skin", "mainwinPauseY");
 
     if (tmp != NULL)
     {
@@ -884,7 +887,7 @@
     }
 
     skin->properties.mainwin_stop_x = 85;
-    tmp = read_ini_string(filename, "skin", "mainwinStopX");
+    tmp = read_ini_string(inifile, "skin", "mainwinStopX");
 
     if (tmp != NULL)
     {
@@ -893,7 +896,7 @@
     }
 
     skin->properties.mainwin_stop_y = 88;
-    tmp = read_ini_string(filename, "skin", "mainwinStopY");
+    tmp = read_ini_string(inifile, "skin", "mainwinStopY");
 
     if (tmp != NULL)
     {
@@ -902,7 +905,7 @@
     }
 
     skin->properties.mainwin_next_x = 108;
-    tmp = read_ini_string(filename, "skin", "mainwinNextX");
+    tmp = read_ini_string(inifile, "skin", "mainwinNextX");
 
     if (tmp != NULL)
     {
@@ -911,7 +914,7 @@
     }
 
     skin->properties.mainwin_next_y = 88;
-    tmp = read_ini_string(filename, "skin", "mainwinNextY");
+    tmp = read_ini_string(inifile, "skin", "mainwinNextY");
 
     if (tmp != NULL)
     {
@@ -920,7 +923,7 @@
     }
 
     skin->properties.mainwin_eject_x = 136;
-    tmp = read_ini_string(filename, "skin", "mainwinEjectX");
+    tmp = read_ini_string(inifile, "skin", "mainwinEjectX");
 
     if (tmp != NULL)
     {
@@ -929,7 +932,7 @@
     }
 
     skin->properties.mainwin_eject_y = 89;
-    tmp = read_ini_string(filename, "skin", "mainwinEjectY");
+    tmp = read_ini_string(inifile, "skin", "mainwinEjectY");
 
     if (tmp != NULL)
     {
@@ -938,7 +941,7 @@
     }
 
     skin->properties.mainwin_width = 275;
-    tmp = read_ini_string(filename, "skin", "mainwinWidth");
+    tmp = read_ini_string(inifile, "skin", "mainwinWidth");
 
     if (tmp != NULL)
     {
@@ -950,7 +953,7 @@
     skin_mask_info[0].width = skin->properties.mainwin_width;
 
     skin->properties.mainwin_height = 116;
-    tmp = read_ini_string(filename, "skin", "mainwinHeight");
+    tmp = read_ini_string(inifile, "skin", "mainwinHeight");
 
     if (tmp != NULL)
     {
@@ -962,7 +965,7 @@
     skin_mask_info[0].height = skin->properties.mainwin_height;
 
     skin->properties.mainwin_about_x = 247;
-    tmp = read_ini_string(filename, "skin", "mainwinAboutX");
+    tmp = read_ini_string(inifile, "skin", "mainwinAboutX");
 
     if (tmp != NULL)
     {
@@ -971,7 +974,7 @@
     }
 
     skin->properties.mainwin_about_y = 83;
-    tmp = read_ini_string(filename, "skin", "mainwinAboutY");
+    tmp = read_ini_string(inifile, "skin", "mainwinAboutY");
 
     if (tmp != NULL)
     {
@@ -980,7 +983,7 @@
     }
 
     skin->properties.mainwin_shuffle_x = 164;
-    tmp = read_ini_string(filename, "skin", "mainwinShuffleX");
+    tmp = read_ini_string(inifile, "skin", "mainwinShuffleX");
 
     if (tmp != NULL)
     {
@@ -989,7 +992,7 @@
     }
 
     skin->properties.mainwin_shuffle_y = 89;
-    tmp = read_ini_string(filename, "skin", "mainwinShuffleY");
+    tmp = read_ini_string(inifile, "skin", "mainwinShuffleY");
 
     if (tmp != NULL)
     {
@@ -998,7 +1001,7 @@
     }
 
     skin->properties.mainwin_repeat_x = 210;
-    tmp = read_ini_string(filename, "skin", "mainwinRepeatX");
+    tmp = read_ini_string(inifile, "skin", "mainwinRepeatX");
 
     if (tmp != NULL)
     {
@@ -1007,7 +1010,7 @@
     }
 
     skin->properties.mainwin_repeat_y = 89;
-    tmp = read_ini_string(filename, "skin", "mainwinRepeatY");
+    tmp = read_ini_string(inifile, "skin", "mainwinRepeatY");
 
     if (tmp != NULL)
     {
@@ -1016,7 +1019,7 @@
     }
 
     skin->properties.mainwin_eqbutton_x = 219;
-    tmp = read_ini_string(filename, "skin", "mainwinEQButtonX");
+    tmp = read_ini_string(inifile, "skin", "mainwinEQButtonX");
 
     if (tmp != NULL)
     {
@@ -1025,7 +1028,7 @@
     }
 
     skin->properties.mainwin_eqbutton_y = 58;
-    tmp = read_ini_string(filename, "skin", "mainwinEQButtonY");
+    tmp = read_ini_string(inifile, "skin", "mainwinEQButtonY");
 
     if (tmp != NULL)
     {
@@ -1034,7 +1037,7 @@
     }
 
     skin->properties.mainwin_plbutton_x = 242;
-    tmp = read_ini_string(filename, "skin", "mainwinPLButtonX");
+    tmp = read_ini_string(inifile, "skin", "mainwinPLButtonX");
 
     if (tmp != NULL)
     {
@@ -1043,7 +1046,7 @@
     }
 
     skin->properties.mainwin_plbutton_y = 58;
-    tmp = read_ini_string(filename, "skin", "mainwinPLButtonY");
+    tmp = read_ini_string(inifile, "skin", "mainwinPLButtonY");
 
     if (tmp != NULL)
     {
@@ -1052,7 +1055,7 @@
     }
 
     skin->properties.textbox_bitmap_font_width = 5;
-    tmp = read_ini_string(filename, "skin", "textboxBitmapFontWidth");
+    tmp = read_ini_string(inifile, "skin", "textboxBitmapFontWidth");
 
     if (tmp != NULL)
     {
@@ -1061,7 +1064,7 @@
     }
 
     skin->properties.textbox_bitmap_font_height = 6;
-    tmp = read_ini_string(filename, "skin", "textboxBitmapFontHeight");
+    tmp = read_ini_string(inifile, "skin", "textboxBitmapFontHeight");
 
     if (tmp != NULL)
     {
@@ -1070,7 +1073,7 @@
     }
 
     skin->properties.mainwin_minimize_x = 244;
-    tmp = read_ini_string(filename, "skin", "mainwinMinimizeX");
+    tmp = read_ini_string(inifile, "skin", "mainwinMinimizeX");
 
     if (tmp != NULL)
     {
@@ -1079,7 +1082,7 @@
     }
 
     skin->properties.mainwin_minimize_y = 3;
-    tmp = read_ini_string(filename, "skin", "mainwinMinimizeY");
+    tmp = read_ini_string(inifile, "skin", "mainwinMinimizeY");
 
     if (tmp != NULL)
     {
@@ -1088,7 +1091,7 @@
     }
 
     skin->properties.mainwin_shade_x = 254;
-    tmp = read_ini_string(filename, "skin", "mainwinShadeX");
+    tmp = read_ini_string(inifile, "skin", "mainwinShadeX");
 
     if (tmp != NULL)
     {
@@ -1097,7 +1100,7 @@
     }
 
     skin->properties.mainwin_shade_y = 3;
-    tmp = read_ini_string(filename, "skin", "mainwinShadeY");
+    tmp = read_ini_string(inifile, "skin", "mainwinShadeY");
 
     if (tmp != NULL)
     {
@@ -1106,7 +1109,7 @@
     }
 
     skin->properties.mainwin_close_x = 264;
-    tmp = read_ini_string(filename, "skin", "mainwinCloseX");
+    tmp = read_ini_string(inifile, "skin", "mainwinCloseX");
 
     if (tmp != NULL)
     {
@@ -1115,7 +1118,7 @@
     }
 
     skin->properties.mainwin_close_y = 3;
-    tmp = read_ini_string(filename, "skin", "mainwinCloseY");
+    tmp = read_ini_string(inifile, "skin", "mainwinCloseY");
 
     if (tmp != NULL)
     {
@@ -1125,6 +1128,8 @@
 
     if (filename != NULL)
         g_free(filename);
+
+    close_ini_file(inifile);
 }
 
 static guint
@@ -1143,18 +1148,17 @@
     return (CLAMP(strtol(str, NULL, 16), 0, 0xFF) << 8);
 }
 
-GdkColor *
-skin_load_color(const gchar * path, const gchar * file,
+static GdkColor *
+skin_load_color(INIFile *inifile,
                 const gchar * section, const gchar * key,
                 gchar * default_hex)
 {
-    gchar *filename, *value;
+    gchar *value;
     GdkColor *color = NULL;
 
-    filename = find_file_recursively(path, file);
-    if (filename || default_hex) {
-        if (filename) {
-            value = read_ini_string(filename, section, key);
+    if (inifile || default_hex) {
+        if (inifile) {
+            value = read_ini_string(inifile, section, key);
             if (value == NULL) {
                 value = g_strdup(default_hex);
             }
@@ -1190,8 +1194,6 @@
                             color, TRUE, TRUE);
             g_free(value);
         }
-        if (filename)
-            g_free(filename);
     }
     return color;
 }
@@ -1212,6 +1214,7 @@
     GdkPoint *gpoints;
 
     gchar *filename = NULL;
+    INIFile *inifile = NULL;
     gboolean created_mask = FALSE;
     GArray *num, *point;
     guint i, j;
@@ -1221,21 +1224,26 @@
         filename = find_file_recursively(path, file);
 
     /* filename will be null if path wasn't set */
-    if (!filename) {
+    if (!filename)
         return create_default_mask(window, width, height);
-    }
+
+    inifile = open_ini_file(filename);
 
-    if ((num = read_ini_array(filename, section, "NumPoints")) == NULL) {
+    if ((num = read_ini_array(inifile, section, "NumPoints")) == NULL) {
         g_free(filename);
+        close_ini_file(inifile);
         return NULL;
     }
 
-    if ((point = read_ini_array(filename, section, "PointList")) == NULL) {
+    if ((point = read_ini_array(inifile, section, "PointList")) == NULL) {
         g_array_free(num, TRUE);
         g_free(filename);
+        close_ini_file(inifile);
         return NULL;
     }
 
+    close_ini_file(inifile);
+
     mask = gdk_pixmap_new(window, width, height, 1);
     gc = gdk_gc_new(mask);
 
@@ -1359,8 +1367,8 @@
  
     filename = find_file_recursively(dirname, basename);
 
-    if (filename && cfg.custom_cursors)	{
-    	cursor_animated = gdk_pixbuf_animation_new_from_file(filename, &error);
+    if (filename && cfg.custom_cursors) {
+        cursor_animated = gdk_pixbuf_animation_new_from_file(filename, &error);
         cursor_pixbuf = gdk_pixbuf_animation_get_static_image(cursor_animated);
         cursor_gdk = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
                                                 cursor_pixbuf, 0, 0);
@@ -1393,14 +1401,21 @@
         skin_numbers_generate_dash(skin);
 #endif
 
+    gchar *filename = find_file_recursively(path, "pledit.txt");
+    INIFile *inifile = open_ini_file(filename);
+
     skin->colors[SKIN_PLEDIT_NORMAL] =
-        skin_load_color(path, "pledit.txt", "text", "normal", "#2499ff");
+        skin_load_color(inifile, "Text", "Normal", "#2499ff");
     skin->colors[SKIN_PLEDIT_CURRENT] =
-        skin_load_color(path, "pledit.txt", "text", "current", "#ffeeff");
+        skin_load_color(inifile, "Text", "Current", "#ffeeff");
     skin->colors[SKIN_PLEDIT_NORMALBG] =
-        skin_load_color(path, "pledit.txt", "text", "normalbg", "#0a120a");
+        skin_load_color(inifile, "Text", "NormalBG", "#0a120a");
     skin->colors[SKIN_PLEDIT_SELECTEDBG] =
-        skin_load_color(path, "pledit.txt", "text", "selectedbg", "#0a124a");
+        skin_load_color(inifile, "Text", "SelectedBG", "#0a124a");
+
+    if (filename)
+        g_free(filename);
+    close_ini_file(inifile);
 
     skin_mask_create(skin, path, SKIN_MASK_MAIN, mainwin->window);
     skin_mask_create(skin, path, SKIN_MASK_MAIN_SHADE, mainwin->window);
@@ -1421,7 +1436,7 @@
     REQUIRE_LOCK(skin->lock);
 
     if (!g_file_test(path, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_DIR))
-	return FALSE;
+        return FALSE;
    
     if (!force) {
         if (skin->path)
@@ -1467,7 +1482,8 @@
 
     g_return_if_fail(path != NULL);
 
-    command = g_strdup_printf("cp %s %s", path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
+    command = g_strdup_printf("cp %s %s",
+                              path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
     if (system(command)) {
         g_message("Unable to install skin (%s) into user directory (%s)",
                   path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);