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

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

/* issues:
 * should this decrement/increment reference count on fonts 
 * when creating/destroying?  The first problem is that you can't 
 * say the object being created is the owner in the xv_find() call
 * which means that reference count should be maintained.
 */

#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 <string.h>
#include <sspkg/drawobj.h>
#include "do_impl.h"
#include "r_impl.h"
#include <sspkg/canshell.h>

Pkg_private int 	drawtext_init();
Pkg_private Xv_opaque	drawtext_set_avlist();
Pkg_private Xv_opaque	drawtext_get_attr();
Pkg_private int 	drawtext_destroy();

void	drawtext_paint_proc();
int	drawtext_event_proc();

/*ARGSUSED*/
Pkg_private int
drawtext_init(parent, drawtext, avlist)
	Xv_opaque	parent;
	Drawtext	drawtext;
	Attr_avlist	avlist;
{
	Drawtext_info	*dinfo;
	Rectobj_info 	*rinfo = RECTOBJ_PRIVATE(drawtext);
	Drawtext_struct	*drawtext_object;

	dinfo = xv_alloc(Drawtext_info);
	dinfo->public_self = drawtext;
	drawtext_object = (Drawtext_struct*) drawtext;
	drawtext_object->private_data = (Xv_opaque) dinfo;

	/*
	 * this shouldn't be done here... but in the set proc
	 * at least then we can use the right handle for owner
	 */
	dinfo->font = xv_find(XV_NULL, FONT, NULL);
	dinfo->font_info = (XFontStruct*)xv_get(dinfo->font, FONT_INFO);

	rinfo->event_proc = drawtext_event_proc;
	rinfo->paint_proc = drawtext_paint_proc;

	rinfo->selectable = TRUE;

	return(XV_OK);
}


Pkg_private Xv_opaque
drawtext_set_avlist(drawtext, avlist)
	Drawtext		drawtext;
	register Attr_avlist	avlist;
{
        register Drawobj_attr attr;
        register Drawtext_info *dinfo = DRAWTEXT_PRIVATE(drawtext);
	Rectobj_info	*rinfo = RECTOBJ_PRIVATE(drawtext);
	Shared_info	*sh_info = rinfo->shared_info;
	int	rect_changed = FALSE;
	int	font_changed = FALSE;

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

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

		case DRAWTEXT_STRING:
			if(dinfo->string)
				free(dinfo->string);
			/* what if *avlist is NULL? */
			dinfo->string = strdup((char*)*avlist++);
			rect_changed = TRUE;
			/* change the rect and repaint */
			break;

		case DRAWTEXT_FONT:
			dinfo->font = (Xv_font)*avlist++;
			dinfo->font_info = 
				(XFontStruct*)xv_get(dinfo->font, FONT_INFO);
			rect_changed = TRUE;
			font_changed = TRUE;
			break;

		case XV_END_CREATE:
	   		font_changed = TRUE;
	   		rect_changed = TRUE; /* force calculation of the rect */
			break;

		default:
			avlist = attr_skip(attr, avlist);

	  }

	if(font_changed || (sh_info != rinfo->shared_info)) {
		if(dinfo->gc && sh_info) {
			XFreeGC(sh_info->dpy, dinfo->gc);
			dinfo->gc = 0;
		}
		if(rinfo->shared_info) {
		  dinfo->gc = XCreateGC(rinfo->shared_info->dpy, 
			xv_get(rinfo->shared_info->canvas_shell, XV_XID), 0, 0);
		  XSetFont(rinfo->shared_info->dpy, dinfo->gc, 
			(Font)xv_get(dinfo->font, XV_XID));
		  XSetForeground(rinfo->shared_info->dpy, dinfo->gc, 
			rinfo->shared_info->pixels[rinfo->fg_color]);
		}
	}

	if(rect_changed) {
	  rinfo->repaint = TRUE;
	  if(dinfo->string) {
		/* only for width and height change */
		rinfo->rect.r_width = XTextWidth(dinfo->font_info, 
					dinfo->string, strlen(dinfo->string));

		rinfo->rect.r_height= dinfo->font_info->ascent +
					dinfo->font_info->descent;
	  } else {
		rinfo->rect.r_width = rinfo->rect.r_height = 0;
	  }
	}

	rectobj_finish_set(drawtext);
	return(XV_SET_DONE);
}


/*ARGSUSED*/
Pkg_private Xv_opaque
drawtext_get_attr(drawtext, status, which_attr, avlist)
	Drawtext		drawtext;
	int		*status;
	register Attr_attribute which_attr;
	Attr_avlist	avlist;
{
	Drawtext_info  *dinfo = DRAWTEXT_PRIVATE(drawtext);

	switch (which_attr) {

		case DRAWTEXT_STRING:
			return (Xv_opaque) dinfo->string;

		case DRAWTEXT_FONT:
			return (Xv_opaque) dinfo->font;

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

/*ARGSUSED*/
Pkg_private int
drawtext_destroy(drawtext, status)
	Drawtext		drawtext;
	Destroy_status	status;
{
	Drawtext_info	*dinfo = DRAWTEXT_PRIVATE(drawtext);
	Rectobj_info *rinfo = RECTOBJ_PRIVATE(drawtext);

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

	free(dinfo->string);
	free(dinfo);
	return XV_OK;
}

/*ARGSUSED*/
Pkg_private void
drawtext_paint_proc(drawtext, dpy, win, xrects)
        Drawtext drawtext;
        Display *dpy;
        Window  win;
        Xv_xrectlist *xrects;
{
	Drawtext_info *dinfo = DRAWTEXT_PRIVATE(drawtext);
	Rectobj_info *rinfo = RECTOBJ_PRIVATE(drawtext);

 	/* hack, the gc should always be created when it gets this far.
	 */
	if(!dinfo->gc) 
		return;

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

	if(rinfo->selected) {
		XSetForeground(dpy, dinfo->gc, 
			rinfo->shared_info->pixels[rinfo->fg_color]);

		XFillRectangle(dpy, win, dinfo->gc,
			rinfo->rect.r_left,
			rinfo->rect.r_top,
			rinfo->rect.r_width,
			rinfo->rect.r_height);

		XSetForeground(dpy, dinfo->gc, 
			rinfo->shared_info->pixels[rinfo->bg_color]);
	} else {
		XSetForeground(dpy, dinfo->gc, 
			rinfo->shared_info->pixels[rinfo->bg_color]);

		XFillRectangle(dpy, win, dinfo->gc,
			rinfo->rect.r_left,
			rinfo->rect.r_top,
			rinfo->rect.r_width,
			rinfo->rect.r_height);

		XSetForeground(dpy, dinfo->gc, 
			rinfo->shared_info->pixels[rinfo->fg_color]);
	} 

	if(dinfo->string)
		XDrawString(dpy, win, dinfo->gc, 
			rinfo->rect.r_left, 
			rinfo->rect.r_top + dinfo->font_info->ascent,
			dinfo->string, strlen(dinfo->string));

	if(rinfo->children)
	        rectobj_paint_children(drawtext, dpy, win, xrects);
}

int
drawtext_event_proc(paint_window, event, canvas, drawtext)
	Xv_window	paint_window;
	Event		*event;
	Canvas		canvas;
	Drawtext	drawtext;	
{
	Drawtext_info *dinfo = DRAWTEXT_PRIVATE(drawtext);
	extern void start_dbl_click();

	start_dbl_click(paint_window, event, canvas, drawtext);

	return TRUE;
}

