summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gib_hash.c144
-rw-r--r--src/gib_hash.h72
-rw-r--r--src/gib_imlib.c697
-rw-r--r--src/gib_imlib.h180
-rw-r--r--src/gib_list.c624
-rw-r--r--src/gib_list.h97
-rw-r--r--src/gib_style.c241
-rw-r--r--src/gib_style.h70
-rw-r--r--src/gib_utils.c121
-rw-r--r--src/gib_utils.h53
-rw-r--r--src/imlib.c4
11 files changed, 2301 insertions, 2 deletions
diff --git a/src/gib_hash.c b/src/gib_hash.c
new file mode 100644
index 0000000..c839222
--- /dev/null
+++ b/src/gib_hash.c
@@ -0,0 +1,144 @@
+/* gib_hash.c
+
+Copyright (C) 1999,2000 Paul Duncan.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#include "gib_hash.h"
+#include "gib_utils.h"
+
+gib_hash_node *gib_hash_node_new(char *key, void *data)
+{
+ gib_hash_node *node = malloc(sizeof(gib_hash_node));
+ node->key = strdup(key);
+ GIB_LIST(node)->data = data;
+ GIB_LIST(node)->next = NULL;
+ GIB_LIST(node)->prev = NULL;
+ return node;
+
+}
+
+void gib_hash_node_free(gib_hash_node *node)
+{
+ free(node->key);
+ free(node);
+ return;
+}
+
+void gib_hash_node_free_and_data(gib_hash_node *node)
+{
+ free(node->list.data);
+ gib_hash_node_free(node);
+ return;
+}
+
+gib_hash *gib_hash_new()
+{
+ gib_hash *hash = malloc(sizeof(gib_hash));
+ hash->base = gib_hash_node_new("__gib_hash_new",NULL);
+ return hash;
+}
+
+void gib_hash_free(gib_hash *hash)
+{
+ /* free hash keys as it's not taken care of by gib_list_free */
+ gib_list *i;
+ for (i = GIB_LIST(hash->base); i; i = i->next)
+ free(GIB_HASH_NODE(i)->key);
+
+ gib_list_free(GIB_LIST(hash->base));
+ free(hash);
+ return;
+}
+
+void gib_hash_free_and_data(gib_hash *hash)
+{
+ /* free hash keys as it's not taken care of by gib_list_free */
+ gib_list *i;
+ for (i = GIB_LIST(hash->base); i; i = i->next)
+ free(GIB_HASH_NODE(i)->key);
+
+ gib_list_free_and_data(GIB_LIST(hash->base));
+ free(hash);
+ return;
+}
+
+static unsigned char gib_hash_find_callback(gib_list *list, void *data)
+{
+ gib_hash_node *node = GIB_HASH_NODE(list);
+ char *key = (char*) data;
+
+ /* strncasecmp causes simliar keys like key1 and key11 clobber eachother */
+ return !strcasecmp(node->key, key);
+}
+
+void gib_hash_set(gib_hash *hash, char *key, void *data)
+{
+ gib_list *l;
+ gib_hash_node *n;
+
+ n = GIB_HASH_NODE(gib_list_find(GIB_LIST(hash->base),
+ gib_hash_find_callback,
+ key));
+ if (n) {
+ GIB_LIST(n)->data = data;
+ } else {
+ /* not using gib_list_add_end here as that would nest the
+ data one level, doing manual insert instead */
+ n = gib_hash_node_new(key,data);
+ l = gib_list_last(GIB_LIST(hash->base));
+
+ GIB_LIST(n)->next = NULL;
+ GIB_LIST(n)->prev = l;
+
+ if (l)
+ l->next = GIB_LIST(n);
+ }
+}
+
+void *gib_hash_get(gib_hash *hash, char *key)
+{
+ gib_list *n = gib_list_find(GIB_LIST(hash->base),gib_hash_find_callback,key);
+ return n?n->data:NULL;
+}
+
+void gib_hash_remove(gib_hash *hash, char *key)
+{
+ gib_list *n = gib_list_find(GIB_LIST(hash->base), gib_hash_find_callback, key);
+ if (n) {
+ gib_list_unlink(GIB_LIST(hash->base), n);
+ gib_hash_node_free(GIB_HASH_NODE(n->data));
+ }
+
+ return;
+}
+
+void gib_hash_foreach(gib_hash *hash, void (*foreach_cb)(gib_hash_node *node, void *data), void *data)
+{
+ gib_hash_node *i, *next;
+ for (i=hash->base; i; i=next) {
+ next = GIB_HASH_NODE(GIB_LIST(i)->next);
+ foreach_cb(i,data);
+ }
+ return;
+}
+
diff --git a/src/gib_hash.h b/src/gib_hash.h
new file mode 100644
index 0000000..480ef6e
--- /dev/null
+++ b/src/gib_hash.h
@@ -0,0 +1,72 @@
+
+/* gib_hash.h
+
+Copyright (C) 1999,2000 Paul Duncan.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#ifndef GIB_HASH_H
+#define GIB_HASH_H
+
+#include "gib_list.h"
+
+#define GIB_HASH(a) ((gib_hash*)a)
+#define GIB_HASH_NODE(a) ((gib_hash_node*)a)
+
+typedef struct __gib_hash gib_hash;
+typedef struct __gib_hash_node gib_hash_node;
+
+struct __gib_hash
+{
+ gib_hash_node *base;
+};
+
+struct __gib_hash_node
+{
+ gib_list list;
+ char *key;
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+gib_hash_node *gib_hash_node_new(char *key, void *data);
+void gib_hash_node_free(gib_hash_node *node);
+void gib_hash_node_free_and_data(gib_hash_node *node);
+
+gib_hash *gib_hash_new();
+void gib_hash_free(gib_hash *hash);
+void gib_hash_free_and_data(gib_hash *hash);
+
+void gib_hash_set(gib_hash *hash, char *key, void *data);
+void *gib_hash_get(gib_hash *hash, char *key);
+void gib_hash_remove(gib_hash *hash, char *key);
+
+void gib_hash_foreach(gib_hash *hash, void (*foreach_cb)(gib_hash_node *node, void *data), void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GIB_HASH_H */
diff --git a/src/gib_imlib.c b/src/gib_imlib.c
new file mode 100644
index 0000000..49eb5cb
--- /dev/null
+++ b/src/gib_imlib.c
@@ -0,0 +1,697 @@
+/* gib_imlib.c
+
+Copyright (C) 1999,2000 Tom Gilbert.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#include "gib_imlib.h"
+#include "gib_utils.h"
+
+int
+gib_imlib_load_image(Imlib_Image * im, char *filename)
+{
+ Imlib_Load_Error err;
+
+ imlib_context_set_progress_function(NULL);
+ if (!filename)
+ return (0);
+ *im = imlib_load_image_with_error_return(filename, &err);
+ if ((err) || (!im))
+ {
+ /* Check error code */
+ switch (err)
+ {
+ case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST:
+ gib_weprintf("%s - File does not exist", filename);
+ break;
+ case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY:
+ gib_weprintf("%s - Directory specified for image filename", filename);
+ break;
+ case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ:
+ gib_weprintf("%s - No read access to directory", filename);
+ break;
+ case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT:
+ gib_weprintf("%s - No Imlib2 loader for that file format", filename);
+ break;
+ case IMLIB_LOAD_ERROR_PATH_TOO_LONG:
+ gib_weprintf("%s - Path specified is too long", filename);
+ break;
+ case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT:
+ gib_weprintf("%s - Path component does not exist", filename);
+ break;
+ case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY:
+ gib_weprintf("%s - Path component is not a directory", filename);
+ break;
+ case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE:
+ gib_weprintf("%s - Path points outside address space", filename);
+ break;
+ case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS:
+ gib_weprintf("%s - Too many levels of symbolic links", filename);
+ break;
+ case IMLIB_LOAD_ERROR_OUT_OF_MEMORY:
+ gib_eprintf("While loading %s - Out of memory", filename);
+ break;
+ case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS:
+ gib_eprintf("While loading %s - Out of file descriptors", filename);
+ break;
+ case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE:
+ gib_weprintf("%s - Cannot write to directory", filename);
+ break;
+ case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE:
+ gib_weprintf("%s - Cannot write - out of disk space", filename);
+ break;
+ case IMLIB_LOAD_ERROR_UNKNOWN:
+ default:
+ gib_weprintf
+ ("While loading %s - Unknown error. Attempting to continue",
+ filename);
+ break;
+ }
+ return (0);
+ }
+ return (1);
+}
+
+int
+gib_imlib_image_get_width(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ return imlib_image_get_width();
+}
+
+int
+gib_imlib_image_get_height(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ return imlib_image_get_height();
+}
+
+int
+gib_imlib_image_has_alpha(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ return imlib_image_has_alpha();
+}
+
+void
+gib_imlib_free_image_and_decache(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ imlib_free_image_and_decache();
+}
+
+void
+gib_imlib_free_image(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ imlib_free_image();
+}
+
+const char *
+gib_imlib_image_get_filename(Imlib_Image im)
+{
+ if (im)
+ {
+ imlib_context_set_image(im);
+ return imlib_image_get_filename();
+ }
+ else
+ return NULL;
+}
+
+void
+gib_imlib_render_image_on_drawable(Drawable d, Imlib_Image im, int x, int y,
+ char dither, char blend, char alias)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_drawable(d);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_dither(dither);
+ imlib_context_set_blend(blend);
+ imlib_context_set_angle(0);
+ imlib_render_image_on_drawable(x, y);
+}
+
+void
+gib_imlib_render_image_on_drawable_with_rotation(Drawable d, Imlib_Image im,
+ int x, int y, double angle,
+ char dither, char blend,
+ char alias)
+{
+ Imlib_Image new_im;
+
+ imlib_context_set_image(im);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_dither(dither);
+ imlib_context_set_blend(blend);
+ imlib_context_set_angle(angle);
+ imlib_context_set_drawable(d);
+ new_im = imlib_create_rotated_image(angle);
+ imlib_context_set_image(new_im);
+ imlib_render_image_on_drawable(x, y);
+ imlib_free_image();
+}
+
+void
+gib_imlib_render_image_on_drawable_at_size(Drawable d, Imlib_Image im, int x,
+ int y, int w, int h, char dither,
+ char blend, char alias)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_drawable(d);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_dither(dither);
+ imlib_context_set_blend(blend);
+ imlib_context_set_angle(0);
+ imlib_render_image_on_drawable_at_size(x, y, w, h);
+}
+
+void
+gib_imlib_render_image_on_drawable_at_size_with_rotation(Drawable d,
+ Imlib_Image im,
+ int x, int y, int w,
+ int h, double angle,
+ char dither,
+ char blend,
+ char alias)
+{
+ Imlib_Image new_im;
+
+ imlib_context_set_image(im);
+ imlib_context_set_drawable(d);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_dither(dither);
+ imlib_context_set_blend(blend);
+ imlib_context_set_angle(angle);
+ new_im = imlib_create_rotated_image(angle);
+ imlib_context_set_image(new_im);
+ imlib_render_image_on_drawable_at_size(x, y, w, h);
+ imlib_free_image_and_decache();
+}
+
+void
+gib_imlib_render_image_part_on_drawable_at_size(Drawable d, Imlib_Image im,
+ int sx, int sy, int sw,
+ int sh, int dx, int dy,
+ int dw, int dh, char dither,
+ char blend, char alias)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_drawable(d);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_dither(dither);
+ imlib_context_set_blend(blend);
+ imlib_context_set_angle(0);
+ imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw,
+ dh);
+}
+
+void
+gib_imlib_render_image_part_on_drawable_at_size_with_rotation(Drawable d,
+ Imlib_Image im,
+ int sx, int sy,
+ int sw, int sh,
+ int dx, int dy,
+ int dw, int dh,
+ double angle,
+ char dither,
+ char blend,
+ char alias)
+{
+ Imlib_Image new_im;
+
+ imlib_context_set_image(im);
+ imlib_context_set_drawable(d);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_dither(dither);
+ imlib_context_set_angle(angle);
+ imlib_context_set_blend(blend);
+ new_im = imlib_create_rotated_image(angle);
+ imlib_context_set_image(new_im);
+ imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw,
+ dh);
+ imlib_free_image_and_decache();
+}
+
+void
+gib_imlib_image_fill_rectangle(Imlib_Image im, int x, int y, int w, int h,
+ int r, int g, int b, int a)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_color(r, g, b, a);
+ imlib_image_fill_rectangle(x, y, w, h);
+}
+
+void
+gib_imlib_image_fill_polygon(Imlib_Image im, ImlibPolygon poly, int r, int g,
+ int b, int a, unsigned char alias, int cx,
+ int cy, int cw, int ch)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_color(r, g, b, a);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_cliprect(cx, cy, cw, ch);
+ imlib_image_fill_polygon(poly);
+ imlib_context_set_cliprect(0, 0, 0, 0);
+}
+
+void
+gib_imlib_image_draw_polygon(Imlib_Image im, ImlibPolygon poly, int r, int g,
+ int b, int a, unsigned char closed,
+ unsigned char alias, int cx, int cy, int cw,
+ int ch)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_color(r, g, b, a);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_cliprect(cx, cy, cw, ch);
+ imlib_image_draw_polygon(poly, closed);
+ imlib_context_set_cliprect(0, 0, 0, 0);
+}
+
+
+void
+gib_imlib_image_draw_rectangle(Imlib_Image im, int x, int y, int w, int h,
+ int r, int g, int b, int a)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_color(r, g, b, a);
+ imlib_image_draw_rectangle(x, y, w, h);
+}
+
+
+void
+gib_imlib_text_draw(Imlib_Image im, Imlib_Font fn, gib_style * s, int x,
+ int y, char *text, Imlib_Text_Direction dir, int r, int g,
+ int b, int a)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_font(fn);
+ imlib_context_set_direction(dir);
+ if (s)
+ {
+ int min_x = 0, min_y = 0;
+ gib_style_bit *bb;
+ gib_list *l;
+
+ /* here we shift the draw to accomodate bits with negative offsets,
+ * which would be drawn at negative coords otherwise */
+ l = s->bits;
+ while (l)
+ {
+ bb = (gib_style_bit *) l->data;
+ if (bb)
+ {
+ if (bb->x_offset < min_x)
+ min_x = bb->x_offset;
+ if (bb->y_offset < min_y)
+ min_y = bb->y_offset;
+ }
+ l = l->next;
+ }
+ x -= min_x;
+ y -= min_y;
+
+ /* Now draw the bits */
+ l = s->bits;
+ while (l)
+ {
+ bb = (gib_style_bit *) l->data;
+ if (bb)
+ {
+ if ((bb->r + bb->g + bb->b + bb->a) == 0)
+ imlib_context_set_color(r, g, b, a);
+ else
+ imlib_context_set_color(bb->r, bb->g, bb->b, bb->a);
+ imlib_text_draw(x + bb->x_offset, y + bb->y_offset, text);
+ }
+ l = l->next;
+ }
+ }
+ else
+ {
+ imlib_context_set_color(r, g, b, a);
+ imlib_text_draw(x, y, text);
+ }
+}
+
+char **
+gib_imlib_list_fonts(int *num)
+{
+ return imlib_list_fonts(num);
+}
+
+
+void
+gib_imlib_get_text_size(Imlib_Font fn, char *text, gib_style * s, int *w,
+ int *h, Imlib_Text_Direction dir)
+{
+
+ imlib_context_set_font(fn);
+ imlib_context_set_direction(dir);
+ imlib_get_text_size(text, w, h);
+ if (s)
+ {
+ gib_style_bit *b;
+ int max_x_off = 0, min_x_off = 0, max_y_off = 0, min_y_off = 0;
+ gib_list *l;
+
+ l = s->bits;
+ while (l)
+ {
+ b = (gib_style_bit *) l->data;
+ if (b)
+ {
+ if (b->x_offset > max_x_off)
+ max_x_off = b->x_offset;
+ else if (b->x_offset < min_x_off)
+ min_x_off = b->x_offset;
+ if (b->y_offset > max_y_off)
+ max_y_off = b->y_offset;
+ else if (b->y_offset < min_y_off)
+ min_y_off = b->y_offset;
+ }
+ l = l->next;
+ }
+ if (h)
+ {
+ *h += max_y_off;
+ *h -= min_y_off;
+ }
+ if (w)
+ {
+ *w += max_x_off;
+ *w -= min_x_off;
+ }
+ }
+}
+
+Imlib_Image gib_imlib_clone_image(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ return imlib_clone_image();
+}
+
+char *
+gib_imlib_image_format(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ return imlib_image_format();
+}
+
+void
+gib_imlib_blend_image_onto_image(Imlib_Image dest_image,
+ Imlib_Image source_image, char merge_alpha,
+ int sx, int sy, int sw, int sh, int dx,
+ int dy, int dw, int dh, char dither,
+ char blend, char alias)
+{
+ imlib_context_set_image(dest_image);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_dither(dither);
+ imlib_context_set_blend(blend);
+ imlib_context_set_angle(0);
+ imlib_blend_image_onto_image(source_image, merge_alpha, sx, sy, sw, sh, dx,
+ dy, dw, dh);
+}
+
+void
+gib_imlib_blend_image_onto_image_with_rotation(Imlib_Image dest_image,
+ Imlib_Image source_image,
+ char merge_alpha, int sx,
+ int sy, int sw, int sh, int dx,
+ int dy, int dw, int dh,
+ double angle, char dither,
+ char blend, char alias)
+{
+ imlib_context_set_image(dest_image);
+ imlib_context_set_anti_alias(alias);
+ imlib_context_set_dither(dither);
+ imlib_context_set_blend(blend);
+ imlib_context_set_angle(angle);
+ imlib_blend_image_onto_image_at_angle(source_image, merge_alpha, sx, sy,
+ sw, sh, dx, dy, (int) angle,
+ (int) angle);
+ return;
+ dw = 0;
+ dh = 0;
+}
+
+Imlib_Image gib_imlib_create_cropped_scaled_image(Imlib_Image im, int sx,
+ int sy, int sw, int sh,
+ int dw, int dh, char alias)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_anti_alias(alias);
+ return imlib_create_cropped_scaled_image(sx, sy, sw, sh, dw, dh);
+}
+
+void
+gib_imlib_apply_color_modifier_to_rectangle(Imlib_Image im, int x, int y,
+ int w, int h, DATA8 * rtab,
+ DATA8 * gtab, DATA8 * btab,
+ DATA8 * atab)
+{
+ Imlib_Color_Modifier cm;
+
+ imlib_context_set_image(im);
+ cm = imlib_create_color_modifier();
+ imlib_context_set_color_modifier(cm);
+ imlib_set_color_modifier_tables(rtab, gtab, btab, atab);
+ imlib_apply_color_modifier_to_rectangle(x, y, w, h);
+ imlib_free_color_modifier();
+}
+
+void
+gib_imlib_image_set_has_alpha(Imlib_Image im, int alpha)
+{
+ imlib_context_set_image(im);
+ imlib_image_set_has_alpha(alpha);
+}
+
+void
+gib_imlib_save_image(Imlib_Image im, char *file)
+{
+ char *tmp;
+
+ imlib_context_set_image(im);
+ tmp = strrchr(file, '.');
+ if (tmp)
+ {
+ char *p, *pp;
+ p = strdup(tmp + 1);
+ pp = p;
+ while(*pp) {
+ *pp = tolower(*pp);
+ pp++;
+ }
+ imlib_image_set_format(p);
+ free(p);
+ }
+ imlib_save_image(file);
+}
+
+void
+gib_imlib_save_image_with_error_return(Imlib_Image im, char *file,
+ Imlib_Load_Error * error_return)
+{
+ char *tmp;
+
+ imlib_context_set_image(im);
+ tmp = strrchr(file, '.');
+ if (tmp)
+ imlib_image_set_format(tmp + 1);
+ imlib_save_image_with_error_return(file, error_return);
+}
+
+void
+gib_imlib_free_font(Imlib_Font fn)
+{
+ imlib_context_set_font(fn);
+ imlib_free_font();
+}
+
+void
+gib_imlib_image_draw_line(Imlib_Image im, int x1, int y1, int x2, int y2,
+ char make_updates, int r, int g, int b, int a)
+{
+ imlib_context_set_image(im);
+ imlib_context_set_color(r, g, b, a);
+ imlib_image_draw_line(x1, y1, x2, y2, make_updates);
+}
+
+Imlib_Image gib_imlib_create_rotated_image(Imlib_Image im, double angle)
+{
+ imlib_context_set_image(im);
+ return (imlib_create_rotated_image(angle));
+}
+
+void
+gib_imlib_image_tile(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ imlib_image_tile();
+}
+
+void
+gib_imlib_image_blur(Imlib_Image im, int radius)
+{
+ imlib_context_set_image(im);
+ imlib_image_blur(radius);
+}
+
+void
+gib_imlib_image_sharpen(Imlib_Image im, int radius)
+{
+ imlib_context_set_image(im);
+ imlib_image_sharpen(radius);
+}
+
+void
+gib_imlib_line_clip_and_draw(Imlib_Image dest, int x0, int y0, int x1, int y1,
+ int cx, int cy, int cw, int ch, int r, int g,
+ int b, int a)
+{
+ imlib_context_set_cliprect(cx, cy, cw, ch);
+ gib_imlib_image_draw_line(dest, x0, y0, x1, y1, 0, r, g, b, a);
+ imlib_context_set_cliprect(0, 0, 0, 0);
+}
+
+Imlib_Image
+gib_imlib_create_image_from_drawable(Drawable d, Pixmap mask, int x, int y,
+ int width, int height,
+ char need_to_grab_x)
+{
+ imlib_context_set_drawable(d);
+ return imlib_create_image_from_drawable(mask, x, y, width, height,
+ need_to_grab_x);
+}
+
+void gib_imlib_parse_color(char *col, int *r, int *g, int *b, int *a)
+ {
+ gib_list *ll;
+ unsigned long cc, rr, gg, bb, aa;
+ int len;
+
+ if (col[0] == '#')
+ {
+ /* #RRGGBBAA style */
+ /* skip the '#' */
+ col++;
+ len = strlen(col);
+ if (len == 8)
+ {
+ cc = (unsigned long) strtoul(col, NULL, 16);
+ rr = (cc & 0xff000000) >> 24;
+ gg = (cc & 0x00ff0000) >> 16;
+ bb = (cc & 0x0000ff00) >> 8;
+ aa = (cc & 0x000000ff);
+ }
+ else if (len == 6)
+ {
+ cc = (unsigned long) strtoul(col, NULL, 16);
+ rr = (cc & 0xff0000) >> 16;
+ gg = (cc & 0x00ff00) >> 8;
+ bb = (cc & 0x0000ff);
+ aa = 255;
+ }
+ else
+ {
+ gib_weprintf("unable to parse color %s\n", col);
+ return;
+ }
+ }
+ else
+ {
+ /* r,g,b,a style */
+ ll = gib_string_split(col, ",");
+ if (!ll)
+ {
+ gib_weprintf("unable to parse color %s\n", col);
+ return;
+ }
+ len = gib_list_length(ll);
+ if (len == 3)
+ {
+ rr = atoi(ll->data);
+ gg = atoi(ll->next->data);
+ bb = atoi(ll->next->next->data);
+ aa = 255;
+ }
+ else if (len == 4)
+ {
+ rr = atoi(ll->data);
+ gg = atoi(ll->next->data);
+ bb = atoi(ll->next->next->data);
+ aa = atoi(ll->next->next->next->data);
+ }
+ else
+ {
+ gib_weprintf("unable to parse color %s\n", col);
+ return;
+ }
+ }
+ *r = rr;
+ *g = gg;
+ *b = bb;
+ *a = aa;
+ }
+
+void
+gib_imlib_parse_fontpath(char *path)
+{
+ gib_list *l, *ll;
+
+ if (!path)
+ return;
+
+ l = gib_string_split(path, ":");
+ if (!l)
+ return;
+ ll = l;
+ while (ll)
+ {
+ imlib_add_path_to_font_path((char *) ll->data);
+ ll = ll->next;
+ }
+ gib_list_free_and_data(l);
+}
+
+Imlib_Font
+gib_imlib_load_font(char *name)
+{
+ Imlib_Font fn;
+
+ if ((fn = imlib_load_font(name)))
+ return fn;
+ gib_weprintf("couldn't load font %s, attempting to fall back to fixed.", name);
+ if ((fn = imlib_load_font("fixed")))
+ return fn;
+ gib_weprintf("failed to even load fixed! Attempting to find any font.");
+ return imlib_load_font("*");
+}
+
+void gib_imlib_image_orientate(Imlib_Image im, int orientation)
+{
+ imlib_context_set_image(im);
+ imlib_image_orientate(orientation);
+}
diff --git a/src/gib_imlib.h b/src/gib_imlib.h
new file mode 100644
index 0000000..6289436
--- /dev/null
+++ b/src/gib_imlib.h
@@ -0,0 +1,180 @@
+/* gib_imlib.h
+
+Copyright (C) 1999,2000 Tom Gilbert.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#ifndef GIB_IMLIB_H
+#define GIB_IMLIB_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <Imlib2.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "gib_style.h"
+
+#define GIBCLIP(x, y, w, h, xx, yy, ww, hh) \
+{ \
+ if ((yy) > y) { h -= (yy) - y; y = (yy); } \
+ if ((yy) + hh < y + h) { h -= y + h - ((yy) + (hh)); } \
+ if ((xx) > x) { w -= (xx) - x; x = (xx); } \
+ if ((xx) + (ww) < x + w) { w -= x + w - ((xx) + (ww)); } \
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int gib_imlib_load_image(Imlib_Image * im, char *filename);
+int gib_imlib_image_get_width(Imlib_Image im);
+int gib_imlib_image_get_height(Imlib_Image im);
+int gib_imlib_image_has_alpha(Imlib_Image im);
+const char *gib_imlib_image_get_filename(Imlib_Image im);
+void gib_imlib_free_image_and_decache(Imlib_Image im);
+void gib_imlib_render_image_on_drawable(Drawable d, Imlib_Image im, int x,
+ int y, char dither, char blend,
+
+ char alias);
+void gib_imlib_render_image_on_drawable_with_rotation(Drawable d,
+ Imlib_Image im, int x,
+ int y, double angle,
+
+ char dither, char blend,
+ char alias);
+void gib_imlib_render_image_part_on_drawable_at_size(Drawable d,
+ Imlib_Image im, int sx,
+ int sy, int sw, int sh,
+ int dx, int dy, int dw,
+ int dh, char dither,
+
+ char blend, char alias);
+void gib_imlib_render_image_part_on_drawable_at_size_with_rotation(Drawable d,
+ Imlib_Image
+
+ im, int sx,
+ int sy,
+ int sw,
+ int sh,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ double
+ angle,
+ char
+ dither,
+ char blend,
+ char
+ alias);
+void gib_imlib_image_fill_rectangle(Imlib_Image im, int x, int y, int w,
+ int h, int r, int g, int b, int a);
+void gib_imlib_text_draw(Imlib_Image im, Imlib_Font fn, gib_style * s, int x,
+ int y, char *text, Imlib_Text_Direction dir, int r,
+ int g, int b, int a);
+void gib_imlib_get_text_size(Imlib_Font fn, char *text, gib_style * s, int *w,
+ int *h, Imlib_Text_Direction dir);
+Imlib_Image gib_imlib_clone_image(Imlib_Image im);
+char *gib_imlib_image_format(Imlib_Image im);
+char **gib_imlib_list_fonts(int *num);
+void gib_imlib_render_image_on_drawable_at_size(Drawable d, Imlib_Image im,
+ int x, int y, int w, int h,
+ char dither, char blend,
+
+ char alias);
+void gib_imlib_render_image_on_drawable_at_size_with_rotation(Drawable d,
+ Imlib_Image im,
+ int x, int y,
+
+ int w, int h,
+ double angle,
+ char dither,
+ char blend,
+ char alias);
+void gib_imlib_blend_image_onto_image(Imlib_Image dest_image,
+ Imlib_Image source_image,
+ char merge_alpha, int sx, int sy,
+ int sw, int sh, int dx, int dy, int dw,
+ int dh, char dither, char blend,
+
+ char alias);
+void gib_imlib_blend_image_onto_image_with_rotation(Imlib_Image dest_image,
+ Imlib_Image source_image,
+ char merge_alpha, int sx,
+ int sy, int sw, int sh,
+ int dx, int dy, int dw,
+ int dh, double angle,
+
+ char dither, char blend,
+ char alias);
+Imlib_Image gib_imlib_create_cropped_scaled_image(Imlib_Image im, int sx,
+ int sy, int sw, int sh,
+ int dw, int dh, char alias);
+void gib_imlib_apply_color_modifier_to_rectangle(Imlib_Image im, int x, int y,
+ int w, int h, DATA8 * rtab,
+ DATA8 * gtab, DATA8 * btab,
+ DATA8 * atab);
+void gib_imlib_image_set_has_alpha(Imlib_Image im, int alpha);
+void gib_imlib_save_image(Imlib_Image im, char *file);
+void gib_imlib_save_image_with_error_return(Imlib_Image im, char *file,
+ Imlib_Load_Error * error_return);
+void gib_imlib_free_font(Imlib_Font fn);
+void gib_imlib_free_image(Imlib_Image im);
+void gib_imlib_image_draw_line(Imlib_Image im, int x1, int y1, int x2, int y2,
+ char make_updates, int r, int g, int b, int a);
+void gib_imlib_image_set_has_alpha(Imlib_Image im, int alpha);
+void gib_imlib_free_font(Imlib_Font fn);
+Imlib_Image gib_imlib_create_rotated_image(Imlib_Image im, double angle);
+void gib_imlib_image_tile(Imlib_Image im);
+void gib_imlib_image_blur(Imlib_Image im, int radius);
+void gib_imlib_image_sharpen(Imlib_Image im, int radius);
+void gib_imlib_image_draw_rectangle(Imlib_Image im, int x, int y, int w,
+ int h, int r, int g, int b, int a);
+void gib_imlib_line_clip_and_draw(Imlib_Image dest, int x0, int y0, int x1,
+ int y1, int cx, int cy, int cw, int ch,
+ int r, int g, int b, int a);
+void gib_imlib_image_fill_polygon(Imlib_Image im, ImlibPolygon poly, int r,
+ int g, int b, int a, unsigned char alias,
+ int cx, int cy, int cw, int ch);
+void gib_imlib_image_draw_polygon(Imlib_Image im, ImlibPolygon poly, int r,
+ int g, int b, int a, unsigned char closed,
+ unsigned char alias, int cx, int cy, int cw,
+
+ int ch);
+Imlib_Image gib_imlib_create_image_from_drawable(Drawable d, Pixmap mask,
+ int x, int y, int width,
+
+ int height,
+ char need_to_grab_x);
+void gib_imlib_parse_color(char *col, int *r, int *g, int *b, int *a);
+void gib_imlib_parse_fontpath(char *path);
+Imlib_Font gib_imlib_load_font(char *name);
+void gib_imlib_image_orientate(Imlib_Image im, int orientation);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/gib_list.c b/src/gib_list.c
new file mode 100644
index 0000000..bb16d52
--- /dev/null
+++ b/src/gib_list.c
@@ -0,0 +1,624 @@
+/* gib_list.c
+
+Copyright (C) 1999,2000 Tom Gilbert.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#include <time.h>
+#include "gib_list.h"
+#include "gib_utils.h"
+
+gib_list *
+gib_list_new(void)
+{
+ gib_list *l;
+
+ l = (gib_list *) malloc(sizeof(gib_list));
+ l->data = NULL;
+ l->next = NULL;
+ l->prev = NULL;
+ return (l);
+}
+
+void
+gib_list_free(gib_list * l)
+{
+ gib_list *ll;
+
+ if (!l)
+ return;
+
+ while (l)
+ {
+ ll = l;
+ l = l->next;
+ free(ll);
+ }
+
+ return;
+}
+
+void
+gib_list_free_and_data(gib_list * l)
+{
+ gib_list *ll;
+
+ if (!l)
+ return;
+
+ while (l)
+ {
+ ll = l;
+ l = l->next;
+ free(ll->data);
+ free(ll);
+ }
+ return;
+}
+
+gib_list *
+gib_list_dup(gib_list * list)
+{
+ gib_list *ret = NULL;
+
+ if (list)
+ {
+ gib_list *last;
+
+ ret = gib_list_new();
+ ret->data = list->data;
+ last = ret;
+ list = list->next;
+ while (list)
+ {
+ last->next = gib_list_new();
+ last->next->prev = last;
+ last = last->next;
+ last->data = list->data;
+ list = list->next;
+ }
+ }
+ return (ret);
+}
+
+gib_list *
+gib_list_dup_special(gib_list * list,
+ void (*cpy_func) (void **dest, void *data))
+{
+ gib_list *ret = NULL;
+
+ if (list)
+ {
+ gib_list *last;
+
+ ret = gib_list_new();
+ cpy_func(&(ret->data), list->data);
+ last = ret;
+ list = list->next;
+ while (list)
+ {
+ last->next = gib_list_new();
+ last->next->prev = last;
+ last = last->next;
+ cpy_func(&(last->data), list->data);
+ list = list->next;
+ }
+ }
+ return (ret);
+}
+
+gib_list *
+gib_list_add_front(gib_list * root, void *data)
+{
+ gib_list *l;
+
+ l = gib_list_new();
+ l->next = root;
+ l->data = data;
+ if (root)
+ root->prev = l;
+ return (l);
+}
+
+gib_list *
+gib_list_add_end(gib_list * root, void *data)
+{
+ gib_list *l, *last;
+
+ last = gib_list_last(root);
+ l = gib_list_new();
+ l->prev = last;
+ l->data = data;
+ if (last)
+ {
+ last->next = l;
+ return (root);
+ }
+ else
+ {
+ return (l);
+ }
+}
+
+gib_list *
+gib_list_add_at_pos(gib_list * root, int pos, void *data)
+{
+ gib_list *l, *top;
+
+ if (pos == gib_list_length(root))
+ root = gib_list_add_end(root, data);
+ else if (pos == 0)
+ root = gib_list_add_front(root, data);
+ else
+ {
+ top = gib_list_nth(root, pos);
+
+ if (!top)
+ return (root);
+
+ l = gib_list_new();
+ l->next = top;
+ l->prev = top->prev;
+ l->data = data;
+ if (top->prev)
+ top->prev->next = l;
+
+ top->prev = l;
+ }
+ return (root);
+}
+
+gib_list *
+gib_list_move_up_by_one(gib_list * root, gib_list * l)
+{
+ if (l || l->prev)
+ root = gib_list_move_down_by_one(root, l->prev);
+ return (root);
+}
+
+gib_list *
+gib_list_move_down_by_one(gib_list * root, gib_list * l)
+{
+ gib_list *temp;
+
+ if (!l || !l->next)
+ return (root);
+
+ /* store item we link next to */
+ temp = l->next;
+ /* remove from list */
+ root = gib_list_unlink(root, l);
+ /* add back one before */
+ l->next = temp->next;
+ l->prev = temp;
+ if (temp->next)
+ temp->next->prev = l;
+ temp->next = l;
+
+ return (root);
+}
+
+
+unsigned char
+gib_list_has_more_than_one_item(gib_list * root)
+{
+ if (root->next)
+ return (1);
+ else
+ return (0);
+}
+
+gib_list *
+gib_list_pop_to_end(gib_list * root, gib_list * l)
+{
+ root = gib_list_unlink(root, l);
+ root = gib_list_add_end(root, l->data);
+ free(l);
+
+ return (root);
+}
+
+gib_list *
+gib_list_cat(gib_list * root, gib_list * l)
+{
+ gib_list *last;
+
+ if (!l)
+ return (root);
+ if (!root)
+ return (l);
+ last = gib_list_last(root);
+ last->next = l;
+ l->prev = last;
+ return (root);
+}
+
+int
+gib_list_length(gib_list * l)
+{
+ int length;
+
+ length = 0;
+ while (l)
+ {
+ length++;
+ l = l->next;
+ }
+ return (length);
+}
+
+gib_list *
+gib_list_last(gib_list * l)
+{
+ if (l)
+ {
+ while (l->next)
+ l = l->next;
+ }
+ return (l);
+}
+
+gib_list *
+gib_list_first(gib_list * l)
+{
+ if (l)
+ {
+ while (l->prev)
+ l = l->prev;
+ }
+ return (l);
+}
+
+gib_list *
+gib_list_jump(gib_list * root, gib_list * l, int direction, int num)
+{
+ int i;
+ gib_list *ret = NULL;
+
+ if (!root)
+ return (NULL);
+ if (!l)
+ return (root);
+
+ ret = l;
+
+ for (i = 0; i < num; i++)
+ {
+ if (direction == FORWARD)
+ {
+ if (ret->next)
+ ret = ret->next;
+ else
+ ret = root;
+ }
+ else
+ {
+ if (ret->prev)
+ ret = ret->prev;
+ else
+ ret = gib_list_last(ret);
+ }
+ }
+ return (ret);
+}
+
+gib_list *
+gib_list_reverse(gib_list * l)
+{
+ gib_list *last;
+
+ last = NULL;
+ while (l)
+ {
+ last = l;
+ l = last->next;
+ last->next = last->prev;
+ last->prev = l;
+ }
+ return (last);
+}
+
+gib_list *
+gib_list_randomize(gib_list * list)
+{
+ int len, r, i;
+ gib_list **farray, *f, *t;
+
+ if (!list)
+ return (NULL);
+ len = gib_list_length(list);
+ if (len <= 1)
+ return (list);
+ farray = (gib_list **) malloc(sizeof(gib_list *) * len);
+ for (f = list, i = 0; f; f = f->next, i++)
+ {
+ farray[i] = f;
+ }
+ srand(getpid() * time(NULL) % ((unsigned int) -1));
+ for (i = 0; i < len - 1; i++)
+ {
+ r = (int) ((len - i - 1) * ((float) rand()) / (RAND_MAX + 1.0)) + i + 1;
+ if (i == r)
+ abort();
+ t = farray[i];
+ farray[i] = farray[r];
+ farray[r] = t;
+ }
+ list = farray[0];
+ list->prev = NULL;
+ list->next = farray[1];
+ for (i = 1, f = farray[1]; i < len - 1; i++, f = f->next)
+ {
+ f->prev = farray[i - 1];
+ f->next = farray[i + 1];
+ }
+ f->prev = farray[len - 2];
+ f->next = NULL;
+ free(farray);
+ return (list);
+}
+
+int
+gib_list_num(gib_list * root, gib_list * l)
+{
+ int i = 0;
+
+ while (root)
+ {
+ if (root == l)
+ return (i);
+ i++;
+ root = root->next;
+ }
+ return (-1);
+}
+
+gib_list *
+gib_list_unlink(gib_list * root, gib_list * l)
+{
+ if (!l)
+ return (root);
+
+ if ((!root) || ((l == root) && (!l->next)))
+ return (NULL);
+
+ if (l->prev)
+ l->prev->next = l->next;
+ if (l->next)
+ l->next->prev = l->prev;
+ if (root == l)
+ root = root->next;
+ return (root);
+}
+
+
+gib_list *
+gib_list_remove(gib_list * root, gib_list * l)
+{
+ root = gib_list_unlink(root, l);
+ free(l);
+ return (root);
+}
+
+gib_list *
+gib_list_sort(gib_list * list, gib_compare_fn cmp)
+{
+ gib_list *l1, *l2;
+
+ if (!list)
+ return (NULL);
+ if (!list->next)
+ return (list);
+
+ l1 = list;
+ l2 = list->next;
+
+ while ((l2 = l2->next) != NULL)
+ {
+ if ((l2 = l2->next) == NULL)
+ break;
+ l1 = l1->next;
+ }
+ l2 = l1->next;
+ l1->next = NULL;
+
+ return (gib_list_sort_merge
+ (gib_list_sort(list, cmp), gib_list_sort(l2, cmp), cmp));
+}
+
+gib_list *
+gib_list_sort_merge(gib_list * l1, gib_list * l2, gib_compare_fn cmp)
+{
+ gib_list list, *l, *lprev;
+
+ l = &list;
+ lprev = NULL;
+
+ while (l1 && l2)
+ {
+ if (cmp(l1->data, l2->data) < 0)
+ {
+ l->next = l1;
+ l = l->next;
+ l->prev = lprev;
+ lprev = l;
+ l1 = l1->next;
+ }
+ else
+ {
+ l->next = l2;
+ l = l->next;
+ l->prev = lprev;
+ lprev = l;
+ l2 = l2->next;
+ }
+ }
+ l->next = l1 ? l1 : l2;
+ l->next->prev = l;
+
+ return (list.next);
+}
+
+gib_list *
+gib_list_nth(gib_list * root, unsigned int num)
+{
+ unsigned int i;
+ gib_list *l;
+
+ if (num > (unsigned int) gib_list_length(root))
+ return (gib_list_last(root));
+ l = root;
+ for (i = 0; l; ++i)
+ {
+ if (i == num)
+ return (l);
+ l = l->next;
+ }
+ return (root);
+}
+
+gib_list *
+gib_list_foreach(gib_list *root, void (*fe_func)(gib_list *node, void *data), void *data)
+{
+ gib_list *i, *next = NULL;
+ for (i=root; i; i=next) {
+ next=i->next;
+ fe_func(i, data);
+ }
+ return root;
+}
+
+gib_list *
+gib_list_find(gib_list *root, unsigned char (*find_func)(gib_list *node, void *data), void *data)
+{
+ gib_list *i = NULL;
+ for (i=root; i; i=i->next)
+ if (find_func(i,data))
+ return i;
+
+ return NULL;
+}
+
+static unsigned char gib_list_find_by_data_callback(gib_list *list, void *data)
+{
+ return (list->data==data);
+}
+
+gib_list *
+gib_list_find_by_data(gib_list *root, void *data)
+{
+ return gib_list_find(root, gib_list_find_by_data_callback, data);
+}
+
+gib_list *
+gib_string_split(const char *string, const char *delimiter)
+{
+ gib_list *string_list = NULL;
+ char *s;
+ unsigned int n = 1;
+
+ if (!string || !delimiter)
+ return NULL;
+
+ s = strstr(string, delimiter);
+ if (s)
+ {
+ unsigned int delimiter_len = strlen(delimiter);
+
+ do
+ {
+ unsigned int len;
+ char *new_string;
+
+ len = s - string;
+ new_string = malloc(sizeof(char) * (len + 1));
+
+ strncpy(new_string, string, len);
+ new_string[len] = 0;
+ string_list = gib_list_add_front(string_list, new_string);
+ n++;
+ string = s + delimiter_len;
+ s = strstr(string, delimiter);
+ }
+ while (s);
+ }
+ if (*string)
+ {
+ n++;
+ string_list = gib_list_add_front(string_list, strdup((char *)string));
+ }
+
+ string_list = gib_list_reverse(string_list);
+
+ return string_list;
+}
+
+
+char *
+gib_strjoin(const char *separator, ...)
+{
+ char *string, *s;
+ va_list args;
+ int len;
+ int separator_len;
+
+ if (separator == NULL)
+ separator = "";
+
+ separator_len = strlen(separator);
+ va_start(args, separator);
+ s = va_arg(args, char *);
+
+ if (s)
+ {
+ len = strlen(s);
+ s = va_arg(args, char *);
+
+ while (s)
+ {
+ len += separator_len + strlen(s);
+ s = va_arg(args, char *);
+ }
+ va_end(args);
+ string = malloc(sizeof(char) * (len + 1));
+
+ *string = 0;
+ va_start(args, separator);
+ s = va_arg(args, char *);
+
+ strcat(string, s);
+ s = va_arg(args, char *);
+
+ while (s)
+ {
+ strcat(string, separator);
+ strcat(string, s);
+ s = va_arg(args, char *);
+ }
+ }
+ else
+ string = strdup("");
+ va_end(args);
+
+ return string;
+}
+
diff --git a/src/gib_list.h b/src/gib_list.h
new file mode 100644
index 0000000..9eedae5
--- /dev/null
+++ b/src/gib_list.h
@@ -0,0 +1,97 @@
+/* gib_list.h
+
+Copyright (C) 1999,2000 Tom Gilbert.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#ifndef GIB_LIST_H
+#define GIB_LIST_H
+
+#include <stdarg.h>
+
+#define GIB_LIST(a) ((gib_list*)a)
+
+enum __direction
+{ FORWARD, BACK };
+
+typedef struct __gib_list gib_list;
+
+struct __gib_list
+{
+ void *data;
+
+ gib_list *next;
+ gib_list *prev;
+};
+
+typedef int (gib_compare_fn) (void *data1, void *data2);
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+gib_list *gib_list_new(void);
+void gib_list_free(gib_list * l);
+gib_list *gib_list_add_front(gib_list * root, void *data);
+gib_list *gib_list_add_end(gib_list * root, void *data);
+gib_list *gib_list_add_at_pos(gib_list * root, int pos, void *data);
+gib_list *gib_list_pop_to_end(gib_list * root, gib_list * l);
+gib_list *gib_list_unlink(gib_list * root, gib_list * l);
+gib_list *gib_list_cat(gib_list * root, gib_list * l);
+int gib_list_length(gib_list * l);
+gib_list *gib_list_last(gib_list * l);
+gib_list *gib_list_first(gib_list * l);
+gib_list *gib_list_jump(gib_list * root, gib_list * l, int direction,
+
+ int num);
+gib_list *gib_list_reverse(gib_list * l);
+gib_list *gib_list_randomize(gib_list * list);
+int gib_list_num(gib_list * root, gib_list * l);
+gib_list *gib_list_remove(gib_list * root, gib_list * l);
+gib_list *gib_list_sort(gib_list * list, gib_compare_fn cmp);
+gib_list *gib_list_sort_merge(gib_list * l1, gib_list * l2,
+
+ gib_compare_fn cmp);
+gib_list *gib_list_nth(gib_list * root, unsigned int num);
+unsigned char gib_list_has_more_than_one_item(gib_list * root);
+void gib_list_free_and_data(gib_list * l);
+gib_list *gib_list_dup(gib_list * list);
+gib_list *gib_list_dup_special(gib_list * list,
+ void (*cpy_func) (void **dest, void *data));
+gib_list *gib_list_move_down_by_one(gib_list * root, gib_list * l);
+gib_list *gib_list_move_up_by_one(gib_list * root, gib_list * l);
+
+gib_list *gib_list_foreach(gib_list *root, void (*fe_func)(gib_list *node, void *data), void *data);
+gib_list *gib_list_find(gib_list *root, unsigned char (*find_func)(gib_list *node, void *data), void *data);
+gib_list *gib_list_find_by_data(gib_list *root, void *data);
+
+/* don't really belong here, will do for now */
+gib_list *gib_string_split(const char *string, const char *delimiter);
+char *gib_strjoin(const char *separator, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/gib_style.c b/src/gib_style.c
new file mode 100644
index 0000000..8fd5ae5
--- /dev/null
+++ b/src/gib_style.c
@@ -0,0 +1,241 @@
+/* gib_style.c
+
+Copyright (C) 1999,2000 Tom Gilbert.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#include "gib_style.h"
+#include "gib_utils.h"
+
+gib_style *
+gib_style_new(char *name)
+{
+ gib_style *s = NULL;
+
+ s = malloc(sizeof(gib_style));
+
+ memset(s, 0, sizeof(gib_style));
+ if (name)
+ s->name = strdup(name);
+
+ return (s);
+}
+
+void
+gib_style_free(gib_style * s)
+{
+ if (s)
+ {
+ if (s->name)
+ free(s->name);
+ if (s->bits)
+ {
+ gib_list *l;
+
+ l = s->bits;
+ while (l)
+ {
+ gib_style_bit_free((gib_style_bit *) l->data);
+ l = l->next;
+ }
+ gib_list_free(s->bits);
+ }
+ free(s);
+ }
+ return;
+}
+
+gib_style_bit *
+gib_style_bit_new(int x_offset, int y_offset, int r, int g, int b, int a)
+{
+ gib_style_bit *sb;
+
+ sb = malloc(sizeof(gib_style_bit));
+ memset(sb, 0, sizeof(gib_style_bit));
+
+ sb->x_offset = x_offset;
+ sb->y_offset = y_offset;
+ sb->r = r;
+ sb->g = g;
+ sb->b = b;
+ sb->a = a;
+
+ return (sb);
+}
+
+void
+gib_style_bit_free(gib_style_bit * s)
+{
+ if (s)
+ free(s);
+ return;
+}
+
+gib_style *
+gib_style_dup(gib_style * s)
+{
+ gib_style *ret;
+
+ ret = gib_style_new(s->name);
+ ret->bits = gib_list_dup_special(s->bits, gib_dup_style_bit);
+
+ return (ret);
+}
+
+void
+gib_dup_style_bit(void **dest, void *data)
+{
+ *dest = malloc(sizeof(gib_style_bit));
+ memcpy(*dest, data, sizeof(gib_style_bit));
+
+ return;
+}
+
+void
+gib_style_save_ascii(gib_style * style, char *file)
+{
+ FILE *stylefile;
+ gib_list *l;
+ gib_style_bit *b;
+
+ if (!style || !style->bits)
+ return;
+
+ stylefile = fopen(file, "w");
+ if (stylefile)
+ {
+ fprintf(stylefile, "#Style\n");
+ fprintf(stylefile, "#NAME %s\n", style->name);
+ l = style->bits;
+ while (l)
+ {
+ b = (gib_style_bit *) l->data;
+ fprintf(stylefile, "%d %d %d %d %d %d\n", b->r, b->g, b->b, b->a,
+ b->x_offset, b->y_offset);
+ l = l->next;
+ }
+ }
+ fclose(stylefile);
+}
+
+gib_style *
+gib_style_new_from_ascii(char *file)
+{
+ FILE *stylefile;
+ char current[4096];
+ char *s;
+ gib_style *ret = NULL;
+
+ stylefile = fopen(file, "r");
+ if (stylefile)
+ {
+ int r = 0, g = 0, b = 0, a = 0, x_off = 0, y_off = 0;
+
+ ret = gib_style_new(NULL);
+ /* skip initial idenifier line */
+ fgets(current, sizeof(current), stylefile);
+ while (fgets(current, sizeof(current), stylefile))
+ {
+ if (current[0] == '\n')
+ continue;
+ if (!strncmp(current, "#NAME", 5))
+ {
+ int l;
+
+ l = strlen(current) - 1;
+ if (current[l] == '\n')
+ current[l] = '\0';
+ if (l > 6)
+ ret->name = strdup(current + 6);
+ continue;
+ }
+ else
+ {
+ /* support EFM style bits */
+ s = strtok(current, " ");
+ if(!s) continue;
+ if (strlen(s) == 2)
+ {
+ if (!strcmp(s, "ol"))
+ {
+ r = g = b = 0;
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ x_off = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ y_off = atoi(s);
+ }
+ else if (!strcmp(s, "sh"))
+ {
+ r = g = b = 0;
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ x_off = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ y_off = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ a = atoi(s);
+ }
+ else if (!strcmp(s, "fg"))
+ {
+ r = g = b = a = 0;
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ x_off = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ y_off = atoi(s);
+ }
+ }
+ else
+ {
+ /* our own format */
+ r = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ g = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ b = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ a = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ x_off = atoi(s);
+ s = strtok(NULL, " ");
+ if(!s) continue;
+ y_off = atoi(s);
+ }
+ }
+ ret->bits =
+ gib_list_add_end(ret->bits,
+ gib_style_bit_new(x_off, y_off, r, g, b, a));
+ }
+ fclose(stylefile);
+ }
+
+ return (ret);
+}
diff --git a/src/gib_style.h b/src/gib_style.h
new file mode 100644
index 0000000..ed7920a
--- /dev/null
+++ b/src/gib_style.h
@@ -0,0 +1,70 @@
+/* gib_style.h
+
+Copyright (C) 1999,2000 Tom Gilbert.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+
+#ifndef GIB_STYLE_H
+#define GIB_STYLE_H
+
+#include "gib_list.h"
+
+#define GIB_STYLE(O) ((gib_style *)O)
+#define GIB_STYLE_BIT(O) ((gib_style_bit *)O)
+
+typedef struct __gib_style_bit gib_style_bit;
+typedef struct __gib_style gib_style;
+
+struct __gib_style_bit
+{
+ int x_offset, y_offset;
+ int r,g,b,a;
+};
+
+struct __gib_style
+{
+ gib_list *bits;
+ char *name;
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+gib_style_bit *gib_style_bit_new(int x_offset, int y_offset, int r, int g, int b, int a);
+gib_style *gib_style_new(char *name);
+void gib_style_bit_free(gib_style_bit *s);
+void gib_style_free(gib_style *s);
+gib_style *gib_style_dup(gib_style *s);
+void gib_dup_style_bit(void **dest, void *data);
+gib_style *gib_style_new_from_ascii(char *file);
+void gib_style_save_ascii(gib_style * style, char *file);
+gib_style *gib_style_new_from_ascii(char *file);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/gib_utils.c b/src/gib_utils.c
new file mode 100644
index 0000000..e851b0d
--- /dev/null
+++ b/src/gib_utils.c
@@ -0,0 +1,121 @@
+/* gib_utils.c
+
+Copyright (C) 1999,2000 Tom Gilbert.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#include "gib_utils.h"
+
+/* eprintf: print error message and exit */
+void
+gib_eprintf(char *fmt, ...)
+{
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "giblib error: ");
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':')
+ fprintf(stderr, "%s", strerror(errno));
+ fprintf(stderr, "\n");
+ exit(2);
+}
+
+/* weprintf: print warning message and continue */
+void
+gib_weprintf(char *fmt, ...)
+{
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "giblib warning: ");
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':')
+ fprintf(stderr, "%s", strerror(errno));
+ fprintf(stderr, "\n");
+}
+
+/* estrdup: duplicate a string, report if error */
+char *
+_strdup(char *s)
+{
+ char *t;
+ if(!s)
+ return NULL;
+ t = (char *) malloc(strlen(s) + 1);
+ if (t == NULL)
+ gib_eprintf("estrdup(\"%.20s\") failed:", s);
+ strcpy(t, s);
+ return t;
+}
+
+/* emalloc: malloc and report if error */
+void *
+_malloc(size_t n)
+{
+ void *p;
+
+ p = malloc(n);
+ if (p == NULL)
+ gib_eprintf("malloc of %u bytes failed:", n);
+ return p;
+}
+
+/* erealloc: realloc and report if error */
+void *
+_realloc(void *ptr, size_t n)
+{
+ void *p;
+
+ p = realloc(ptr, n);
+ if (p == NULL)
+ gib_eprintf("realloc of %p by %u bytes failed:", ptr, n);
+ return p;
+}
+
+/* efree: just do the free for now */
+void
+_free(void *p)
+{
+ free(p);
+}
+
+char *
+gib_stroflen(char c, int l)
+{
+ static char buf[1024];
+ int i = 0;
+
+ buf[0] = '\0';
+ while (l--)
+ buf[i++] = c;
+ buf[i] = '\0';
+ return buf;
+}
diff --git a/src/gib_utils.h b/src/gib_utils.h
new file mode 100644
index 0000000..82ef878
--- /dev/null
+++ b/src/gib_utils.h
@@ -0,0 +1,53 @@
+/* gib_utils.h
+
+Copyright (C) 1999,2000 Tom Gilbert.
+
+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 of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+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 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.
+
+*/
+
+#ifndef GIB_UTILS_H
+#define GIB_UTILS_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void gib_eprintf(char *fmt, ...);
+void gib_weprintf(char *fmt, ...);
+char *_strdup(char *s);
+void *_malloc(size_t n);
+void _free(void *p);
+void *_realloc(void *ptr, size_t n);
+char *gib_stroflen(char c, int l);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/imlib.c b/src/imlib.c
index 60cb267..69962ee 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -162,14 +162,14 @@ void ungib_imlib_save_image_with_error_return(Imlib_Image im, char *file,
tmp = strrchr(file, '.');
if (tmp) {
char *p, *pp;
- p = gib_estrdup(tmp + 1);
+ p = estrdup(tmp + 1);
pp = p;
while(*pp) {
*pp = tolower(*pp);
pp++;
}
imlib_image_set_format(p);
- gib_efree(p);
+ free(p);
}
imlib_save_image_with_error_return(file, error_return);
}