/* $Id: Core.c,v 1.2 1997/06/10 15:29:12 archer Exp $
 *	CORE.C - Default methods and creation for Widgets
 *
 */
#include <Widget/WidgetsP.h>
#include <Widget/Shell.h>


/**
 ** X11_CORE_PRESS
 **	Widget gets de-pressed, use usual sense
 **/
void x11__core_press(X11_widget wdg, XEvent *dummy)
{
/*
 * Inactive widgets do not get a press event (well, almost)
 */
	if (wdg->is_disabled)
		return;
/*
 * Activation can change the background
 *	(Note that this event means that wdg->id is not None)
 */
	if (wdg->can_active) {
		XSetWindowBackground(x11__screen, wdg->id, wdg->active_bk);
		XClearArea(x11__screen, wdg->id, 0, 0, 0, 0, False);
		wdg->is_active = True;
	}
/*
 * Focus occurs
 */
	wdg->is_selected  = True;
	wdg->is_depressed = True;
	if (wdg->can_focus && !wdg->has_focus)
		X11_ShellFocus(wdg);
#ifdef DEBUGGING_X11
	x11__assert(wdg->on_expose);
#endif
	(*wdg->on_expose)(wdg, (XEvent *)0);
}


/**
 ** X11_CORE_RELEASE
 **	Widget gets released, use usual sense
 **/
void x11__core_release(X11_widget wdg, XEvent *dummy)
{
/*
 * Widgets de-activate
 *	(Note that this event means that wdg->id is not None)
 */
	if (wdg->can_active && wdg->is_active) {
		XSetWindowBackground(x11__screen, wdg->id,
					wdg->background);
		XClearArea(x11__screen, wdg->id, 0, 0, 0, 0, False);
		wdg->is_active = False;
	}
/*
 * Unselected
 */
	wdg->is_selected  = False;
	wdg->is_depressed = False;
	if (!wdg->unmapped)
		(*wdg->on_expose)(wdg, (XEvent *)0);
}


/**
 ** X11_CORE_ENTER
 **	Pointer moves in of the bounding window
 **/
void x11__core_enter(X11_widget wdg, XEvent *dummy)
{
/*
 * Autofocus?
 */
	if (wdg->auto_focus && !wdg->has_focus) {
		X11_ShellFocus(wdg);
		XClearArea(x11__screen, wdg->id, 0, 0, 0, 0, True);
	}
/*
 * Generally
 */
	if (wdg->is_depressed && !wdg->is_selected)
		x11__core_press(wdg, dummy);
}


/**
 ** X11_CORE_EXIT
 **	Pointer moves out of the bounding window
 **/
void x11__core_exit(X11_widget wdg, XEvent *dummy)
{
/*
 * Generally
 */
	if (wdg->is_depressed && wdg->is_selected) {
		x11__core_release(wdg, dummy);
		wdg->is_depressed = True;
	}
}


/**
 ** X11_CORE_MOTION
 **	Pointer moves in or out of the bounding window
 **/
void x11__core_motion(X11_widget wdg, XEvent *motion)
{
/*
 * Where's the pointer?
 */
	if (motion->xmotion.x >= 0 && motion->xmotion.x < wdg->w &&
	    motion->xmotion.y >= 0 && motion->xmotion.y < wdg->h) {
		if (wdg->on_enter_window)
			(*wdg->on_enter_window)(wdg, motion);
	} else {
		if (wdg->on_exit_window)
			(*wdg->on_exit_window)(wdg, motion);
	}
}


/**
 ** X11_CORE_GEOMETRY
 **	Do not redo geometry
 **/
void x11__core_geometry(X11_widget wdg, XEvent *dummy)
{
/* Use creation-defined geometry */
}


/**
 ** X11_CORE_RESIZE
 **	Resize the object
 **/
void x11__core_resize(X11_widget wdg, XEvent *dummy)
{
int	w, h;
/*
 * Resize occurs only after the Widget is on the X11 screen
 */
	if (!wdg->id)
		return;
/*
 * Resizing...
 */
	w = wdg->w - wdg->border2;
	if (w <= 0)
		w = 1;
	h = wdg->h - wdg->border2;
	if (h <= 0)
		h = 1;
	XResizeWindow(x11__screen, wdg->id, w, h);
}


/**
 ** X11_WIDGET_GROW
 **	After a geometry, resize or not the widget?
 **/
void x11__widget_grow(X11_widget o)
{
unsigned int	w, h;
/*
 * Decide upon a size
 */
	w = o->w;
	h = o->h;
	if (w < o->w_min || o->fixed_w)
		w = o->w_min;
	if (h < o->h_min || o->fixed_h)
		h = o->h_min;
/*
 * Resize?
 */
	if (w != o->w || h != o->h) {
		o->w = w;
		o->h = h;
		(*o->on_resize_window)(o, (XEvent *)0);
	}
}


/**
 ** X11_CORE_CREATE
 **	Widget has been mapped, realize it
 **/
void x11__core_create(X11_widget o, XEvent *none)
{
X11_widget	parent;
unsigned long	bk;
unsigned int	w, h;
/*
 * Be sure
 */
	parent = o->parent;
	if (!parent->id)
		return;
/*
 * Window parameters
 */
	w = o->w;
	if (w)
		w -= o->border2;
	h = o->h;
	if (h)
		h -= o->border2;
	if (w < 1)
		w = 1;
	if (h < 1)
		h = 1;
	if (o->is_active)
		bk = o->active_bk;
	else
		bk = o->background;
/*
 * Create the window
 */
	o->id = XCreateSimpleWindow(x11__screen, parent->id, 
					o->x, o->y, w, h, o->border2/2,
					o->border_color, bk);
	XSelectInput(x11__screen, o->id, o->event_mask);
/*
 * Specific cursor?
 */
	if (o->use_cursor)
		XDefineCursor(x11__screen, o->id, o->use_cursor);
/*
 * If shown, map
 */
	if (!o->unmapped)
		XMapWindow(x11__screen, o->id);
}


/**
 ** X11_CORE_SETUP
 **	Create a basic widget, with inheritance...
 **/
void x11__core_setup(X11_widget new, X11_widget parent, char *class, char *name)
{
X11_widget	shell;
X11_widget	list, last;
/*
 * Link into the global list
 */
	new->list    = parent->list;
	parent->list = new;
/*
 * Link in order
 */
	new->parent = parent;
	last = 0;
	for (list = parent->child; list; list = list->sibling)
		last = list;
	if (last)
		last->sibling = new;
	else
		parent->child = new;
/*
 * Initialize various maps
 */
	new->class = class;
	strncpy(new->name, name, sizeof(new->name)-1); /* Already zero-ended */
	x11__resource_lookup(new);
/*
 * Inherit a few things
 */
	new->border_color = parent->border_color;
	new->background   = parent->background;
	new->foreground   = parent->foreground;
	new->focus_color  = parent->focus_color;
	new->active_bk    = parent->active_bk;
	new->active_fg    = parent->active_fg;
	new->tl_color     = parent->tl_color;
	new->br_color     = parent->br_color;
/*
 * Inherit the Shell
 */
	shell      = parent->shell;
	new->shell = shell;
	if (new->parent == shell && last)
		new->unmanaged = True;
/*
 * Basic mandatory methods
 */
	new->on_geometry_check	= x11__core_geometry;
	new->on_resize_window	= x11__core_resize;
	new->on_window_create	= x11__core_create;
}


/**
 ** X11_WIDGET_GC
 **	Allocate a GC for a widget
 **/
GC x11__widget_gc(X11_widget o)
{
XGCValues	v;
/*
 * Create GC from object
 */
	v.background         = o->background;
	v.foreground         = o->foreground;
	v.graphics_exposures = False;
	return XCreateGC(x11__screen, x11__root_id,
				GCGraphicsExposures|GCBackground|GCForeground,
				&v);
}
