/* $Id: Destroy.c,v 1.1 1997/04/15 10:09:29 archer Exp $
 *	DESTROY.C - Destruction of Widgets
 *
 * This contains all the generic widget functions that the application might
 * want to call.
 */
#include <Widget/WidgetsP.h>
#include <Widget/EventsP.h>
#include <Widget/ShellP.h>


/**
 ** Internal: DROP_PREPARE
 **	Prepare to free a widget
 **/
static void drop_prepare(X11_widget wdg)
{
x11__shell	*sh;
X11_widget	prev, child;
/*
 * If we're a menu popup, we might still be mapped when the window "parent"
 * has been unmapped
 */
	if (wdg->id)
		XUnmapWindow(x11__screen, wdg->id);
/*
 * Free the children first
 */
	for (child = wdg->child; child; child = child->sibling)
		drop_prepare(child);
/*
 * Unlink from event list
 */
	prev = 0;
	for (child = x11__widget_root; child; child = prev->list) {
		if (child == wdg) {
			if (prev)
				prev->list = wdg->list;
			else
				x11__widget_root = wdg->list;
			wdg->list = 0;
			break;
		}
		prev = child;
	}
/*
 * Intrinsic destroy methods
 */
	if ((sh = (x11__shell *)wdg->shell) != 0) {
#if 0
		X11_AcceleratorCancel(wdg);
#endif
		if (sh->current_default == wdg)
			x11__default_loses(wdg);
		if (sh->current_focus == wdg)
			x11__focus_loses(wdg);
	}
/*
 * Call any remaining destroy methods
 */
	if (wdg->on_destruction)
		(*wdg->on_destruction)(wdg, (XEvent *)0);
}


/**
 ** X11_DESTROY
 **	Logically free a Widget and entire hierarchy
 **/
void X11_Destroy(X11_widget wdg)
{
X11_widget	child, parent, prev;
/*
 * Check validity
 */
	if (!wdg)
		return;
/*
 * Unmap X11 window, to avoid flicker
 */
	if (wdg->id)
		XUnmapWindow(x11__screen, wdg->id);
/*
 * Unlink from parent
 */
	if ((parent = wdg->parent) != 0)
		if ((child = parent->child) == wdg)
			parent->child = wdg->sibling;
		else {
/*
 * Search in child chain
 */
			while (child)
				if ((prev = child->sibling) == wdg) {
					child->sibling = wdg->sibling;
					break;
				} else
					child = prev;
		}
	wdg->sibling = 0;
	wdg->parent  = 0;
/*
 * Recursive drop
 */
	drop_prepare(wdg);
/*
 * Link to garbage collector's list
 */
	wdg->list = x11__widget_garbage_bin;
	x11__widget_garbage_bin = wdg;
}
