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

#ifndef lint
#ifdef sccs
static char     sccsid[] = "@(#)bkg_event.c 1.13 91/05/07";
#endif
#endif

#include <X11/Xlib.h>
#include "canshell_impl.h"
#include "r_impl.h"
#include <sspkg/rectobj.h>

static int startx, starty, lastx, lasty;
GC xor_gc;

draw_rubberband(canvas_shell)
	Canvas_shell canvas_shell;
{
	Xv_window xv_win;
	int	x1, y1;
	int	x2, y2;
	int	width, height;
	Canvas_shell_info *csinfo = CANVAS_SHELL_PRIVATE(canvas_shell);

	x1 = MIN(startx, lastx);
	y1 = MIN(starty, lasty);
	x2 = MAX(startx, lastx);
	y2 = MAX(starty, lasty);

	width = x2 - x1;
	height= y2 - y1;

	CANVAS_EACH_PAINT_WINDOW(canvas_shell, xv_win)
	    XDrawRectangle(csinfo->shared_info.dpy, xv_get(xv_win, XV_XID), 
			xor_gc,
			x1, y1, width, height);
	CANVAS_END_EACH
}


typedef enum { RUBBER_SELECT, RUBBER_ADJUST } Mode;
static Mode rubberband_mode;

static void *
rubberband_select_rectobj(rectobj, rubber_rect)
	Rectobj rectobj;
	Rect	*rubber_rect;
{
	Rect *rect;
	
	if(xv_get(rectobj, RECTOBJ_SELECTABLE) == FALSE)
		return (void*) 0;
	rect = (Rect*) xv_get(rectobj, XV_RECT);
	if(rect_includesrect(rubber_rect, rect)) {
		if(rubberband_mode == RUBBER_ADJUST) 
			xv_set(rectobj, RECTOBJ_SELECTED,
				xv_get(rectobj, RECTOBJ_SELECTED) ^ TRUE,
				XV_NULL);
		else
			xv_set(rectobj, RECTOBJ_SELECTED, TRUE,
				XV_NULL);
	}
	return (void*) 0;
}

/*
 * when the rubberband is released, check all the items to see if
 * they were within the selected area.  If the middle button was
 * used, flip the states.
 */
static void
rubberband_select(canvas_shell, event)
	Canvas_shell 	canvas_shell;
	Event		*event;
{
	Rect	enclosing_rect;
	int	x2, y2;

	enclosing_rect.r_left = MIN(startx, lastx);
	enclosing_rect.r_top  = MIN(starty, lasty);
	x2 = MAX(startx, lastx);
	y2 = MAX(starty, lasty);

	enclosing_rect.r_width = x2 - enclosing_rect.r_left;
	enclosing_rect.r_height= y2 - enclosing_rect.r_top;

	rubberband_mode = ((event_id(event) == MS_MIDDLE) ? RUBBER_ADJUST: RUBBER_SELECT);

	xv_set(canvas_shell, CANVAS_SHELL_DELAY_REPAINT, TRUE, NULL);
	traverse_rectobj_tree(canvas_shell, rubberband_select_rectobj, 
				&enclosing_rect);
	xv_set(canvas_shell, CANVAS_SHELL_DELAY_REPAINT, FALSE, NULL);

}


int
background_event_proc(paint_window, event, canvas_shell, rectobj)
	Xv_window	paint_window;
	Event		*event;
	Canvas_shell	canvas_shell;
	Rectobj		rectobj;
{
	Canvas_shell_info	*csinfo = CANVAS_SHELL_PRIVATE(canvas_shell);
	Event			read_event;

	if( (event_id(event) == MS_RIGHT) && (event_is_down(event)) )  {
		Menu menu;
		if(menu = rectobj_get_menu(rectobj))
			menu_show(menu, paint_window, event, 0);
		return TRUE;
	}

	/* 
	 * filter out unwanted events
	 */
	if((event_id(event) != MS_LEFT) && (event_id(event) != MS_MIDDLE))
		return TRUE;
	if(!event_is_down(event))
		return TRUE;
	
	if(event_id(event) == MS_LEFT)
			clear_selection(0);
	if(count_buttons_down(event) != 0) {
		/*puts("other than zero buttons down");*/
		return TRUE;
	}

	xor_gc = XCreateGC(csinfo->shared_info.dpy,
			xv_get(canvas_shell, XV_XID), 0, 0);
	XSetForeground(csinfo->shared_info.dpy, xor_gc,
			xv_get(canvas_shell, WIN_FOREGROUND_COLOR));
	XSetFunction(csinfo->shared_info.dpy, xor_gc, GXxor);


	lastx = startx = event_x(event);
	lasty = starty = event_y(event);

	while(1) {

		(void) xv_input_readevent(paint_window, &read_event, 
			TRUE, FALSE, NULL);

		switch( event_id(&read_event) ) {
		  case MS_LEFT:
		  case MS_MIDDLE:
		  case MS_RIGHT:
			if( event_is_up(&read_event) && 
			    count_buttons_down(&read_event) < 2 ) {
				draw_rubberband(canvas_shell);
				rubberband_select(canvas_shell, &read_event);
				XFreeGC(csinfo->shared_info.dpy, xor_gc);
				return TRUE;
			}
			break;
		  case LOC_DRAG:
			draw_rubberband(canvas_shell);
			lastx = event_x(&read_event);
			lasty = event_y(&read_event);
			draw_rubberband(canvas_shell);
			break;
		  default:
			break;
		}
	}
}



/*
 * the following table holds:
 *
 *	RECTOBJ_MENU exists	RECTOBJ_INHERIT_MENU	action
 *	-------------------	--------------------	-------------------
 *		T			F		use the menu
 *		T			T		inherit from parent
 *		F			F		no menu is offered
 *		F			T		inherit from parent
 * RECTOBJ_INHERIT_MENU is asserted to be FALSE when setting RECTOBJ_MENU to
 * something non-NULL (i.e. a real menu) (via xv_get()).  
 * It returns to it's original value when RECTOBJ_MENU is later set to zero.
 */

Menu
rectobj_get_menu(rectobj)
	Rectobj rectobj;
{
	Menu 	menu;
	Rectobj parent;
	int	inherit_menu;
	Canvas_shell canvas_shell;

	if(!rectobj)
		return (Menu) 0;

	while(1) {
	  inherit_menu = (int) xv_get(rectobj, RECTOBJ_INHERIT_MENU);
	  if(inherit_menu == TRUE) {
	  	parent = xv_get(rectobj, RECTOBJ_PARENT);
		if(!parent)
			return (Menu) 0;
	  	rectobj = parent;
		continue;
	  }
	  return (Menu) xv_get(rectobj, RECTOBJ_MENU);
	}
}

