Commits

jjacky committed fd7381b

first commit. i need to start using vcs much sooner.

Comments (0)

Files changed (41)

+
+.PHONY = all kalu kalu-dbus doc install uninstall clean
+
+WARNINGS := -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align \
+			-Wwrite-strings -Wmissing-prototypes -Wmissing-declarations \
+			-Wredundant-decls -Wnested-externs -Winline -Wno-long-long \
+			-Wuninitialized -Wconversion -Wstrict-prototypes
+CFLAGS := -g -std=c99 $(WARNINGS) -imacros configure.h
+
+PROGRAMS = kalu kalu-dbus
+DOCS = kalu.1.gz
+
+SRCFILES =	main.c alpm.c config.c util.c watched.c util-gtk.c kalu-updater.c \
+			updater.c closures.c cJSON.c aur.c curl.c news.c
+
+HDRFILES =	alpm.h config.h util.h kalu.h watched.h util-gtk.h kalu-updater.h \
+			updater.h closures.h updater-dbus.h kupdater.h cJSON.h aur.h \
+			curl.h news.h arch_linux.h
+
+OBJFILES =	main.o alpm.o config.o util.o watched.o util-gtk.o kalu-updater.o \
+			updater.o closures.o cJSON.o aur.o curl.o news.o
+
+DBUSSRCFILES = kalu-dbus.c
+DBUSOBJFILES = kalu-dbus.o
+
+MANFILES = kalu.1
+
+#all: $(PROGRAMS) $(DOCS)
+all: $(PROGRAMS)
+
+kalu: $(OBJFILES)
+	$(CC) -o kalu $(OBJFILES) `pkg-config --libs gtk+-3.0 libnotify` `curl-config --libs` -lalpm -lm
+
+main.o:	main.c arch_linux.h alpm.h config.h util.h kalu.h updater.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags gtk+-3.0 libnotify` -lalpm main.c
+
+alpm.o: alpm.c alpm.h config.h util.h kalu.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags glib-2.0` alpm.c
+
+config.o: config.c alpm.h config.h util.h kalu.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags glib-2.0` config.c
+
+util.o: util.c alpm.h util.h kalu.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags glib-2.0` util.c
+
+watched.o: watched.c alpm.h watched.h kalu.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags gtk+-3.0` watched.c
+
+util-gtk.o: util-gtk.c kalu.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags gtk+-3.0 libnotify` util-gtk.c
+
+kalu-updater.o:	kalu-updater.c kalu-updater.h kalu.h updater-dbus.h kupdater.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags glib-2.0` kalu-updater.c
+
+updater.o:	updater.c updater.h kalu.h kupdater.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags gtk+-3.0` updater.c
+
+closures.o:	closures.c closures.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags glib-2.0` closures.c
+
+cJSON.o:	cJSON.c cJSON.h
+	$(CC) -c $(CFLAGS) cJSON.c
+
+aur.o:	aur.c aur.h kalu.h curl.h cJSON.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags glib-2.0` aur.c
+
+curl.o:	curl.c curl.h kalu.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags glib-2.0` `curl-config --cflags` curl.c
+
+news.o:	news.c news.h kalu.h curl.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags gtk+-3.0` news.c
+
+kalu-dbus: $(DBUSOBJFILES)
+	$(CC) -o kalu-dbus $(DBUSOBJFILES) `pkg-config --libs glib-2.0 polkit-gobject-1` -lalpm
+
+kalu-dbus.o: kalu-dbus.c updater-dbus.h kupdater.h
+	$(CC) -c $(CFLAGS) `pkg-config --cflags glib-2.0 polkit-gobject-1` kalu-dbus.c
+
+doc: $(DOCS)
+
+kalu.1.gz: $(MANFILES)
+	gzip -c kalu.1 > kalu.1.gz
+
+index.html:
+	groff -T html -man kalu.1 > index.html
+
+install:
+	install -D -m755 kalu $(DESTDIR)/usr/bin/kalu
+	install -D -m755 kalu-dbus $(DESTDIR)/usr/bin/kalu-dbus
+#	install -D -m644 kalu.1.gz $(DESTDIR)/usr/share/man/man1/kalu.1.gz
+#	install -D -m644 index.html $(DESTDIR)usr/share/doc/kalu/html/index.html
+	install -D -m644 arch_linux_48x48_icon_by_painlessrob.png $(DESTDIR)usr/share/pixmaps/kalu.png
+	install -D -m644 org.jjk.kalu.policy $(DESTDIR)usr/share/polkit-1/actions/org.jjk.kalu.policy
+	install -D -m644 org.jjk.kalu.service $(DESTDIR)usr/share/dbus-1/system-services/org.jjk.kalu.service
+	install -D -m644 org.jjk.kalu.conf $(DESTDIR)etc/dbus-1/system.d/org.jjk.kalu.conf
+	install -D -m644 kalu.desktop $(DESTDIR)usr/share/applications/kalu.desktop
+
+uninstall:
+	rm -f $(DESTDIR)/usr/bin/kalu
+	rm -f $(DESTDIR)/usr/bin/kalu-dbus
+	rm -f $(DESTDIR)/usr/share/man/man1/kalu.1.gz
+	rm -rf $(DESTDIR)usr/share/doc/kalu
+	rm -f $(DESTDIR)usr/share/pixmaps/kalu.png
+	rm -f $(DESTDIR)usr/share/polkit-1/actions/org.jjk.kalu.policy
+	rm -f $(DESTDIR)usr/share/dbus-1/system-services/org.jjk.kalu.service
+	rm -f $(DESTDIR)etc/dbus-1/system.d/org.jjk.kalu.conf
+	rm -f $(DESTDIR)usr/share/applications/kalu.desktop
+
+clean:
+	rm -f $(PROGRAMS)
+	rm -f $(OBJFILES)
+	rm -f $(DOCS)
+
+#define _BSD_SOURCE /* for strdup w/ -std=c99 */
+
+/* C */
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <utime.h>
+
+/* alpm */
+#include <alpm.h>
+#include <alpm_list.h>
+
+/* glib */
+#include <glib-2.0/glib.h>
+
+/* kalu */
+#include "kalu.h"
+#include "alpm.h"
+#include "util.h"
+#include "config.h"
+
+/* global variable */
+unsigned short alpm_verbose;
+
+
+static kalu_alpm_t *alpm;
+
+static gboolean copy_file (const gchar *from, const gchar *to);
+static gboolean create_local_db (const gchar *dbpath, gchar **newpath, GError **error);
+
+
+
+static gboolean
+copy_file (const gchar *from, const gchar *to)
+{
+    gchar *contents;
+    gsize  length;
+    
+    debug ("copying %s to %s", from, to);
+    
+    if (!g_file_get_contents (from, &contents, &length, NULL))
+    {
+        debug ("cannot read %s", from);
+        return FALSE;
+    }
+    
+    if (!g_file_set_contents (to, contents, (gssize) length, NULL))
+    {
+        debug ("cannot write %s", to);
+        g_free (contents);
+        return FALSE;
+    }
+    
+    debug ("..done");
+    g_free (contents);
+    return TRUE;
+}
+
+static gboolean
+create_local_db (const gchar *dbpath, gchar **newpath, GError **error)
+{
+    gchar    buf[MAX_PATH];
+    gchar    buf2[MAX_PATH];
+    gchar   *folder;
+    GDir    *dir;
+    
+    debug ("creating local db");
+    
+    /* create folder in tmp dir */
+    if (NULL == (folder = g_dir_make_tmp ("kalu-XXXXXX", NULL)))
+    {
+        g_set_error (error, KALU_ERROR, 1, "Unable to create temp folder");
+        return FALSE;
+    }
+    debug ("created tmp folder %s", folder);
+    
+    /* symlink local */
+    snprintf (buf, MAX_PATH - 1, "%s/local", dbpath);
+    snprintf (buf2, MAX_PATH - 1, "%s/local", folder);
+    if (0 != symlink (buf, buf2))
+    {
+        g_set_error (error, KALU_ERROR, 1, "Unable to create symlink %s", buf2);
+        goto error;
+    }
+    debug ("created symlink %s", buf2);
+    
+    /* copy databases in sync */
+    snprintf (buf, MAX_PATH - 1, "%s/sync", folder);
+    if (0 != mkdir (buf, 0700))
+    {
+        g_set_error (error, KALU_ERROR, 1, "Unable to create folder %s", buf);
+        goto error;
+    }
+    debug ("created folder %s", buf);
+    
+    snprintf (buf, MAX_PATH - 1, "%s/sync", dbpath);
+    if (NULL == (dir = g_dir_open (buf, 0, NULL)))
+    {
+        g_set_error (error, KALU_ERROR, 1, "Unable to open folder %s", buf);
+        goto error;
+    }
+    
+    const gchar    *file;
+    struct stat     filestat;
+    struct utimbuf  times;
+    
+    while ((file = g_dir_read_name (dir)))
+    {
+        snprintf (buf, MAX_PATH - 1, "%s/sync/%s", dbpath, file);
+        snprintf (buf2, MAX_PATH - 1, "%s/sync/%s", folder, file);
+        if (!copy_file (buf, buf2))
+        {
+            g_set_error (error, KALU_ERROR, 1, "Copy failed for %s", buf);
+            g_dir_close (dir);
+            goto error;
+        }
+        /* we need to preserve modified date, used to determine if DBs are
+         * up to date or not by libalpm */
+        if (0 != stat (buf, &filestat))
+        {
+            g_set_error (error, KALU_ERROR, 1, "Unable to stat %s\n", buf);
+            g_dir_close (dir);
+            goto error;
+        }
+        else
+        {
+            times.actime = filestat.st_atime;
+            times.modtime = filestat.st_mtime;
+            if (0 != utime (buf2, &times))
+            {
+                /* sucks, but no fail, we'll just have to download this db */
+                debug ("Unable to change time of %s", buf2);
+            }
+            else
+            {
+                debug ("updated time for %s", buf2);
+            }
+        }
+    }
+    g_dir_close (dir);
+    
+    *newpath = folder;
+    return TRUE;
+
+error:
+    g_free (folder);
+    return FALSE;
+}
+
+gboolean
+kalu_alpm_load (const gchar *conffile, GError **error)
+{
+    GError             *local_err = NULL;
+    gchar              *newpath;
+    enum _alpm_errno_t  err;
+    pacman_config_t    *pac_conf = NULL;
+    
+    /* parse pacman.conf */
+    debug ("parsing pacman.conf (%s) for options", conffile);
+    if (!parse_pacman_conf (conffile, NULL, 0, 0, &pac_conf, &local_err))
+    {
+        g_propagate_error (error, local_err);
+        free_pacman_config (pac_conf);
+        return FALSE;
+    }
+    
+    debug ("setting up libalpm");
+    if (NULL == (alpm = calloc (1, sizeof (*alpm))))
+    {
+        g_set_error (error, KALU_ERROR, 1, "Unable to allocate memory");
+        free_pacman_config (pac_conf);
+        return FALSE;
+    }
+    
+    /* create tmp copy of db (so we can sync w/out being root) */
+    if (!create_local_db (pac_conf->dbpath, &newpath, &local_err))
+    {
+        g_set_error (error, KALU_ERROR, 1, "Unable to create local copy of database: %s",
+            local_err->message);
+        g_clear_error (&local_err);
+        free_pacman_config (pac_conf);
+        kalu_alpm_free ();
+        return FALSE;
+    }
+    alpm->dbpath = newpath;
+    
+    /* init libalpm */
+    alpm->handle = alpm_initialize (pac_conf->rootdir, alpm->dbpath, &err);
+    if (alpm->handle == NULL)
+    {
+        g_set_error (error, KALU_ERROR, 1, "Failed to initialize alpm library: %s",
+            alpm_strerror (err));
+        free_pacman_config (pac_conf);
+        kalu_alpm_free ();
+        return FALSE;
+    }
+    
+    /* set arch & some options (what to ignore during update) */
+    alpm_option_set_arch (alpm->handle, pac_conf->arch);
+    alpm_option_set_ignorepkgs (alpm->handle, pac_conf->ignorepkgs);
+    alpm_option_set_ignoregroups (alpm->handle, pac_conf->ignoregroups);
+    
+    /* now we need to add dbs */
+    alpm_list_t *i;
+    for (i = pac_conf->databases; i; i = alpm_list_next (i))
+    {
+        database_t *db_conf = i->data;
+        alpm_db_t *db;
+        
+        /* register db */
+        debug ("register %s", db_conf->name);
+        db = alpm_db_register_sync (alpm->handle, db_conf->name, db_conf->siglevel);
+        if (db == NULL)
+        {
+            g_set_error (error, KALU_ERROR, 1, "Could not register database %s: %s",
+                db_conf->name, alpm_strerror (alpm_errno (alpm->handle)));
+            free_pacman_config (pac_conf);
+            kalu_alpm_free ();
+            return FALSE;
+        }
+        
+        /* add servers */
+        alpm_list_t *j;
+        for (j = db_conf->servers; j; j = alpm_list_next (j))
+        {
+            char *value = j->data;
+            const char *dbname = alpm_db_get_name (db);
+            /* let's attempt a replacement for the current repo */
+            char *temp = strreplace (value, "$repo", dbname);
+            /* let's attempt a replacement for the arch */
+            const char *arch = pac_conf->arch;
+            char *server;
+            
+            if (arch)
+            {
+                server = strreplace (temp, "$arch", arch);
+                free (temp);
+            }
+            else
+            {
+                if (strstr (temp, "$arch"))
+                {
+                    g_set_error (error, KALU_ERROR, 1, "Server %s contains the $arch variable, "
+                        "but no Architecture was defined", value);
+                    free (temp);
+                    free (value);
+                    free_pacman_config (pac_conf);
+                    kalu_alpm_free ();
+                    return FALSE;
+                }
+                server = temp;
+            }
+            
+            debug ("add server %s into %s", server, dbname);
+            if (alpm_db_add_server (db, server) != 0)
+            {
+                /* pm_errno is set by alpm_db_setserver */
+                g_set_error (error, KALU_ERROR, 1, "Could not add server %s to database %s: %s",
+                    server, dbname, alpm_strerror (alpm_errno (alpm->handle)));
+                free (server);
+                free (value);
+                free_pacman_config (pac_conf);
+                kalu_alpm_free ();
+                return FALSE;
+            }
+            
+            free (server);
+        }
+    }
+    
+    /* set global var */
+    alpm_verbose = pac_conf->verbosepkglists;
+    
+    free_pacman_config (pac_conf);
+    return TRUE;
+}
+
+gboolean
+kalu_alpm_syncdbs (GError **error)
+{
+    alpm_list_t     *sync_dbs   = NULL;
+    alpm_list_t     *i;
+    GError          *local_err  = NULL;
+    int             ret;
+    
+    if (!check_syncdbs (alpm, 1, 0, &local_err))
+    {
+        g_propagate_error (error, local_err);
+		return FALSE;
+	}
+    
+    sync_dbs = alpm_option_get_syncdbs (alpm->handle);
+    for (i = sync_dbs; i; i = alpm_list_next (i))
+    {
+		alpm_db_t *db = i->data;
+
+		ret = alpm_db_update (0, db);
+		if (ret < 0)
+        {
+            g_set_error (error, KALU_ERROR, 1, "Failed to update %s: %s",
+                alpm_db_get_name (db), alpm_strerror (alpm_errno (alpm->handle)));
+            return FALSE;
+		}
+        else if (ret == 1)
+        {
+			debug ("%s is up to date", alpm_db_get_name (db));
+		}
+        else
+        {
+            debug ("%s was updated", alpm_db_get_name (db));
+		}
+	}
+    
+    return TRUE;
+}
+
+gboolean
+kalu_alpm_has_updates (alpm_list_t **packages, GError **error)
+{
+    alpm_list_t *i;
+    alpm_list_t *data       = NULL;
+    GError      *local_err  = NULL;
+    
+    if (!check_syncdbs (alpm, 1, 1, &local_err))
+    {
+        g_propagate_error (error, local_err);
+		return FALSE;
+	}
+    
+    if (!trans_init (alpm, alpm->flags, 1, &local_err) == -1)
+    {
+        g_propagate_error (error, local_err);
+		return FALSE;
+	}
+    
+    if (alpm_sync_sysupgrade (alpm->handle, 0) == -1)
+    {
+        g_set_error (error, KALU_ERROR, 1, "%s", alpm_strerror (alpm_errno (alpm->handle)));
+        goto cleanup;
+    }
+    
+    if (alpm_trans_prepare (alpm->handle, &data) == -1)
+    {
+        int len = 1024;
+        gchar buf[255], err[len--];
+        err[0] = '\0';
+		switch (alpm_errno (alpm->handle))
+        {
+			case ALPM_ERR_PKG_INVALID_ARCH:
+				for (i = data; i; i = alpm_list_next (i))
+                {
+					const char *pkg = i->data;
+                    len -= snprintf (buf, 255, "- Package %s does not have a valid architecture\n",
+                                    pkg);
+					if (len >= 0)
+                    {
+                        strncat (err, buf, (size_t) len);
+                    }
+				}
+				break;
+			case ALPM_ERR_UNSATISFIED_DEPS:
+				for (i = data; i; i = alpm_list_next (i))
+                {
+					alpm_depmissing_t *miss = i->data;
+					char *depstring = alpm_dep_compute_string (miss->depend);
+                    len -= snprintf (buf, 255, "- %s requires %s\n", miss->target, depstring);
+					if (len >= 0)
+                    {
+                        strncat (err, buf, (size_t) len);
+                    }
+					free (depstring);
+				}
+				break;
+			case ALPM_ERR_CONFLICTING_DEPS:
+				for (i = data; i; i = alpm_list_next (i))
+                {
+					alpm_conflict_t *conflict = i->data;
+					/* only print reason if it contains new information */
+					if (conflict->reason->mod == ALPM_DEP_MOD_ANY)
+                    {
+						len -= snprintf (buf, 255, "- %s and %s are in conflict\n",
+								 conflict->package1, conflict->package2);
+                        if (len >= 0)
+                        {
+                            strncat (err, buf, (size_t) len);
+                        }
+					}
+                    else
+                    {
+						char *reason = alpm_dep_compute_string (conflict->reason);
+						len -= snprintf (buf, 255, "- %s and %s are in conflict (%s)\n",
+								 conflict->package1, conflict->package2, reason);
+                        if (len >= 0)
+                        {
+                            strncat (err, buf, (size_t) len);
+                        }
+                        free (reason);
+					}
+				}
+				break;
+			default:
+				break;
+		}
+        g_set_error (error, KALU_ERROR, 2, "Failed to prepare transaction: %s\n%s",
+            alpm_strerror (alpm_errno (alpm->handle)), err);
+		goto cleanup;
+	}
+    
+    alpm_db_t  *db_local = alpm_option_get_localdb (alpm->handle);
+    for (i = alpm_trans_get_add (alpm->handle); i; i = alpm_list_next (i))
+    {
+        alpm_pkg_t *pkg = i->data;
+        alpm_pkg_t *old = alpm_db_get_pkg (db_local, alpm_pkg_get_name (pkg));
+        kalu_package_t *package;
+        
+        package = calloc (1, sizeof (*package));
+        package->name = strdup (alpm_pkg_get_name (pkg));
+        package->new_version = strdup (alpm_pkg_get_version (pkg));
+        package->dl_size = (guint) alpm_pkg_download_size (pkg);
+        package->new_size = (guint) alpm_pkg_get_isize (pkg);
+        /* we might not have an old package, when an update requires to
+         * install a new package (e.g. after a split) */
+        if (old)
+        {
+            package->old_version = strdup (alpm_pkg_get_version (old));
+            package->old_size = (guint) alpm_pkg_get_isize (old);
+        }
+        else
+        {
+            package->old_version = strdup ("none");
+            package->old_size = 0;
+        }
+        
+        *packages = alpm_list_add (*packages, package);
+    }
+    
+cleanup:
+	if (data)
+    {
+		FREELIST (data);
+	}
+    trans_release (alpm, NULL);
+    
+    return (*packages != NULL);
+}
+
+gboolean
+kalu_alpm_has_updates_watched (alpm_list_t **packages, alpm_list_t *watched, GError **error)
+{
+    alpm_list_t *sync_dbs = alpm_option_get_syncdbs (alpm->handle);
+    alpm_list_t *i, *j;
+    GError *local_err = NULL;
+    
+    if (!check_syncdbs (alpm, 1, 1, &local_err))
+    {
+        g_propagate_error (error, local_err);
+		return FALSE;
+	}
+    
+    for (i = watched; i; i = alpm_list_next (i))
+    {
+        watched_package_t *w_pkg = i->data;
+        for (j = sync_dbs; j; j = alpm_list_next (j))
+        {
+            alpm_pkg_t *pkg = alpm_db_get_pkg ((alpm_db_t *) j->data, w_pkg->name);
+            if (pkg)
+            {
+                if (alpm_pkg_vercmp (alpm_pkg_get_version (pkg), w_pkg->version) > 0)
+                {
+                    kalu_package_t *package;
+                    package = calloc (1, sizeof (*package));
+                    
+                    package->name = strdup (alpm_pkg_get_name (pkg));
+                    package->old_version = strdup (w_pkg->version);
+                    package->new_version = strdup (alpm_pkg_get_version (pkg));
+                    package->dl_size = (guint) alpm_pkg_download_size (pkg);
+                    package->new_size = (guint) alpm_pkg_get_isize (pkg);
+                    
+                    *packages = alpm_list_add (*packages, package);
+                    debug ("found watched update %s: %s -> %s", package->name,
+                           package->old_version, package->new_version);
+                }
+                break;
+            }
+        }
+    }
+    
+    return (*packages != NULL);
+}
+
+gboolean
+kalu_alpm_has_foreign (alpm_list_t **packages, alpm_list_t *ignore, GError **error)
+{
+    alpm_db_t *dblocal;
+    alpm_list_t *sync_dbs, *i, *j;
+    gboolean found;
+    GError *local_err = NULL;
+    
+    if (!check_syncdbs (alpm, 1, 1, &local_err))
+    {
+        g_propagate_error (error, local_err);
+		return FALSE;
+	}
+    
+    dblocal  = alpm_option_get_localdb (alpm->handle);
+    sync_dbs = alpm_option_get_syncdbs (alpm->handle);
+    
+    for (i = alpm_db_get_pkgcache (dblocal); i; i = alpm_list_next (i))
+    {
+        alpm_pkg_t *pkg = i->data;
+        const char *pkgname = alpm_pkg_get_name (pkg);
+        found = FALSE;
+        
+        if (NULL != alpm_list_find_str (ignore, pkgname))
+        {
+            continue;
+        }
+        
+        for (j = sync_dbs; j; j = alpm_list_next (j))
+        {
+            if (alpm_db_get_pkg ((alpm_db_t *) j->data, pkgname))
+            {
+                found = TRUE;
+                break;
+            }
+        }
+        if (!found)
+        {
+            *packages = alpm_list_add (*packages, pkg);
+        }
+    }
+    
+    return (*packages != NULL);
+}
+
+void
+kalu_alpm_free (void)
+{
+    if (alpm == NULL)
+    {
+        return;
+    }
+    
+    if (alpm->handle != NULL)
+    {
+        alpm_release (alpm->handle);
+    }
+    
+    /* yes, we remove the dbpath. because we made a tmp copy of it */
+    if (alpm->dbpath)
+    {
+        rmrf (alpm->dbpath);
+    }
+	free (alpm->dbpath);
+    
+    g_free (alpm);
+    alpm = NULL;
+}
+
+#ifndef _KALU_ALPM_H
+#define _KALU_ALPM_H
+
+/* glib */
+#include <glib-2.0/glib.h>
+
+/* alpm */
+#include <alpm.h>
+#include <alpm_list.h>
+
+typedef struct _kalu_alpm_t {
+    char            *dbpath; /* the tmp-path where we copied dbs */
+    alpm_handle_t   *handle;
+    alpm_transflag_t flags;
+} kalu_alpm_t;
+
+/* global variable */
+extern unsigned short alpm_verbose;
+
+gboolean
+kalu_alpm_load (const gchar *conffile, GError **error);
+
+gboolean
+kalu_alpm_syncdbs (GError **error);
+
+gboolean
+kalu_alpm_has_updates (alpm_list_t **packages, GError **error);
+
+gboolean
+kalu_alpm_has_updates_watched (alpm_list_t **packages, alpm_list_t *watched, GError **error);
+
+gboolean
+kalu_alpm_has_foreign (alpm_list_t **packages, alpm_list_t *ignore, GError **error);
+
+void
+kalu_alpm_free (void);
+
+#endif /* _KALU_ALPM_H */
+/* GdkPixbuf RGBA C-Source image dump */
+
+#ifdef __SUNPRO_C
+#pragma align 4 (arch)
+#endif
+#ifdef __GNUC__
+static const guint8 arch[] __attribute__ ((__aligned__ (4))) = 
+#else
+static const guint8 arch[] = 
+#endif
+{ ""
+  /* Pixbuf magic (0x47646b50) */
+  "GdkP"
+  /* length: header (24) + pixel_data (9216) */
+  "\0\0$\30"
+  /* pixdata_type (0x1010002) */
+  "\1\1\0\2"
+  /* rowstride (192) */
+  "\0\0\0\300"
+  /* width (48) */
+  "\0\0\0""0"
+  /* height (48) */
+  "\0\0\0""0"
+  /* pixel_data: */
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\256\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\275\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f\0\0\0\377\0\0\0\362\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\311\6+=\376\3\30!\377\0\0\0W\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\0\3\4\377\21t\246"
+  "\377\6+>\376\0\0\0\354\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\307\5\"0\376\30\231\331\377\22y\254"
+  "\377\0\4\6\377\0\0\0\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\377\17b\213\377\27\223\321\377\26\222\320\377"
+  "\3\34'\377\0\0\0\332\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\216\3\32&\377\25\213\306\377\27\223\321\377\27\223\322"
+  "\377\21l\231\377\0\0\0\374\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\363\14Op\377\27\225\324\377\27\223\321\377\27\223"
+  "\320\377\26\215\311\377\7-@\377\0\0\0\241\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0>\3\26\37\377\24\202\270\377\26\222\320\377\27\223"
+  "\321\377\27\223\321\377\27\223\322\377\14W|\377\0\1\2\377\0\0\0\21\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\365\7""4J\377\27\225\324\377\27"
+  "\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\26\220\315"
+  "\377\3\25\36\376\0\0\0Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\1\0\0\0\0\376\24\204"
+  "\274\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\13Ih\377\0\1\2\377\0\0\0\6\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\365\3\34(\377\25\215\310\377\26\222\320\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\224\323"
+  "\377\3\27\40\377\0\0\0_\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\21\0\0\0\377\3\33&\376\26"
+  "\213\306\377\26\222\320\377\27\223\321\377\27\223\321\377\27\223\321"
+  "\377\27\223\321\377\27\223\321\377\12Fd\377\0\2\3\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\327"
+  "\0\0\0\215\0\0\0\11\0\0\0\377\3\31$\377\26\214\310\377\26\222\320\377"
+  "\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\224\323"
+  "\377\2\24\34\377\0\0\0k\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0(\0\3\5\377\5\"2\377\1\6\11\343\0\0\0Q\0\0\0\326"
+  "\4\37,\377\26\217\313\377\26\222\320\377\27\223\321\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\14Mn\377\0\0\1\367\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\5$3\377\27\230\330"
+  "\377\14Rv\377\1\13\20\377\0\0\0\254\0\0\0\342\12Da\377\27\224\323\377"
+  "\26\222\320\377\27\223\321\377\27\223\321\377\27\223\321\377\26\220\316"
+  "\377\2\22\32\377\0\0\0x\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0""3\1\6\11\377\15X~\377\26\222\320\377\26\222\320\377\27\226\326"
+  "\377\14Vz\377\5%5\377\0\0\0\376\15W{\377\27\223\321\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\27\224\322\377\15Tx\377\0\0\0\360\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\221\6(9\376\27\227\327"
+  "\377\27\223\321\377\27\223\321\377\26\222\320\377\27\223\321\377\26\221"
+  "\316\377\26\213\307\377\24\207\301\377\27\223\321\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\26\222\320\377\25\212\305\377\2\24\35"
+  "\377\0\0\0\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\1\11\14\377\15W}"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\225\324"
+  "\377\15W|\376\0\0\0\356\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\275\5\"1\376"
+  "\27\226\325\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377"
+  "\26\222\320\377\25\207\300\377\3\31#\377\0\0\0}\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\1"
+  "\6\11\377\16_\207\377\27\223\321\377\27\223\321\377\27\223\321\377\27"
+  "\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\223\321\377\27\225\325\377\14Tw\376\0\0\0"
+  "\363\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\317\4\36+\376\27\225\324\377\27\223\321\377\27"
+  "\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377"
+  "\26\222\320\377\25\210\301\377\4\34)\377\0\0\0n\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\1\1\377\20h\224"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\26\222\320\377\27\224\323\377\27\225\325\377"
+  "\27\225\324\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\225\324\377\14L"
+  "m\376\0\0\0\376\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\346\3\31#\376\27\226\326\377\27\223\321\377\27\223\321"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\224\322\377\25\214"
+  "\307\377\14Ll\377\6.B\377\13Ii\377\24\202\271\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377"
+  "\26\222\320\377\25\213\306\377\5\35)\377\0\0\0g\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0>\0\0\0\377\21s\243\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\27\223\321\377\26\222\320\377\27\223\321"
+  "\377\14Tx\377\2\16\23\376\0\0\0\377\0\0\0\372\0\0\0\373\0\1\1\377\11"
+  ">X\377\26\221\317\377\27\223\321\377\27\223\321\377\27\223\321\377\27"
+  "\223\321\377\27\223\321\377\27\224\322\377\12Hg\377\0\0\1\377\0\0\0\21"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\365\7""3I\377\27\223\322"
+  "\377\26\222\320\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\20e\217\377\0\4\6\376\0\0\0\377\0\0\0\32\0\0\0\4\0\0\0\3\0\0"
+  "\0g\0\1\1\376\10=X\377\27\223\321\377\27\223\321\377\27\223\321\377\27"
+  "\223\321\377\27\223\321\377\27\223\321\377\26\217\314\377\4\31$\376\0"
+  "\0\0\222\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""3\0\0\0\377\24\200\265"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\26\222"
+  "\320\377\26\222\317\377\5#2\377\0\0\0\377\0\0\0\16\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0g\0\1\2\377\20k\231\377\27\223\322\377\27\223\321"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\13J"
+  "j\377\0\1\2\377\0\0\0\26\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11\0\0\0\377\7""1E\376"
+  "\26\222\320\377\27\222\320\377\27\223\321\377\27\223\321\377\27\223\321"
+  "\377\27\224\322\377\14Ps\377\0\0\0\377\0\0\0(\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\321\4\40.\377\26\215\311\377\27\223\321"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\26\222\320\377\27\225"
+  "\324\377\2\20\27\376\0\0\0\262\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\2\23\33\376\24"
+  "\205\275\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321"
+  "\377\27\223\321\377\26\216\312\377\6+=\377\0\0\0\345\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\0\0\0\375\21p\237\377"
+  "\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321"
+  "\377\26\222\320\377\16_\207\377\0\3\5\377\0\0\0""0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\1\377"
+  "\10<V\377\26\222\320\377\27\223\321\377\27\223\321\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\24\206\277\377\0\0\0\377\0\0\0N\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\346"
+  "\10""6M\377\27\227\326\377\27\223\321\377\27\223\321\377\27\225\324\377"
+  "\27\226\326\377\27\226\326\377\30\234\337\377\4\34)\376\0\0\0\272\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\230\1\12\17\376\26\217\313\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\223\321\377\27\224\323\377\15[\203\377\0\0"
+  "\0\376\0\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\273\2\23\33\377\26\221\316\377\27\223\321\377\25\210"
+  "\302\377\14Sw\377\7/C\377\7/C\377\13Jj\377\10;T\377\2\20\27\377\0\0\0"
+  ".\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\31\0\0\0\377"
+  "\10;U\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377"
+  "\27\223\321\377\27\223\321\377\27\225\324\377\10""8O\377\0\0\0\372\0"
+  "\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0f\2\16\24\377\22w\252\377\27\223\321\377\27\225\324\377\16\\"
+  "\203\377\0\6\10\377\0\0\0\377\0\0\0\364\0\0\0\377\0\0\0\377\0\0\0\276"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\304\2\17\26"
+  "\376\30\227\327\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\223\321\377\27\225\324\377\10:R\377\0\0\0"
+  "\372\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0f\0\0\0\377\22w\251\377\27\223\321\377\27\223\321\377\27"
+  "\223\321\377\25\216\312\377\10;U\376\0\0\0\377\0\0\0+\0\0\0\307\0\0\0"
+  "\377\0\0\0Z\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0;\0\0\0\377\15Y\177"
+  "\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\223\321\377\27\225\324\377\10:R\377\0\0\0"
+  "\372\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0f\0\0\0\377\22w\252\377\27\223\321\377\27\223\321\377\26"
+  "\222\320\377\27\223\321\377\26\222\317\377\14Pr\376\1\13\20\377\0\0\0"
+  "\335\0\0\0\0\0\0\0l\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\305\5%5"
+  "\376\27\226\326\377\27\223\321\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\27\223\321\377\27\224\322\377\27\230\331\377\20g\223\377\10"
+  ">Y\377\0\0\0\372\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0f\5!0\377\16]\205\377\27\230\330\377\27\225"
+  "\324\377\26\222\320\377\27\223\321\377\26\222\320\377\27\224\322\377"
+  "\25\214\307\377\7""3I\377\0\0\0\377\0\2\3\14\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0f\0\5\7\377\17d\217\377\27\223\321\377\27\223\321\377\27\223"
+  "\321\377\26\222\320\377\27\230\330\377\22v\250\377\12Gf\377\1\11\16\377"
+  "\0\6\11\376\0\0\0\377\0\0\0\377\0\0\0\12\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\313\0\3\5\377\1\11\15\376"
+  "\1\7\13\377\12A]\377\17e\221\377\30\231\332\377\27\223\321\377\27\222"
+  "\320\377\26\222\320\377\26\221\317\377\16\\\202\376\2\15\22\377\0\0\0"
+  "i\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\346\6+=\376\27\230\331\377\26\222\320\377"
+  "\27\223\322\377\27\227\327\377\20l\232\377\7""1F\377\1\11\15\376\0\0"
+  "\0\377\0\0\0\356\0\0\0\250\0\0\0G\0\0\0\16\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#\0\0\0i"
+  "\0\0\0\277\0\0\0\377\1\12\17\377\3\31$\377\17d\217\377\26\217\313\377"
+  "\27\225\324\377\26\222\320\377\27\226\325\377\20l\232\376\2\22\32\377"
+  "\0\0\0\177\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\\\0\0\0\377\23~\263\377\27\224\323\377\26\217\313"
+  "\377\20l\232\377\4\36*\376\0\0\0\377\0\0\0\364\0\0\0\251\0\0\0'\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0s\0\0\0\323\0\0\0\377\1\14\21\377\14Rt\377\24\202\271\377\27"
+  "\226\326\377\27\226\325\377\5(9\376\0\0\0\376\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\372\12Fd\376\26"
+  "\217\314\377\16\\\203\377\2\15\24\377\0\0\0\377\0\0\0\336\0\0\0Z\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\35\0\0\0\251\0\0\0"
+  "\376\4\31$\377\13Ih\377\24\204\273\377\25\210\302\377\0\3\4\377\0\0\0"
+  "m\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\221\2"
+  "\15\23\377\14Qt\377\2\20\26\377\0\0\0\377\0\0\0\322\0\0\0R\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\256\0\0\0\370\4\36+\377\13Hf\376\4#2\376\0\0\0\377\0"
+  "\0\0\22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11\4\37,\375\10"
+  "=W\376\0\0\0\375\0\0\0\332\0\0\0\25\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\217\0\0\0\377\2\24\34\377\0\0\0\376\0\0\0\241"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\300\0\1\1\377\0\0\0\377"
+  "\0\0\0&\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\3\0\0\0\220\0\0\0\377\0\0\0\377\0\0\0\34\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\23\0\0\0\377\0\0\0*\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\26\0\0\0\300\0\0\0\316\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\31\0\0\0\11\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0"};
+
+
+/* GdkPixbuf RGBA C-Source image dump */
+
+#ifdef __SUNPRO_C
+#pragma align 4 (arch_gray)
+#endif
+#ifdef __GNUC__
+static const guint8 arch_gray[] __attribute__ ((__aligned__ (4))) = 
+#else
+static const guint8 arch_gray[] = 
+#endif
+{ ""
+  /* Pixbuf magic (0x47646b50) */
+  "GdkP"
+  /* length: header (24) + pixel_data (9216) */
+  "\0\0$\30"
+  /* pixdata_type (0x1010002) */
+  "\1\1\0\2"
+  /* rowstride (192) */
+  "\0\0\0\300"
+  /* width (48) */
+  "\0\0\0""0"
+  /* height (48) */
+  "\0\0\0""0"
+  /* pixel_data: */
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\256\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\275\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f\0\0\0\377\0\0\0\362\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\311!!!\376\22\22\22\377\0\0\0W\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\2\2\2\377[[[\377"
+  "!!!\376\0\0\0\354\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\307\32\32\32\376yyy\377___\377\3\3\3\377\0"
+  "\0\0\24\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377MMM\377ttt\377sss\377\25\25\25\377\0\0\0\332\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\216\24\24\24\377n"
+  "nn\377ttt\377ttt\377UUU\377\0\0\0\374\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\363>>>\377vvv\377ttt\377ttt\377ooo\377"
+  "###\377\0\0\0\241\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0>\21\21"
+  "\21\377fff\377sss\377ttt\377ttt\377ttt\377DDD\377\0\0\0\377\0\0\0\21"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\365(((\377vvv\377ttt\377ttt\377"
+  "ttt\377ttt\377rrr\377\20\20\20\376\0\0\0Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\376hhh\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377999\377"
+  "\0\0\0\377\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\365\25\25\25\377ooo\377sss\377"
+  "ttt\377ttt\377ttt\377ttt\377ttt\377uuu\377\21\21\21\377\0\0\0_\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\21\0\0\0\377\25\25\25\376nnn\377sss\377ttt\377ttt\377"
+  "ttt\377ttt\377ttt\377777\377\1\1\1\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\327\0\0\0\215\0"
+  "\0\0\11\0\0\0\377\23\23\23\377ooo\377sss\377ttt\377ttt\377ttt\377ttt"
+  "\377uuu\377\17\17\17\377\0\0\0k\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0(\2\2\2\377\33\33\33\377\4\4\4\343\0\0\0"
+  "Q\0\0\0\326\30\30\30\377qqq\377sss\377ttt\377ttt\377ttt\377ttt\377=="
+  "=\377\0\0\0\367\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\300\34\34\34\377xxx\377@@@\377\10\10\10\377\0\0\0\254\0"
+  "\0\0\342555\377uuu\377sss\377ttt\377ttt\377ttt\377rrr\377\16\16\16\377"
+  "\0\0\0x\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""3\4\4\4\377"
+  "EEE\377sss\377sss\377vvv\377CCC\377\35\35\35\377\0\0\0\376DDD\377ttt"
+  "\377ttt\377ttt\377ttt\377uuu\377BBB\377\0\0\0\360\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\221\37\37\37\376www\377ttt\377ttt\377"
+  "sss\377ttt\377rrr\377nnn\377jjj\377ttt\377ttt\377ttt\377ttt\377sss\377"
+  "mmm\377\17\17\17\377\0\0\0\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""0\6"
+  "\6\6\377DDD\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377"
+  "ttt\377ttt\377ttt\377ttt\377ttt\377vvv\377DDD\376\0\0\0\356\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\275\32\32\32\376vvv\377ttt\377ttt\377ttt\377"
+  "ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377"
+  "sss\377kkk\377\23\23\23\377\0\0\0}\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\40\4\4\4\377KKK"
+  "\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377t"
+  "tt\377ttt\377ttt\377ttt\377ttt\377ttt\377vvv\377BBB\376\0\0\0\363\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\317\27\27\27\376vvv\377ttt\377ttt\377ttt\377ttt\377tt"
+  "t\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377"
+  "ttt\377sss\377kkk\377\26\26\26\377\0\0\0n\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0\377RRR\377ttt\377"
+  "ttt\377ttt\377ttt\377ttt\377ttt\377sss\377uuu\377vvv\377vvv\377ttt\377"
+  "ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377vvv\377<<<\376\0\0\0\376\0"
+  "\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\346\23\23\23\376vvv\377ttt\377ttt\377ttt\377ttt\377ttt\377uuu\377nn"
+  "n\377<<<\377$$$\377999\377ggg\377ttt\377ttt\377ttt\377ttt\377ttt\377"
+  "ttt\377sss\377nnn\377\27\27\27\377\0\0\0g\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0>\0\0\0\377ZZZ\377ttt\377ttt\377ttt\377ttt"
+  "\377sss\377ttt\377BBB\377\12\12\12\376\0\0\0\377\0\0\0\372\0\0\0\373"
+  "\0\0\0\377000\377rrr\377ttt\377ttt\377ttt\377ttt\377ttt\377uuu\37788"
+  "8\377\0\0\0\377\0\0\0\21\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0"
+  "\0\365(((\377ttt\377sss\377ttt\377ttt\377ttt\377ttt\377PPP\377\3\3\3"
+  "\376\0\0\0\377\0\0\0\32\0\0\0\4\0\0\0\3\0\0\0g\0\0\0\376000\377ttt\377"
+  "ttt\377ttt\377ttt\377ttt\377ttt\377qqq\377\23\23\23\376\0\0\0\222\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""3\0\0\0\377eee\377ttt\377ttt\377"
+  "ttt\377ttt\377sss\377sss\377\33\33\33\377\0\0\0\377\0\0\0\16\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0g\0\0\0\377TTT\377ttt\377ttt\377ttt\377"
+  "ttt\377ttt\377ttt\377:::\377\0\0\0\377\0\0\0\26\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\11\0\0\0\377&&&\376sss\377sss\377ttt\377ttt\377ttt\377uuu\377\77\77"
+  "\77\377\0\0\0\377\0\0\0(\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\321\31\31\31\377ooo\377ttt\377ttt\377ttt\377ttt\377sss\377"
+  "vvv\377\14\14\14\376\0\0\0\262\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\16\16\16\376ii"
+  "i\377ttt\377ttt\377ttt\377ttt\377ttt\377ppp\377!!!\377\0\0\0\345\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\0\0\0\375"
+  "XXX\377ttt\377ttt\377ttt\377ttt\377ttt\377sss\377KKK\377\2\2\2\377\0"
+  "\0\0""0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\13\0\0\0\377///\377sss\377ttt\377ttt\377ttt\377ttt\377t"
+  "tt\377jjj\377\0\0\0\377\0\0\0N\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\346***\377www\377ttt\377ttt\377vvv\377"
+  "vvv\377vvv\377{{{\377\26\26\26\376\0\0\0\272\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\230\7\7\7\376qqq\377"
+  "ttt\377ttt\377ttt\377ttt\377ttt\377uuu\377GGG\377\0\0\0\376\0\0\0\10"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\273\16\16\16\377rrr\377ttt\377kkk\377AAA\377%%%\377%%%\377:::\377"
+  "...\377\14\14\14\377\0\0\0.\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\31\0\0\0\377...\377ttt\377ttt\377ttt\377ttt\377ttt\377"
+  "ttt\377vvv\377,,,\377\0\0\0\372\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f\13\13\13\377^^^\377ttt\377"
+  "vvv\377HHH\377\4\4\4\377\0\0\0\377\0\0\0\364\0\0\0\377\0\0\0\377\0\0"
+  "\0\276\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\304"
+  "\13\13\13\376www\377ttt\377ttt\377ttt\377ttt\377ttt\377ttt\377vvv\377"
+  "---\377\0\0\0\372\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0f\0\0\0\377^^^\377ttt\377ttt\377ttt\377ppp"
+  "\377...\376\0\0\0\377\0\0\0+\0\0\0\307\0\0\0\377\0\0\0Z\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0;\0\0\0\377FFF\377ttt\377ttt\377ttt\377t"
+  "tt\377ttt\377ttt\377ttt\377vvv\377---\377\0\0\0\372\0\0\0\4\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f\0\0\0\377"
+  "^^^\377ttt\377ttt\377sss\377ttt\377sss\377\77\77\77\376\10\10\10\377"
+  "\0\0\0\335\0\0\0\0\0\0\0l\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\305"
+  "\35\35\35\376vvv\377ttt\377ttt\377ttt\377ttt\377ttt\377uuu\377xxx\377"
+  "QQQ\377000\377\0\0\0\372\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0f\32\32\32\377III\377xxx\377vvv\377"
+  "sss\377ttt\377sss\377uuu\377nnn\377(((\377\0\0\0\377\1\1\1\14\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0f\3\3\3\377OOO\377ttt\377ttt\377ttt\377sss"
+  "\377xxx\377]]]\377888\377\7\7\7\377\4\4\4\376\0\0\0\377\0\0\0\377\0\0"
+  "\0\12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\313\2\2\2\377\7\7\7\376\5\5\5\377333\377PPP\377yyy\377ttt\377"
+  "sss\377sss\377rrr\377HHH\376\12\12\12\377\0\0\0i\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\346!!!\376xxx\377sss\377ttt\377www\377UUU\377&&&\377\7\7\7\376"
+  "\0\0\0\377\0\0\0\356\0\0\0\250\0\0\0G\0\0\0\16\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#\0\0"
+  "\0i\0\0\0\277\0\0\0\377\7\7\7\377\23\23\23\377OOO\377qqq\377vvv\377s"
+  "ss\377vvv\377UUU\376\16\16\16\377\0\0\0\177\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\377ccc\377"
+  "uuu\377qqq\377UUU\377\27\27\27\376\0\0\0\377\0\0\0\364\0\0\0\251\0\0"
+  "\0'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0s\0\0\0\323\0\0\0\377\11\11\11\377@@@\377ggg\377vvv\377"
+  "vvv\377\37\37\37\376\0\0\0\376\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\372777\376qqq\377HHH\377\12"
+  "\12\12\377\0\0\0\377\0\0\0\336\0\0\0Z\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\35\0\0\0\251\0\0\0\376\23\23\23\377999\377hhh"
+  "\377kkk\377\2\2\2\377\0\0\0m\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\221\12\12\12\377@@@\377\14\14\14\377\0\0\0\377"
+  "\0\0\0\322\0\0\0R\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\256\0\0\0\370\27\27\27\377"
+  "888\376\33\33\33\376\0\0\0\377\0\0\0\22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\11\30\30\30\375///\376\0\0\0\375\0\0\0\332\0\0\0\25"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\217\0\0\0"
+  "\377\17\17\17\377\0\0\0\376\0\0\0\241\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\300\0\0\0\377\0\0\0\377\0\0\0&\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\220"
+  "\0\0\0\377\0\0\0\377\0\0\0\34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\23\0\0\0"
+  "\377\0\0\0*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\26\0\0\0\300"
+  "\0\0\0\316\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\31\0\0\0\11\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0-\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
+
+
Add a comment to this file

arch_linux_48x48_icon_by_painlessrob-gray.png

Added
New image
Add a comment to this file

arch_linux_48x48_icon_by_painlessrob.png

Added
New image
+
+#define _BSD_SOURCE /* for strdup w/ -std=c99 */
+
+/* C */
+#include <string.h>
+
+/* glib */
+#include <glib-2.0/glib.h>
+
+/* alpm */
+#include <alpm.h>
+#include <alpm_list.h>
+
+/* cjson */
+#include "cJSON.h"
+
+/* kalu */
+#include "kalu.h"
+#include "aur.h"
+#include "curl.h"
+
+#define MAX_URL_LENGTH          1024
+
+static void *
+get_pkg_from_list (const char *pkgname, alpm_list_t *pkgs, gboolean is_watched)
+{
+    alpm_list_t *i;
+    const char *name;
+    for (i = pkgs; i; i = alpm_list_next (i))
+    {
+        if (is_watched)
+        {
+            name = ((watched_package_t *) i->data)->name;
+        }
+        else
+        {
+            name = alpm_pkg_get_name ((alpm_pkg_t *) i->data);
+        }
+        if (strcmp (pkgname, name) == 0)
+        {
+            return i->data;
+        }
+    }
+    return NULL;
+}
+
+#define add(str)    do {                                \
+        len = snprintf (s, (size_t) max, "%s", str);    \
+        max -= len;                                     \
+        s += len;                                       \
+    } while (0)
+gboolean
+aur_has_updates (alpm_list_t **packages,
+                 alpm_list_t *aur_pkgs,
+                 gboolean is_watched,
+                 GError **error)
+{
+    alpm_list_t *urls = NULL, *i;
+    char buf[MAX_URL_LENGTH + 1], *s;
+    int max, len;
+    size_t len_prefix = strlen (AUR_URL_PREFIX_PKG);
+    GError *local_err = NULL;
+    char *data;
+    const char *pkgname, *pkgver, *oldver;
+    cJSON *json, *results, *package;
+    int c, j;
+    void *pkg;
+    kalu_package_t *kpkg;
+    
+    debug ("looking for AUR updates");
+    
+    /* print start of url */
+    max = MAX_URL_LENGTH;
+    s = buf;
+    add (AUR_URL_PREFIX);
+    
+    for (i = aur_pkgs; i; i = alpm_list_next (i))
+    {
+        if (is_watched)
+        {
+            pkgname = ((watched_package_t *) i->data)->name;
+        }
+        else
+        {
+            pkgname = alpm_pkg_get_name ((alpm_pkg_t *) i->data);
+        }
+        
+        /* still enough space to add this pkgname ? */
+        if ((int) (len_prefix + strlen (pkgname)) > max)
+        {
+            /* nope. so we store this url and start a new one */
+            urls = alpm_list_add (urls, strdup (buf));
+            max = MAX_URL_LENGTH;
+            s = buf;
+            add (AUR_URL_PREFIX);
+        }
+        /* add pkgname */
+        add (AUR_URL_PREFIX_PKG);
+        add (pkgname);
+    }
+    urls = alpm_list_add (urls, strdup (buf));
+    
+    /* download */
+    for (i = urls; i; i = alpm_list_next (i))
+    {
+        data = curl_download (i->data, &local_err);
+        if (local_err != NULL)
+        {
+            g_propagate_error (error, local_err);
+            FREELIST (urls);
+            FREE_PACKAGE_LIST (*packages);
+            return FALSE;
+        }
+        free (i->data);
+        i->data = NULL;
+        
+        /* parse json */
+        debug ("parsing json");
+        json = cJSON_Parse (data);
+        results = cJSON_GetObjectItem (json, "results");
+        c = cJSON_GetArraySize (results);
+        debug ("got %d results", c);
+        for (j = 0; j < c; ++j)
+        {
+            package = cJSON_GetArrayItem (results, j);
+            if (package)
+            {
+                /* AUR */
+                pkgname = cJSON_GetObjectItem (package, "Name")->valuestring;
+                pkgver = cJSON_GetObjectItem (package, "Version")->valuestring;
+                /* ALPM/watched */
+                pkg = get_pkg_from_list (pkgname, aur_pkgs, is_watched);
+                if (is_watched)
+                {
+                    oldver = ((watched_package_t *) pkg)->version;
+                }
+                else
+                {
+                    oldver = alpm_pkg_get_version ((alpm_pkg_t *) pkg);
+                }
+                /* is AUR newer? */
+                if (alpm_pkg_vercmp (pkgver, oldver) == 1)
+                {
+                    debug ("%s %s -> %s", pkgname, oldver, pkgver);
+                    kpkg = calloc (1, sizeof (*kpkg));
+                    kpkg->name = strdup (pkgname);
+                    kpkg->old_version = strdup (oldver);
+                    kpkg->new_version = strdup (pkgver);
+                    *packages = alpm_list_add (*packages, kpkg);
+                }
+            }
+        }
+        cJSON_Delete (json);
+        free (data);
+    }
+    alpm_list_free (urls);
+    urls = NULL;
+    
+    return (*packages != NULL);
+}
+#undef add
+
+
+#ifndef _KALU_AUR_H
+#define _KALU_AUR_H
+
+#define AUR_URL_PREFIX      "http://aur.archlinux.org/rpc.php?type=multiinfo"
+#define AUR_URL_PREFIX_PKG  "&arg[]="
+
+gboolean
+aur_has_updates (alpm_list_t **packages,
+                 alpm_list_t *aur_pkgs,
+                 gboolean is_watched,
+                 GError **error);
+
+#endif /* _KALU_AUR_H */
+/*
+  Copyright (c) 2009 Dave Gamble
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+Welcome to cJSON.
+
+cJSON aims to be the dumbest possible parser that you can get your job done with.
+It's a single file of C, and a single header file.
+
+JSON is described best here: http://www.json.org/
+It's like XML, but fat-free. You use it to move data around, store things, or just
+generally represent your program's state.
+
+
+First up, how do I build?
+Add cJSON.c to your project, and put cJSON.h somewhere in the header search path.
+For example, to build the test app:
+
+gcc cJSON.c test.c -o test -lm
+./test
+
+
+As a library, cJSON exists to take away as much legwork as it can, but not get in your way.
+As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it
+in one of two modes: Auto and Manual. Let's have a quick run-through.
+
+
+I lifted some JSON from this page: http://www.json.org/fatfree.html
+That page inspired me to write cJSON, which is a parser that tries to share the same
+philosophy as JSON itself. Simple, dumb, out of the way.
+
+Some JSON:
+{
+    "name": "Jack (\"Bee\") Nimble", 
+    "format": {
+        "type":       "rect", 
+        "width":      1920, 
+        "height":     1080, 
+        "interlace":  false, 
+        "frame rate": 24
+    }
+}
+
+Assume that you got this from a file, a webserver, or magic JSON elves, whatever,
+you have a char * to it. Everything is a cJSON struct.
+Get it parsed:
+	cJSON *root = cJSON_Parse(my_json_string);
+
+This is an object. We're in C. We don't have objects. But we do have structs.
+What's the framerate?
+
+	cJSON *format = cJSON_GetObjectItem(root,"format");
+	int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint;
+
+
+Want to change the framerate?
+	cJSON_GetObjectItem(format,"frame rate")->valueint=25;
+	
+Back to disk?
+	char *rendered=cJSON_Print(root);
+
+Finished? Delete the root (this takes care of everything else).
+	cJSON_Delete(root);
+
+That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers
+before you dereference them. If you want to see how you'd build this struct in code?
+	cJSON *root,*fmt;
+	root=cJSON_CreateObject();	
+	cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
+	cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject());
+	cJSON_AddStringToObject(fmt,"type",		"rect");
+	cJSON_AddNumberToObject(fmt,"width",		1920);
+	cJSON_AddNumberToObject(fmt,"height",		1080);
+	cJSON_AddFalseToObject (fmt,"interlace");
+	cJSON_AddNumberToObject(fmt,"frame rate",	24);
+
+Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup.
+Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and
+a few from elsewhere.
+
+What about manual mode? First up you need some detail.
+Let's cover how the cJSON objects represent the JSON data.
+cJSON doesn't distinguish arrays from objects in handling; just type.
+Each cJSON has, potentially, a child, siblings, value, a name.
+
+The root object has: Object Type and a Child
+The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling:
+Sibling has type Object, name "format", and a child.
+That child has type String, name "type", value "rect", and a sibling:
+Sibling has type Number, name "width", value 1920, and a sibling:
+Sibling has type Number, name "height", value 1080, and a sibling:
+Sibling hs type False, name "interlace", and a sibling:
+Sibling has type Number, name "frame rate", value 24
+
+Here's the structure:
+typedef struct cJSON {
+	struct cJSON *next,*prev;
+	struct cJSON *child;
+
+	int type;
+
+	char *valuestring;
+	int valueint;
+	double valuedouble;
+
+	char *string;
+} cJSON;
+
+By default all values are 0 unless set by virtue of being meaningful.
+
+next/prev is a doubly linked list of siblings. next takes you to your sibling,
+prev takes you back from your sibling to you.
+Only objects and arrays have a "child", and it's the head of the doubly linked list.
+A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0.
+The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in
+cJSON.h
+
+A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read
+valuedouble.
+
+Any entry which is in the linked list which is the child of an object will have a "string"
+which is the "name" of the entry. When I said "name" in the above example, that's "string".
+"string" is the JSON name for the 'variable name' if you will.
+
+Now you can trivially walk the lists, recursively, and parse as you please.
+You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take
+the root object, and traverse the structure (which is, formally, an N-tree),
+and tokenise as you please. If you wanted to build a callback style parser, this is how
+you'd do it (just an example, since these things are very specific):
+
+void parse_and_callback(cJSON *item,const char *prefix)
+{
+	while (item)
+	{
+		char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2);
+		sprintf(newprefix,"%s/%s",prefix,item->name);
+		int dorecurse=callback(newprefix, item->type, item);
+		if (item->child && dorecurse) parse_and_callback(item->child,newprefix);
+		item=item->next;
+		free(newprefix);
+	}
+}
+
+The prefix process will build you a separated list, to simplify your callback handling.
+The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or
+let you invoke it per-item. For the item above, your callback might look like this:
+
+int callback(const char *name,int type,cJSON *item)
+{
+	if (!strcmp(name,"name"))	{ /* populate name */ }
+	else if (!strcmp(name,"format/type")	{ /* handle "rect" */ }
+	else if (!strcmp(name,"format/width")	{ /* 800 */ }
+	else if (!strcmp(name,"format/height")	{ /* 600 */ }
+	else if (!strcmp(name,"format/interlace")	{ /* false */ }
+	else if (!strcmp(name,"format/frame rate")	{ /* 24 */ }
+	return 1;
+}
+
+Alternatively, you might like to parse iteratively.
+You'd use:
+
+void parse_object(cJSON *item)
+{
+	int i; for (i=0;i<cJSON_GetArraySize(item);i++)
+	{
+		cJSON *subitem=cJSON_GetArrayItem(item,i);
+		// handle subitem.	
+	}
+}
+
+Or, for PROPER manual mode:
+
+void parse_object(cJSON *item)
+{
+	cJSON *subitem=item->child;
+	while (subitem)
+	{
+		// handle subitem
+		if (subitem->child) parse_object(subitem->child);
+		
+		subitem=subitem->next;
+	}
+}
+
+Of course, this should look familiar, since this is just a stripped-down version
+of the callback-parser.
+
+This should cover most uses you'll find for parsing. The rest should be possible
+to infer.. and if in doubt, read the source! There's not a lot of it! ;)
+
+
+In terms of constructing JSON data, the example code above is the right way to do it.
+You can, of course, hand your sub-objects to other functions to populate.
+Also, if you find a use for it, you can manually build the objects.
+For instance, suppose you wanted to build an array of objects?
+
+cJSON *objects[24];
+
+cJSON *Create_array_of_anything(cJSON **items,int num)
+{
+	int i;cJSON *prev, *root=cJSON_CreateArray();
+	for (i=0;i<24;i++)
+	{
+		if (!i)	root->child=objects[i];
+		else	prev->next=objects[i], objects[i]->prev=prev;
+		prev=objects[i];
+	}
+	return root;
+}
+	
+and simply: Create_array_of_anything(objects,24);
+
+cJSON doesn't make any assumptions about what order you create things in.
+You can attach the objects, as above, and later add children to each
+of those objects.
+
+As soon as you call cJSON_Print, it renders the structure to text.
+
+
+
+The test.c code shows how to handle a bunch of typical cases. If you uncomment
+the code, it'll load, parse and print a bunch of test files, also from json.org,
+which are more complex than I'd care to try and stash into a const char array[].
+
+
+Enjoy cJSON!
+
+
+- Dave Gamble, Aug 2009
+/*
+  Copyright (c) 2009 Dave Gamble
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "cJSON.h"
+
+static const char *ep;
+
+const char *cJSON_GetErrorPtr() {return ep;}
+
+static int cJSON_strcasecmp(const char *s1,const char *s2)
+{
+	if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
+	for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)	if(*s1 == 0)	return 0;
+	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
+}
+
+static void *(*cJSON_malloc)(size_t sz) = malloc;
+static void (*cJSON_free)(void *ptr) = free;
+
+static char* cJSON_strdup(const char* str)
+{
+      size_t len;
+      char* copy;
+
+      len = strlen(str) + 1;
+      if (!(copy = (char*)cJSON_malloc(len))) return 0;
+      memcpy(copy,str,len);
+      return copy;
+}
+
+void cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+    if (!hooks) { /* Reset hooks */
+        cJSON_malloc = malloc;
+        cJSON_free = free;
+        return;
+    }
+
+	cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
+	cJSON_free	 = (hooks->free_fn)?hooks->free_fn:free;
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item()
+{
+	cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
+	if (node) memset(node,0,sizeof(cJSON));
+	return node;
+}
+
+/* Delete a cJSON structure. */
+void cJSON_Delete(cJSON *c)
+{
+	cJSON *next;
+	while (c)
+	{
+		next=c->next;
+		if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
+		if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
+		if (c->string) cJSON_free(c->string);
+		cJSON_free(c);
+		c=next;
+	}
+}
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static const char *parse_number(cJSON *item,const char *num)
+{
+	double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
+
+	/* Could use sscanf for this? */
+	if (*num=='-') sign=-1,num++;	/* Has sign? */
+	if (*num=='0') num++;			/* is zero */
+	if (*num>='1' && *num<='9')	do	n=(n*10.0)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
+	if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;		do	n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}	/* Fractional part? */
+	if (*num=='e' || *num=='E')		/* Exponent? */
+	{	num++;if (*num=='+') num++;	else if (*num=='-') signsubscale=-1,num++;		/* With sign? */
+		while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');	/* Number? */
+	}
+
+	n=sign*n*pow(10.0,(scale+subscale*signsubscale));	/* number = +/- number.fraction * 10^+/- exponent */
+	
+	item->valuedouble=n;
+	item->valueint=(int)n;
+	item->type=cJSON_Number;
+	return num;
+}
+
+/* Render the number nicely from the given item into a string. */
+static char *print_number(cJSON *item)
+{
+	char *str;
+	double d=item->valuedouble;
+	if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
+	{
+		str=(char*)cJSON_malloc(21);	/* 2^64+1 can be represented in 21 chars. */
+		if (str) sprintf(str,"%d",item->valueint);
+	}
+	else
+	{
+		str=(char*)cJSON_malloc(64);	/* This is a nice tradeoff. */
+		if (str)
+		{
+			if (fabs(floor(d)-d)<=DBL_EPSILON)			sprintf(str,"%.0f",d);
+			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)	sprintf(str,"%e",d);
+			else										sprintf(str,"%f",d);
+		}
+	}
+	return str;
+}
+
+/* Parse the input text into an unescaped cstring, and populate item. */
+static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+static const char *parse_string(cJSON *item,const char *str)
+{
+	const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
+	if (*str!='\"') {ep=str;return 0;}	/* not a string! */
+	
+	while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;	/* Skip escaped quotes. */
+	
+	out=(char*)cJSON_malloc(len+1);	/* This is how long we need for the string, roughly. */
+	if (!out) return 0;
+	
+	ptr=str+1;ptr2=out;
+	while (*ptr!='\"' && *ptr)
+	{
+		if (*ptr!='\\') *ptr2++=*ptr++;
+		else
+		{
+			ptr++;
+			switch (*ptr)
+			{
+				case 'b': *ptr2++='\b';	break;
+				case 'f': *ptr2++='\f';	break;
+				case 'n': *ptr2++='\n';	break;
+				case 'r': *ptr2++='\r';	break;
+				case 't': *ptr2++='\t';	break;
+				case 'u':	 /* transcode utf16 to utf8. */
+					sscanf(ptr+1,"%4x",&uc);ptr+=4;	/* get the unicode char. */
+
+					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)	break;	// check for invalid.
+
+					if (uc>=0xD800 && uc<=0xDBFF)	// UTF16 surrogate pairs.
+					{
+						if (ptr[1]!='\\' || ptr[2]!='u')	break;	// missing second-half of surrogate.
+						sscanf(ptr+3,"%4x",&uc2);ptr+=6;
+						if (uc2<0xDC00 || uc2>0xDFFF)		break;	// invalid second-half of surrogate.
+						uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF);
+					}
+
+					len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
+					
+					switch (len) {
+						case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+						case 1: *--ptr2 =(uc | firstByteMark[len]);
+					}
+					ptr2+=len;
+					break;
+				default:  *ptr2++=*ptr; break;
+			}
+			ptr++;
+		}
+	}
+	*ptr2=0;
+	if (*ptr=='\"') ptr++;
+	item->valuestring=out;
+	item->type=cJSON_String;
+	return ptr;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static char *print_string_ptr(const char *str)
+{
+	const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
+	
+	if (!str) return cJSON_strdup("");
+	ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
+	
+	out=(char*)cJSON_malloc(len+3);
+	if (!out) return 0;
+
+	ptr2=out;ptr=str;
+	*ptr2++='\"';
+	while (*ptr)
+	{
+		if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
+		else
+		{
+			*ptr2++='\\';
+			switch (token=*ptr++)
+			{
+				case '\\':	*ptr2++='\\';	break;
+				case '\"':	*ptr2++='\"';	break;
+				case '\b':	*ptr2++='b';	break;
+				case '\f':	*ptr2++='f';	break;
+				case '\n':	*ptr2++='n';	break;
+				case '\r':	*ptr2++='r';	break;
+				case '\t':	*ptr2++='t';	break;
+				default: sprintf(ptr2,"u%04x",token);ptr2+=5;	break;	/* escape and print */
+			}
+		}
+	}
+	*ptr2++='\"';*ptr2++=0;
+	return out;
+}
+/* Invote print_string_ptr (which is useful) on an item. */
+static char *print_string(cJSON *item)	{return print_string_ptr(item->valuestring);}
+
+/* Predeclare these prototypes. */
+static const char *parse_value(cJSON *item,const char *value);
+static char *print_value(cJSON *item,int depth,int fmt);
+static const char *parse_array(cJSON *item,const char *value);
+static char *print_array(cJSON *item,int depth,int fmt);
+static const char *parse_object(cJSON *item,const char *value);
+static char *print_object(cJSON *item,int depth,int fmt);
+
+/* Utility to jump whitespace and cr/lf */
+static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
+
+/* Parse an object - create a new root, and populate. */
+cJSON *cJSON_Parse(const char *value)
+{
+	cJSON *c=cJSON_New_Item();
+	ep=0;
+	if (!c) return 0;       /* memory fail */
+
+	if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
+	return c;
+}
+
+/* Render a cJSON item/entity/structure to text. */
+char *cJSON_Print(cJSON *item)				{return print_value(item,0,1);}
+char *cJSON_PrintUnformatted(cJSON *item)	{return print_value(item,0,0);}
+
+/* Parser core - when encountering text, process appropriately. */
+static const char *parse_value(cJSON *item,const char *value)
+{
+	if (!value)						return 0;	/* Fail on null. */
+	if (!strncmp(value,"null",4))	{ item->type=cJSON_NULL;  return value+4; }
+	if (!strncmp(value,"false",5))	{ item->type=cJSON_False; return value+5; }
+	if (!strncmp(value,"true",4))	{ item->type=cJSON_True; item->valueint=1;	return value+4; }
+	if (*value=='\"')				{ return parse_string(item,value); }
+	if (*value=='-' || (*value>='0' && *value<='9'))	{ return parse_number(item,value); }
+	if (*value=='[')				{ return parse_array(item,value); }
+	if (*value=='{')				{ return parse_object(item,value); }
+
+	ep=value;return 0;	/* failure. */
+}
+
+/* Render a value to text. */
+static char *print_value(cJSON *item,int depth,int fmt)
+{
+	char *out=0;
+	if (!item) return 0;
+	switch ((item->type)&255)
+	{
+		case cJSON_NULL:	out=cJSON_strdup("null");	break;
+		case cJSON_False:	out=cJSON_strdup("false");break;
+		case cJSON_True:	out=cJSON_strdup("true"); break;
+		case cJSON_Number:	out=print_number(item);break;
+		case cJSON_String:	out=print_string(item);break;
+		case cJSON_Array:	out=print_array(item,depth,fmt);break;
+		case cJSON_Object:	out=print_object(item,depth,fmt);break;
+	}
+	return out;
+}
+
+/* Build an array from input text. */
+static const char *parse_array(cJSON *item,const char *value)
+{
+	cJSON *child;
+	if (*value!='[')	{ep=value;return 0;}	/* not an array! */
+
+	item->type=cJSON_Array;
+	value=skip(value+1);
+	if (*value==']') return value+1;	/* empty array. */
+
+	item->child=child=cJSON_New_Item();
+	if (!item->child) return 0;		 /* memory fail */
+	value=skip(parse_value(child,skip(value)));	/* skip any spacing, get the value. */
+	if (!value) return 0;
+
+	while (*value==',')
+	{
+		cJSON *new_item;
+		if (!(new_item=cJSON_New_Item())) return 0; 	/* memory fail */
+		child->next=new_item;new_item->prev=child;child=new_item;
+		value=skip(parse_value(child,skip(value+1)));
+		if (!value) return 0;	/* memory fail */
+	}
+
+	if (*value==']') return value+1;	/* end of array */
+	ep=value;return 0;	/* malformed. */
+}
+
+/* Render an array to text */
+static char *print_array(cJSON *item,int depth,int fmt)
+{
+	char **entries;
+	char *out=0,*ptr,*ret;int len=5;
+	cJSON *child=item->child;
+	int numentries=0,i=0,fail=0;
+	
+	/* How many entries in the array? */
+	while (child) numentries++,child=child->next;
+	/* Allocate an array to hold the values for each */
+	entries=(char**)cJSON_malloc(numentries*sizeof(char*));
+	if (!entries) return 0;
+	memset(entries,0,numentries*sizeof(char*));
+	/* Retrieve all the results: */
+	child=item->child;
+	while (child && !fail)
+	{
+		ret=print_value(child,depth+1,fmt);
+		entries[i++]=ret;
+		if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
+		child=child->next;
+	}
+	
+	/* If we didn't fail, try to malloc the output string */
+	if (!fail) out=(char*)cJSON_malloc(len);
+	/* If that fails, we fail. */
+	if (!out) fail=1;
+
+	/* Handle failure. */
+	if (fail)
+	{
+		for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
+		cJSON_free(entries);
+		return 0;
+	}
+	
+	/* Compose the output array. */
+	*out='[';
+	ptr=out+1;*ptr=0;
+	for (i=0;i<numentries;i++)
+	{
+		strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
+		if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
+		cJSON_free(entries[i]);
+	}
+	cJSON_free(entries);
+	*ptr++=']';*ptr++=0;
+	return out;	
+}
+
+/* Build an object from the text. */
+static const char *parse_object(cJSON *item,const char *value)
+{
+	cJSON *child;
+	if (*value!='{')	{ep=value;return 0;}	/* not an object! */
+	
+	item->type=cJSON_Object;
+	value=skip(value+1);
+	if (*value=='}') return value+1;	/* empty array. */
+	
+	item->child=child=cJSON_New_Item();
+	if (!item->child) return 0;
+	value=skip(parse_string(child,skip(value)));
+	if (!value) return 0;
+	child->string=child->valuestring;child->valuestring=0;
+	if (*value!=':') {ep=value;return 0;}	/* fail! */
+	value=skip(parse_value(child,skip(value+1)));	/* skip any spacing, get the value. */
+	if (!value) return 0;
+	
+	while (*value==',')
+	{
+		cJSON *new_item;
+		if (!(new_item=cJSON_New_Item()))	return 0; /* memory fail */
+		child->next=new_item;new_item->prev=child;child=new_item;
+		value=skip(parse_string(child,skip(value+1)));
+		if (!value) return 0;
+		child->string=child->valuestring;child->valuestring=0;
+		if (*value!=':') {ep=value;return 0;}	/* fail! */
+		value=skip(parse_value(child,skip(value+1)));	/* skip any spacing, get the value. */
+		if (!value) return 0;
+	}
+	
+	if (*value=='}') return value+1;	/* end of array */
+	ep=value;return 0;	/* malformed. */
+}
+
+/* Render an object to text. */
+static char *print_object(cJSON *item,int depth,int fmt)
+{
+	char **entries=0,**names=0;
+	char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
+	cJSON *child=item->child;
+	int numentries=0,fail=0;
+	/* Count the number of entries. */
+	while (child) numentries++,child=child->next;
+	/* Allocate space for the names and the objects */
+	entries=(char**)cJSON_malloc(numentries*sizeof(char*));
+	if (!entries) return 0;
+	names=(char**)cJSON_malloc(numentries*sizeof(char*));
+	if (!names) {cJSON_free(entries);return 0;}
+	memset(entries,0,sizeof(char*)*numentries);
+	memset(names,0,sizeof(char*)*numentries);
+
+	/* Collect all the results into our arrays: */
+	child=item->child;depth++;if (fmt) len+=depth;
+	while (child)
+	{
+		names[i]=str=print_string_ptr(child->string);
+		entries[i++]=ret=print_value(child,depth,fmt);
+		if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
+		child=child->next;
+	}
+	
+	/* Try to allocate the output string */
+	if (!fail) out=(char*)cJSON_malloc(len);
+	if (!out) fail=1;
+
+	/* Handle failure */
+	if (fail)
+	{
+		for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
+		cJSON_free(names);cJSON_free(entries);
+		return 0;
+	}
+	
+	/* Compose the output: */
+	*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
+	for (i=0;i<numentries;i++)
+	{
+		if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
+		strcpy(ptr,names[i]);ptr+=strlen(names[i]);
+		*ptr++=':';if (fmt) *ptr++='\t';
+		strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
+		if (i!=numentries-1) *ptr++=',';
+		if (fmt) *ptr++='\n';*ptr=0;
+		cJSON_free(names[i]);cJSON_free(entries[i]);
+	}
+	
+	cJSON_free(names);cJSON_free(entries);
+	if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
+	*ptr++='}';*ptr++=0;
+	return out;	
+}
+
+/* Get Array size/item / object item. */
+int    cJSON_GetArraySize(cJSON *array)							{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
+cJSON *cJSON_GetArrayItem(cJSON *array,int item)				{cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
+cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)	{cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}