#include "coolwidget.h"
#include "icon.h"
#include "coollocal.h"
#include "mad.h"

void edit_tri_cursor (Window win);

static char *file_xpm[] = {
/* width height ncolors chars_per_pixel */
"32 32 5 1",
/* colors */
"` c black",
"a c gray",
"c c black",
"d s none c none",
"e c white",
/* pixels */
"dddd``````````````````dddddddddd",
"dddd`eeeeeeeeeeeeeeee``ddddddddd",
"dddd`eeeeeeeeeeeeeeee`a`dddddddd",
"dddd`eeeeeeeeeeeeeeee`aa`ddddddd",
"dddd`eeeeeeeeeeeeeeee`aaa`dddddd",
"dddd`eeeeeeeeeeeeeeee`aaaa`ddddd",
"dddd`eeeeeeeeeeeeeeee```````dddd",
"dddd`eeeeeeeeeeeeeeeeeaaaaa`cddd",
"dddd`eeeeeeeeeeeeeeeeeeaaaa`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
"dddd````````````````````````cddd",
"dddddccccccccccccccccccccccccddd"
};

static int eh_icon (CWidget * w, XEvent * xevent, CEvent * cwevent)
{
    static int windowx, windowy;
    static int wx = 0, wy = 0;
    static int wwidth = 0, wheight = 0;
    static int allowwindowmove = 0;

    switch (xevent->type) {
    case Expose:
	if (!xevent->xexpose.count && !allowwindowmove) {
	    CPowerIcon *i;
	    time_t t;
	    i = (CPowerIcon *) w->user;
	    if (i) {
		time (&t);
		if (i->last_expose != t) {
		    XLowerWindow (CDisplay, xevent->xexpose.window);
		    i->last_expose = t;
		}
	    }
	}
	break;
    case MappingNotify:
	XLowerWindow (CDisplay, w->winid);
	break;
    case ClientMessage:
	if (!w->disabled)
	    cwevent->ident = w->ident;
	break;
    case ButtonRelease:
	XLowerWindow (CDisplay, w->winid);
	resolve_button (xevent, cwevent);
	allowwindowmove = 0;
	break;
    case ButtonPress:
	resolve_button (xevent, cwevent);
	cwevent->ident = w->ident;
	XRaiseWindow (CDisplay, w->winid);
	windowx = xevent->xbutton.x_root - w->x;
	windowy = xevent->xbutton.y_root - w->y;
	wx = xevent->xbutton.x;
	wy = xevent->xbutton.y;
	wwidth = w->width;
	wheight = w->height;
	allowwindowmove = 1;
	break;
    case MotionNotify:
	resolve_button (xevent, cwevent);
	if (!(w->position & WINDOW_UNMOVEABLE) && allowwindowmove && (cwevent->state & (Button1Mask | Button2Mask))) {
	    w->x = xevent->xmotion.x_root - windowx;
	    w->y = xevent->xmotion.y_root - windowy;
	    if (w->x + xevent->xmotion.x < 2)
		w->x = -wx + 2;
	    if (w->y + xevent->xmotion.y < 2)
		w->y = -wy + 2;
	    XMoveWindow (CDisplay, w->winid, w->x, w->y);
	}
	break;
    }
    return 0;
}



void destroy_icon (CWidget * w)
{
    CIcon *icon;
    icon = (CIcon *) w->hook;
    if (!icon)
	return;
    if (icon->picture) {
	XFreePixmap (CDisplay, icon->picture);
	if (icon->mask)
	    XFreePixmap (CDisplay, icon->mask);
	XFreeColors (CDisplay, CColormap,
		   icon->attributes.pixels, icon->attributes.npixels, 0);
	XpmFreeAttributes (&icon->attributes);
    }
    if (icon->xpm_filename)
	free (icon->xpm_filename);
    if (icon->title)
	free (icon->title);
    free (icon);
    w->hook = 0;
}

static void draw_icon_title (CIcon * icon, int ox, int oy, int width, Window win, GC * gc)
{
    int done = 0, h = 0;
    char *title;
    title = icon->title;
    while (!done) {
	int wl;
	char *p;
	p = strchr (title, '\n');
	if (!p) {
	    done = 1;
	    p = title + strlen ((char *) title);
	}
	wl = XTextWidth (CFontStruct, title, (unsigned long) p - (unsigned long) title);
	XDrawString (CDisplay, win, *gc,
		     FONT_OFFSET_X + (width - wl) / 2 + ox,
	  FONT_OFFSET_Y + icon->attributes.height + oy + 2 + h,
		     title,
		     (unsigned long) p - (unsigned long) title);
	h += FONT_PIX_PER_LINE;
	title = p + 1;
    }
}

CWidget *CDrawIcon (const char *identifier, Window parent, int x, int y, const char *filename, char *title)
{
    Window win;
    CIcon *icon;
    GC gc;
    XGCValues gcv;
    XImage *ximage, *shapeimage;

    int width, height, fwidth, fheight, title_offset, have_title = 0;

    if (title)
	if (*title)
	    have_title = 1;

    icon = CMalloc (sizeof (CIcon));
    memset (icon, 0, sizeof (CIcon));

    icon->attributes.valuemask =
	XpmReturnPixels | XpmReturnInfos | XpmCloseness
	| XpmVisual | XpmColormap | XpmDepth;
    icon->attributes.colormap = CColormap;
    icon->attributes.visual = CVisual;
    icon->attributes.depth = CDepth;
    icon->attributes.closeness = 40000;

    if (XpmReadFileToImage (CDisplay, (char *) filename, &ximage, &shapeimage,
			    &icon->attributes) != XpmSuccess) {
	XpmCreateImageFromData (CDisplay, file_xpm, &ximage, &shapeimage,
				&icon->attributes);
	CErrorDialog (CRoot, 20, 20, _ (" Create Icon "), get_sys_error (_ (" Error trying to read file `%s' into an XImage ")), filename);
    }
    if (have_title) {
	CTextSize (&fwidth, &fheight, title);
	fwidth += 4;
	fheight += 4;
	title_offset = 0;
    } else {
	fwidth = fheight = 0;
	title_offset = 0;
    }

    width = max (fwidth, icon->attributes.width);
    height = fheight + icon->attributes.height + title_offset;

    icon->w = CSetupWidget (identifier, parent, x, y,
	     width, height, C_ICON_WIDGET, INPUT_BUTTON, COLOR_WHITE, 0);
    edit_tri_cursor (icon->w->winid);
    icon->w->hook = (void *) icon;
    icon->w->destroy = destroy_icon;
    icon->w->position |= WINDOW_ALWAYS_LOWERED;
    icon->w->eh = eh_icon;
    icon->xpm_filename = (char *) strdup (filename);
    icon->title = (char *) strdup (title ? title : "");

    win = icon->w->winid;
    icon->picture = XCreatePixmap (CDisplay, win, width, height, CDepth);
    CSetColor (COLOR_BLACK);
    XFillRectangle (CDisplay, icon->picture, CGC, 0, 0, width, height);

    if (have_title) {
	CSetColor (COLOR_WHITE);
	XFillRectangle (CDisplay, icon->picture, CGC,
			(width - fwidth) / 2 + 1, icon->attributes.height + title_offset + 1,
			fwidth - 2, fheight - 2);
    }
    XPutImage (CDisplay, icon->picture, CGC, ximage, 0, 0,
	       (width - icon->attributes.width) / 2, 0,
	       icon->attributes.width, icon->attributes.height);

    CSetColor (COLOR_BLACK);

    if (have_title)
	draw_icon_title (icon, 0, title_offset, width, icon->picture, &CGC);
    icon->mask = XCreatePixmap (CDisplay, win, width, height, 1);

/* we need a GC of depth 1, so we create one just for this function */
    gcv.font = CFontStruct->fid;
    gc = XCreateGC (CDisplay, icon->mask, GCFont, &gcv);

    XSetForeground (CDisplay, gc, 0);
    XFillRectangle (CDisplay, icon->mask, gc, 0, 0, width, height);
    XSetForeground (CDisplay, gc, 1);
    if (shapeimage != NULL)
	XPutImage (CDisplay, icon->mask, gc, shapeimage, 0, 0,
		   (width - icon->attributes.width) / 2, 0, icon->attributes.width, icon->attributes.height);
    else
	XFillRectangle (CDisplay, icon->mask, gc,
			(width - icon->attributes.width) / 2, 0, icon->attributes.width, icon->attributes.height);

    if (have_title) {
#if 0
	XFillRectangle (CDisplay, icon->mask, gc,
	    (width - fwidth) / 2, icon->attributes.height + title_offset,
			fwidth, fheight);
#else
	draw_icon_title (icon, 0, title_offset, width, icon->mask, &gc);
	draw_icon_title (icon, 1, title_offset, width, icon->mask, &gc);
	draw_icon_title (icon, 0, title_offset + 1, width, icon->mask, &gc);
	draw_icon_title (icon, -1, title_offset + 0, width, icon->mask, &gc);
	draw_icon_title (icon, 0, title_offset - 1, width, icon->mask, &gc);

	draw_icon_title (icon, 1, title_offset + 1, width, icon->mask, &gc);
	draw_icon_title (icon, -1, title_offset + 1, width, icon->mask, &gc);
	draw_icon_title (icon, 1, title_offset - 1, width, icon->mask, &gc);
	draw_icon_title (icon, -1, title_offset - 1, width, icon->mask, &gc);
#endif
    }
    XFreeGC (CDisplay, gc);
    XDestroyImage (ximage);
    if (shapeimage != NULL)
	XDestroyImage (shapeimage);

    XSetWindowBackgroundPixmap (CDisplay, win, icon->picture);

    XShapeCombineMask (CDisplay, win, ShapeBounding, 0, 0,
		       icon->mask, ShapeSet);
    XClearWindow (CDisplay, win);
    return icon->w;
}

