/*
 *	(c) Copyright 1991 Sun Microsystems, Inc.  All rights reserved.
 *	See LEGAL_NOTICE file for terms and restrictions.
 */

#ifndef lint
#ifdef sccs
static char     sccsid[] = "@(#)drawimage.c 1.18 91/05/06";
#endif
#endif

/*
 * issues:
 * - not handling different sized in highlight and normal images.
 * - should checks for equivalent depth pixmaps be inforced on set call?
 *   or should only one plane of the pixmap be copyied when destination
 *   and source depths don't match?
 */
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <xview/rect.h>
#include <xview/xv_xrect.h>
#include <xview/win_input.h>
#include <sspkg/drawobj.h>
#include "r_impl.h"
#include "do_impl.h"
#include <sspkg/canshell.h>

Pkg_private int 	drawimage_init();
Pkg_private Xv_opaque	drawimage_set_avlist();
Pkg_private Xv_opaque	drawimage_get_attr();
Pkg_private int 	drawimage_destroy();

void	drawimage_paint_proc();
void	render_image();

/*ARGSUSED*/
Pkg_private int
drawimage_init(parent, drawimage_public, avlist)
	Xv_opaque	parent;
	Drawimage		drawimage_public;
	Attr_avlist	avlist;
{
	Drawimage_info	*dinfo;
	Drawimage_struct	*drawimage_object;
	extern int start_dbl_click();

	dinfo = xv_alloc(Drawimage_info);
	dinfo->public_self = drawimage_public;
	drawimage_object = (Drawimage_struct*) drawimage_public;
	drawimage_object->private_data = (Xv_opaque) dinfo;

	xv_set(drawimage_public, 
		RECTOBJ_PAINT_PROC, drawimage_paint_proc, 
		RECTOBJ_EVENT_PROC, start_dbl_click,
		RECTOBJ_SELECTABLE, TRUE,
		NULL);

	return(XV_OK);
}


Pkg_private Xv_opaque
drawimage_set_avlist(drawimage_public, avlist)
	Drawimage		drawimage_public;
	register Attr_avlist	avlist;
{
        register Drawimage_attr attr;
        register Drawimage_info *dinfo = DRAWIMAGE_PRIVATE(drawimage_public);
        register Rectobj_info  *rinfo = RECTOBJ_PRIVATE(drawimage_public);


	if(*avlist != XV_END_CREATE) {
		Xv_opaque set_result;
		set_result = 
		    xv_super_set_avlist(drawimage_public, &drawimage_pkg, avlist);
		if(set_result != XV_OK) {
			rectobj_reset_set_info(drawimage_public);
			return(set_result);
		}
	}

	while (attr = (Drawimage_attr) * avlist++)
	  switch (attr) {

		case DRAWIMAGE_SVRIMAGE:
			dinfo->server_image = (Server_image)*avlist++;
			if(dinfo->server_image == 0)
				break;
			rinfo->rect.r_width = xv_get(dinfo->server_image, XV_WIDTH);
			rinfo->rect.r_height= xv_get(dinfo->server_image, XV_HEIGHT);
			dinfo->depth = xv_get(dinfo->server_image, SERVER_IMAGE_DEPTH);
			rectobj_repaint_rect(drawimage_public, NULL, FALSE);
			break;

		case DRAWIMAGE_HIGHLIGHT_IMAGE:
			dinfo->highlight_image= (Server_image)*avlist++;
			if(dinfo->highlight_image == 0)
				break;
			rinfo->rect.r_width = xv_get(dinfo->highlight_image, XV_WIDTH);
			rinfo->rect.r_height= xv_get(dinfo->highlight_image, XV_HEIGHT);
			dinfo->highlight_depth = xv_get(dinfo->highlight_image, SERVER_IMAGE_DEPTH);
			rectobj_repaint_rect(drawimage_public, NULL, FALSE);
			break;

		default:
			avlist = attr_skip(attr, avlist);

	  }

	rectobj_finish_set(drawimage_public);
	return(XV_SET_DONE);
}


/*ARGSUSED*/
Pkg_private Xv_opaque
drawimage_get_attr(drawimage_public, status, which_attr, avlist)
	Drawimage		drawimage_public;
	int		*status;
	register Attr_attribute which_attr;
	Attr_avlist	avlist;
{
	Drawimage_info  *dinfo = DRAWIMAGE_PRIVATE(drawimage_public);

	switch (which_attr) {

		case DRAWIMAGE_SVRIMAGE:
			return (Xv_opaque) dinfo->server_image;

		case DRAWIMAGE_HIGHLIGHT_IMAGE:
			return (Xv_opaque) dinfo->highlight_image;

		default:
			*status = XV_ERROR;
			return (Xv_opaque) 0;
	}
}

/*ARGSUSED*/
Pkg_private int
drawimage_destroy(drawimage_public, status)
	Drawimage		drawimage_public;
	Destroy_status	status;
{
	Drawimage_info	*dinfo = DRAWIMAGE_PRIVATE(drawimage_public);

	if ((status == DESTROY_CHECKING) || (status == DESTROY_SAVE_YOURSELF))
		return XV_OK;

	free(dinfo);
	return XV_OK;
}

/*ARGSUSED*/
Pkg_private void
drawimage_paint_proc(drawimage_public, dpy, win, xrects)
        Drawimage drawimage_public;
        Display *dpy;
        Window  win;
        Xv_xrectlist *xrects;
{
	Drawimage_info *dinfo = DRAWIMAGE_PRIVATE(drawimage_public);
	Rectobj_info *rinfo = RECTOBJ_PRIVATE(drawimage_public);
	GC gc;
	int selected;

	gc = XCreateGC(dpy, win, 0, 0);

	XSetBackground(dpy, gc, rinfo->shared_info->pixels[rinfo->bg_color]);
	XSetForeground(dpy, gc, rinfo->shared_info->pixels[rinfo->fg_color]);

	if(xrects && xrects->count)
		XSetClipRectangles(dpy, gc,
			0, 0,
			xrects->rect_array,
			xrects->count,
			Unsorted);

	selected = xv_get(drawimage_public, RECTOBJ_SELECTED);

        if(dinfo->server_image ||
          ((selected == FALSE) && (dinfo->highlight_image != NULL)))
		render_image(rinfo, dinfo->depth, dpy, win, gc,
                        xv_get(dinfo->server_image, SERVER_IMAGE_PIXMAP));

        if(selected)
          if(dinfo->highlight_image)
		render_image(rinfo, dinfo->highlight_depth, dpy, win, gc,
                        xv_get(dinfo->highlight_image, SERVER_IMAGE_PIXMAP));
          else
		XDrawRectangle(dpy, win, gc,
			rinfo->rect.r_left, rinfo->rect.r_top,
			rinfo->rect.r_width-1, rinfo->rect.r_height-1);

	XFreeGC(dpy, gc);
        rectobj_paint_children(drawimage_public, dpy, win, xrects);
}


static void
render_image(rinfo, depth, dpy, win, gc, image)
	Rectobj_info	*rinfo;
	int		depth;
	Display		*dpy;
        Window  	win;
	GC		gc;
	Drawable	image;
{
	if(depth == 1)
		XCopyPlane(dpy,
			image,
			win,
			gc, 
			0, 0,
			(int) rinfo->rect.r_width, (int) rinfo->rect.r_height,
			(int) rinfo->rect.r_left, (int) rinfo->rect.r_top,
			1);
	else
		XCopyArea(dpy,
			image,
			win,
			gc, 
			0, 0,
			(int) rinfo->rect.r_width, (int) rinfo->rect.r_height,
			(int) rinfo->rect.r_left, (int) rinfo->rect.r_top);
}

