/********************************************************************
 *																	*
 *	Window module													*
 *																	*
 *	Copyright (c) Clever Bits and Bitgate Software 1993 - 1994		*
 *	All Rights Reserved.											*
 *																	*
 *	All procedures that manipulates the window structure of			*
 *	a window, as well as creating and killing windows.				*
 *																	*
 ********************************************************************
 *																	*
 *	Update log:														*
 *																	*
 *	[24.9.93] Ken Hollis											*
 *							- changed some code layout				*
 *	[31.10.93] Karl A. 0ygard										*
 *		WOpenWindow			- Changed xor'ing of win->state to |	*
 *		WCloseWindow		- Changed xor'ing of win->state to &	*
 *							- It now takes a parameter which is		*
 *								passed to the dispatcher to tell it	*
 *								whether or not the dispatcher can	*
 *								stop the window from getting closed	*
 *		WWindSet			- Removed () around window titles - I	*
 *								didn't like it.						*
 *		WWindSet			- pnameheader is renamed prgnameheader	*
 *							- prgnameheader is preformatted in WInit*
 *		WCloseWindowNow		- renamed WCruelCloseWindow				*
 *		WKillAllWindows		- made it nicer and more secure			*
 *	[2.11.93 - 7.11.93] Karl A. 0ygard								*
 *							- changed some code layout				*
 *		WCreateWindow		- optimised								*
 *		WMoveWindow			- changed way sizing of windows from	*
 *								dialogs work. Somewhat better.		*
 *	[3.12.93 - 29.3.93] Ken Hollis									*
 *							- added window elements as dialog box	*
 *		WInitElements		- added to fix object elements			*
 *		WWindSet			- added support for window iconification*
 *							- fixed up iconification routines a bit	*
 *							- fixed name concatenation				*
 *		WRedrawAllWindows	- added									*
 *		WCreateWindow		- added popup information clearing		*
 *							- added text loading support			*
 *		WReassignWindow		- added for dialog reassignment			*
 *		WRedrawWindowLevel	- added for drawing different object	*
 *								levels (optimizes redraw speed)		*
 *		WCreateWindow		- added bug fix to top W_UNUNTOPPABLE	*
 *								window if there is one; must be done*
 *							- added treenumber item to window		*
 *		WTopWindow			- added dominance checking for topping	*
 *																	*
 ********************************************************************/

#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <tos.h>

#include "winlib.h"

#ifdef __TURBOC__
#pragma warn -pia
#endif

#ifndef __WINDOWS__
#define __WINDOWS__
#endif

/*
 *	Set window parameters
 *
 *	Same parameters as wind_set except for
 *
 *	win = window in which to set parameters
 *
 *	This procedure is an interception of wind_set in order to ensure that
 *	the application sets correct information. (Censorship!)
 */
GLOBAL int WWindSet(WINDOW *win, int wi_sfield, ...)
{
	va_list	argptr;
	int wi_sw1, wi_sw2, wi_sw3, wi_sw4;
	long wi_sl1;

	switch (wi_sfield) {
		case WF_TOP:
			wind_set(win->handle, WF_TOP);
			if (win->prev)									/* Bring window to top of WindowChain */
				win->prev->next = win->next;
			win->next->prev = win->prev;
		
			if (WindowChain == win)
				WindowChain = win->next;
		
			WindowChain->prev = win;
			win->next = WindowChain;
			win->prev = NULL;
			WindowChain = win;
			return TRUE;

		case WF_MODAL:
		case WF_BEVENT:
		case WF_MINIMIZE:
		case WF_UNUNTOPPABLE:
			va_start(argptr, wi_sfield);
			wi_sw1 = va_arg(argptr, int);
			va_end(argptr);

			switch (wi_sfield) {
				case WF_MODAL:
					if (wi_sw1)
						win->state |= W_MODAL;
					else
						win->state &= ~W_MODAL;

					return TRUE;

				case WF_BEVENT:
					if (AES_VERSION >= 0x0400)
						wind_set(win->handle, WF_BEVENT, wi_sw1 ? 1 : 0);

					if (wi_sw1)
						win->state |= W_BEVENT;
					else
						win->state &= ~W_BEVENT;
					return TRUE;

				case WF_MINIMIZE:
					if (wi_sw1)
						win->state |= W_MINIMIZED;
					else
						win->state &= ~W_MINIMIZED;

					WWindSet(win, WF_CURRXYWH, -1, -1, -1, win->size.g_h);
					return TRUE;

				case WF_UNUNTOPPABLE:
					if (wi_sw1)
						win->state |= W_UNUNTOPPABLE;
					else
						win->state &= ~W_UNUNTOPPABLE;

					WWindSet(win, WF_TOP);
					return TRUE;
			}

		case WF_TIMER:
			if (wi_sw1)
				win->state |= W_TIMER;
			else
				win->state &= ~W_TIMER;

			return TRUE;

		case WF_DIALOG:
			if (wi_sw1)
				win->state |= W_DIALOG;
			else
				win->state &= ~W_DIALOG;

			return TRUE;

		case WF_NAME:
		case WF_INFO:
			va_start(argptr, wi_sfield);
			wi_sl1 = va_arg(argptr, long);
			va_end(argptr);

			switch (wi_sfield) {
				case WF_NAME:
					sprintf(win->origtitle, "%s", wi_sl1);

					if (win->state & W_DIALOG)
						sprintf(win->title, "[ %s%s ]", prgnameheader, wi_sl1);
					else
						sprintf(win->title, "%s%s", prgnameheader, wi_sl1);

					return wind_set(win->handle, WF_NAME, win->title);

				case WF_INFO:
					strncpy(win->info, (char *) wi_sl1, 128);
					return wind_set(win->handle, WF_INFO, win->info);
			}

		case WF_ICONIFY:
			va_start(argptr, wi_sfield);
			wi_sw1 = va_arg(argptr, int);
			wi_sw2 = va_arg(argptr, int);
			wi_sw3 = va_arg(argptr, int);
			wi_sw4 = va_arg(argptr, int);
			va_end(argptr);

			win->state |= W_ICONIFIED;
/*			if (AES_VERSION>=0x0400)
				wind_set(win->handle, WF_ICONIFY, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
			else */

			if (WCallIconifyDispatcher(win, TRUE))
				WIconify(win);

			return TRUE;

		default:
			va_start(argptr, wi_sfield);
			wi_sw1 = va_arg(argptr, int);
			wi_sw2 = va_arg(argptr, int);
			wi_sw3 = va_arg(argptr, int);
			wi_sw4 = va_arg(argptr, int);
			va_end(argptr);

			switch (wi_sfield) {
				case WF_CURRXYWH:
					WMoveWindow(win, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
					return TRUE;

/*				case WF_ICONIFY:
					win->state |= W_ICONIFIED;
					if (AES_VERSION>=0x0400)
						wind_set(win->handle, WF_ICONIFY, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
					else
						WIconify(win);
					return TRUE; */

				case WF_UNICONIFY:
					win->state &= ~W_ICONIFIED;
					wind_set(win->handle, WF_UNICONIFY, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
					return TRUE;

				default:
					return wind_set(win->handle, wi_sfield, wi_sw1, wi_sw2, wi_sw3, wi_sw4);
			}
	}
}


/*
 *	Get window parameters
 *
 *	Same parameters as wind_get except for
 *	win = WINDOW to get parameters from
 *
 *	This procedure is an interception of wind_get in order to ensure that
 *	the application gets correct information. (Censorship.)
 */
GLOBAL int WWindGet(WINDOW *win, int wi_gfield, ...)
{
	va_list	argptr;
	int ret, *wi_gw1, *wi_gw2, *wi_gw3, *wi_gw4;
	
	va_start(argptr, wi_gfield);
	wi_gw1 = va_arg(argptr, int *);
	wi_gw2 = va_arg(argptr, int *);
	wi_gw3 = va_arg(argptr, int *);
	wi_gw4 = va_arg(argptr, int *);
	va_end(argptr);

	switch (wi_gfield) {
		case WF_WORKXYWH:
			if (ret = wind_get(win->handle, WF_WORKXYWH, wi_gw1, wi_gw2, wi_gw3, wi_gw4))
				if (win->menubar)
					if (win->handle > 0) {
						int h;

						h = *wi_gw4 - win->menubar[1].ob_height + 1 < 0 ? *wi_gw4 : win->menubar[1].ob_height + 1;
						*wi_gw4 -= h;
						*wi_gw2 += h;
					}
			return ret;

		default:
			return wind_get(win->handle, wi_gfield, wi_gw1, wi_gw2, wi_gw3, wi_gw4);
	}
}


/*
 *	Open a window
 *
 *	Returns TRUE upon success
 */
GLOBAL int WOpenWindow(WINDOW *win)
{
	if (!(win->state & W_OPEN)) {
		if (!wind_open(win->handle, win->size.g_x, win->size.g_y, win->size.g_w, win->size.g_h))
			return FALSE;

		win->state |= W_OPEN;				/* Set state to "open" */
		win->state &= ~W_ICONIFIED;
	}

	return TRUE;
}


/*
 *	Ask a window to close
 *
 *	Sends a request to the window to kindly close
 *
 *	message = WC_OBJECTABLE	- window may protest
 *			  WC_NOTOBJECTABLE - window may not protest
 *
 *	win = Window to close (if NULL, top window will be closed)
 */
GLOBAL void WCloseWindow(WINDOW *win, int message)
{
	int msg_buf[8];

	if (!win)
		win = WindowChain;

	if (win->next)
	{
		msg_buf[0] = WM_CLOSED;
		msg_buf[1] = Ap_ID;
		msg_buf[2] = 0;
		msg_buf[3] = win->handle;
		msg_buf[4] = message;

		WMsgWindow(win, msg_buf);
	}
}


/*
 *	Close a window
 *
 *	Closes the window without notifying the window about it.
 *	Call WCloseWindow with the WC_NOTOBJECTABLE parameter,
 *	rather than closing it. It is not nice.
 *
 *	win = Window to close (if NULL, top window will be closed)
 */
GLOBAL void WCruelCloseWindow(WINDOW *win, BOOL icon)
{
	if (!win)
		win = WindowChain;

	win->edit_disp = FALSE;

	if (win->next && win->state & W_OPEN) {
		if (wind_close(win->handle)) {
			if (icon) {
				win->state &= ~W_OPEN;			/* Set state to not open */
				win->state |= W_ICONIFIED;
			} else
				win->state &= ~W_OPEN;

			graf_shrinkbox(desk.g_w / 2, desk.g_h / 2, 2, 2, win->size.g_x, win->size.g_y, win->size.g_w, win->size.g_h);
			return;
		}
	}
}


/*
 *	Ask a window to die
 *
 *	Call WNiceCloseWindow, rather than killing it. It is not
 *	nice.
 *
 *	win = Window to kill (if NULL, top window will be closed)
 */
GLOBAL void WKillWindow(WINDOW *win)
{
	int msg_buf[8];

	if (!win)
		win = WindowChain;

	if (win->next)
	{
		msg_buf[0] = WM_KILL;
		msg_buf[1] = Ap_ID;
		msg_buf[2] = 0;
		msg_buf[3] = win->handle;
	
		WMsgWindow(win, msg_buf);
	}
}


/*
 *	Create a new window
 *
 *	state = state of new window
 *				W_OPEN				  = automatically opened
 *				W_MINIMIZED			  = "minimized"
 *				W_UNUNTOPPABLE		  = un-untoppable window
 *										(i.e. requires full attention - should be used with W_MODAL)
 *				W_FULLERMINIMIZES	  = window is minimized rather than fulled when FULLER is selected
 *				W_BACKGROUND		  = window which can be clicked in in the background
 *				W_MODAL 			  = window which blocks mouse clicks to all other windows, 
 *										*even* if they have the W_BACKGROUND mode
 *										(i.e. requires full attention - should be used with W_UNUNTOPPABLE)
 *	kind = Attributes of the window (see wi_crkind in wind_create)
 *	title = title string to use for title of window (none if 0)
 *	info = info string to use for infofield of window (none if 0)
 *	object = Resource object to put in window (none if -1)
 *	edobject = First editable field in resource object (none if 0)
 *	menubar = Resource object number of the menubar to put in window (none if -1)
 *	WndDispatcher = a pointer to the windowdispatcher of the window.
 *	 (may be left 0, meaning that WinLIB will deal with it.)
 *	user = user definable pointer (is put into the WINDOW structure of
 *	 the window, and may be used freely)
 *	x, y, w, h = physical size of window
 *	 (any parameters that are -1 will be taken from the centered
 *	  resource (if any))
 *
 *	Returns: pointer to created window structure
 *			 NOMORE if no windows are available, 
 *			 FALSE on any other failure
 */
GLOBAL WINDOW *WCreateWindow(int state, int style, int kind, 
							  char *title, char *info, 
							  int object, int edobject, 
							  int menubar, 
							  int WndDispatcher(WINDOW *, int[]), 
							  void *user, 
							  int x, int y, int w, int h,
							  OBJECT *obj, int dominance)
{
	WINDOW *ptr;
	int pops;

	if (ptr = malloc(sizeof(WINDOW))) {
		int msg_buf[8];

		ptr->state = 0;
		ptr->style = 0;
		ptr->user = user;
		ptr->kind = kind;
		ptr->edobject = edobject;
		ptr->edpos = -1;
		ptr->edit_disp = FALSE;

		ptr->has_edit = (edobject) ? TRUE : FALSE;
		ptr->dominance = dominance;

		ptr->WndDispatcher = malloc(sizeof(WndDispatcher));
		ptr->WndDispatcher = WndDispatcher;

		ptr->timer.clock = 0x00000000;
		ptr->timer.ev_mtcount = 0x00000000;
		ptr->timer.user = NULL;
		ptr->timer.status = FALSE;

		if (menubar != -1) {
			rsrc_gaddr(R_TREE, menubar, &(ptr->menubar));
			ptr->menubar[1].ob_spec.obspec.framesize = -1;
		} else 
			ptr->menubar = NULL;

		if (obj || object != -1) {
			int x2, y2, w2, h2;

			if (object != -1) {
				rsrc_gaddr(R_TREE, object, &(ptr->tree));
				ptr->treenumber = object;
			} else {
				ptr->tree = obj;
				ptr->treenumber = -1;
			}

			form_center(ptr->tree, &x2, &y2, &w2, &h2);

			x2 += abs(ptr->tree->ob_spec.obspec.framesize);
			y2 += abs(ptr->tree->ob_spec.obspec.framesize);
			w2 -= abs(ptr->tree->ob_spec.obspec.framesize) * 2;
			h2 -= abs(ptr->tree->ob_spec.obspec.framesize) * 2;

			wind_calc(WC_BORDER, ptr->kind, x2, y2, w2, h2, &x2, &y2, &w2, &h2);

			x = (x != -1) ? x : x2;
			y = (y != -1) ? y : y2;
			w = (w != -1) ? w : w2;
			h = (h != -1) ? h : h2;
		} else {
			ptr->tree = NULL;

			x = (x != -1) ? x : 0;
			y = (y != -1) ? y : 0;
			w = (w != -1) ? w : 1;
			h = (h != -1) ? h : 1;
		}

		if (menubar != -1)
			h += ptr->menubar[1].ob_height + 1;

		ptr->size.g_x = x;
		ptr->size.g_y = y;
		ptr->size.g_w = w;
		ptr->size.g_h = h;

													/* Create new window */
		if ((ptr->handle = wind_create(ptr->kind, x, y, w, h)) < 0) {
			free(ptr);
			return (WINDOW *) NOMORE;
		}

		WindowChain->prev = ptr;					/* Insert window in chain */
		ptr->next = WindowChain;
		ptr->prev = NULL;
		WindowChain = ptr;

		graf_growbox(desk.g_w / 2, desk.g_h / 2, 2, 2, ptr->size.g_x, ptr->size.g_y, ptr->size.g_w, ptr->size.g_h);

		if (state & W_FULLERMINIMIZES)
			ptr->state |= W_FULLERMINIMIZES;

		if (info)
			WWindSet(ptr, WF_INFO, info);

		if (state & W_OPEN)
			WOpenWindow(ptr);

		if (state & W_MINIMIZED)
			WWindSet(ptr, WF_MINIMIZE, 1);

		if (state & W_UNUNTOPPABLE)
			WWindSet(ptr, WF_UNUNTOPPABLE, 1);

		if (state & W_BEVENT)
			WWindSet(ptr, WF_BEVENT, 1);

		if (state & W_MODAL)
			WWindSet(ptr, WF_MODAL, 1);

		if (state & W_TIMER)
			WWindSet(ptr, WF_TIMER, 1);

		if (state & W_DIALOG)
			WWindSet(ptr, WF_DIALOG, 1);

		if (title)
			WWindSet(ptr, WF_NAME, title);

		if (state & W_FULLERICONIFIES)
			ptr->state |= W_FULLERICONIFIES;

		if (style & S_FULLERMINIMIZES)
			ptr->style |= S_FULLERMINIMIZES;

		if (style & S_FULLERICONIFIES)
			ptr->style |= S_FULLERICONIFIES;

		if (style & S_FULLERCHOOSES)
			ptr->style |= S_FULLERCHOOSES;

		if (style & S_MULTICOPYABLE)
			ptr->style |= S_MULTICOPYABLE;

		vsl_color(VDIhandle, BLACK);

		msg_buf[0] = WM_CREATED;
		msg_buf[1] = Ap_ID;
		msg_buf[2] = 0;
		msg_buf[3] = ptr->handle;
		WMsgWindow(ptr, msg_buf);

		WTopWindow(ptr);

		return ptr;
	}

	return FALSE;
}

/*
 *	Move/resize window
 *
 *	win = Window to move
 *	x = new x coordinate
 *	y = new y coordinate
 *	w = new width
 *	h = new height
 *
 *	Any parameters that are -1 are taken from the current settings of the window.
 */
GLOBAL void WMoveWindow(WINDOW *win, int x, int y, int w, int h)
{
	int wx, wy, ww, wh;

	wind_get(win->handle, WF_CURRXYWH, &wx, &wy, &ww, &wh);

	x = (x == -1) ? wx : (win->size.g_x = x);
	y = (y == -1) ? wy : (win->size.g_y = y);
	w = (w == -1) ? ww : w;
	h = (h == -1) ? wh : h;

	if (win->state & W_MINIMIZED)
		if (w != ww || h != wh )
			win->state &= ~W_MINIMIZED;
		else {
			int dummy, height;

			wind_get(win->handle, WF_WORKXYWH, &dummy, &dummy, &dummy, &height);
			if (h > wh - height)
				h = wh - height;
		}

	if (!(win->state & W_MINIMIZED)) {
		win->size.g_w = w;
		win->size.g_h = h;
	}

	if (x != wx || y != wy || w != ww || h != wh)			/* If either parameter has changed... */
		wind_set(win->handle, WF_CURRXYWH, x, y, w, h);	/* Move window */

	WWindGet(win, WF_WORKXYWH, &x, &y, &w, &h);

	if (win->tree) {
		win->tree->ob_x = x - (win->tree->ob_type & 0xff00 ? win->tree->ob_spec.obspec.framesize : 0);
		win->tree->ob_y = y - (win->tree->ob_type & 0xff00 ? win->tree->ob_spec.obspec.framesize : 0);
	}

	if (win->menubar)
		if (win->handle > 0) {
			win->menubar->ob_x = x;
			win->menubar->ob_y = y - win->menubar[1].ob_height - 1;
		}
}


/*
 *	Top window
 *
 *	win = Window to bring to top
 *
 *	If win = 0, bottommost window (if any) is topped
 */
GLOBAL void WTopWindow(WINDOW *win)
{
	int dominanthandle;

	if (!win) {
		if ((win = WindowChain)->next)
			if (WindowChain->state & W_UNUNTOPPABLE)
				while ((win->next->next) && (win->next->state & W_UNUNTOPPABLE) &&
						(win->next->dominance != D_NONE)) {
					if (dominanthandle = WFindDominance()) {
						WINDOW *dom;

						dom = WLocateWindow('HNDL', dominanthandle);

						if (dom->dominance == D_ALWAYSTOP) {
							WWindSet(dom, WF_TOP, dominanthandle);
							return;
						}
					}

					win = win->next;
				}
			else
				while (win->next->next)
					win = win->next;
		else
			return;
	} else {
		WINDOW *newwin = WindowChain;

		if (newwin->state & W_UNUNTOPPABLE)
			if (win->dominance == D_ALWAYSTOP) {
				WINDOW *dom;

				dom = WLocateWindow('HNDL', win->handle);

				if (dom->dominance == D_ALWAYSTOP) {
					WWindSet(dom, WF_TOP, win->handle);
					return;
				}
			}

			if (win->dominance == D_SWITCHABLE)
				if (dominanthandle = WFindDominance()) {
					WINDOW *dom;

					dom = WLocateWindow('HNDL', dominanthandle);

					if (dom->dominance == D_ALWAYSTOP) {
						WWindSet(dom, WF_TOP, dominanthandle);
						return;
					}
				}

			if (dominanthandle = WFindDominance()) {
				WINDOW *dom;

				dom = WLocateWindow('HNDL', dominanthandle);

				if (dom->dominance == D_ALWAYSTOP) {
					WWindSet(dom, WF_TOP, dominanthandle);
					return;
				}
			}

		if (newwin->next)
			newwin = newwin->next;
		else
			return;
	}

	WWindSet(win, WF_TOP, win->handle);
}


/*
 *	Redraw rectangle of a window
 *
 *	win = window to redraw
 *	x = x coord
 *	y = y coord
 *	w = width
 *	h = height
 *
 *	(This procedure really just sends a message to the window dispatcher
 *	 of the window to repaint the actual rectangle.)
 */
GLOBAL void WRedrawWindow(WINDOW *win, int x, int y, int w, int h)
{
	int msg_buf[8];

	msg_buf[0] = WM_REDRAW;
	msg_buf[1] = Ap_ID;
	msg_buf[2] = 0;
	msg_buf[3] = win->handle;
	msg_buf[4] = x;
	msg_buf[5] = y;
	msg_buf[6] = w;
	msg_buf[7] = h;

	WMsgWindow(win, msg_buf);
}

GLOBAL void WRedrawWindowLevel(WINDOW *win, int xx, int yy, int ww, int hh, int object, int level)
{
	GRECT realrect, temp, work;
	int pxyarray[4], msg_buf[8], tophandle;

	WWindGet(win, WF_TOP, &tophandle);

	if (win->edobject && win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
		objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
		win->edit_disp = FALSE;
	}

	realrect.g_x = xx;
	realrect.g_y = yy;
	realrect.g_w = ww;
	realrect.g_h = hh;

	msg_buf[0] = WM_REDRAW;
	msg_buf[1] = msg_buf[2] = 0;
	msg_buf[3] = win->handle;
	msg_buf[4] = xx;
	msg_buf[5] = yy;
	msg_buf[6] = ww;
	msg_buf[7] = hh;

	if (win->menubar)
		if (win->handle > 0) {
			int x, y, dummy;

			WUpdateWindowMenu(win, msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7]);
			objc_offset(win->menubar, 1, &x, &y);
			dummy = max(msg_buf[5], y + win->menubar[1].ob_height + 1);
			if (dummy > msg_buf[5]) {
				msg_buf[7] -= dummy - msg_buf[5];
				msg_buf[5] = dummy;
			}
		}

	if (rc_intersect(&realrect, &desk)) {
		WWindGet(win, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);

		if (rc_intersect(&realrect, &work))
			if (msg_buf[7] > 0 && WCallWndDispatcher(win, msg_buf))
				if (win->tree)
					WUpdateWindowDlgLevel(win, msg_buf[4], msg_buf[5], msg_buf[6], msg_buf[7], object, level);
				else {	
					wind_update(BEG_UPDATE);
					graf_mouse(M_OFF, NULL);

					vsf_interior(VDIhandle, FIS_SOLID);
					vswr_mode(VDIhandle, MD_REPLACE);
					vsf_color(VDIhandle, 0);

					WWindGet(win, WF_FIRSTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
					while (temp.g_w && temp.g_h) {
						if (rc_intersect(&temp, &realrect)) {
							pxyarray[0] = temp.g_x;
							pxyarray[1] = temp.g_y;
							pxyarray[2] = temp.g_x + temp.g_w - 1;
							pxyarray[3] = temp.g_y + temp.g_h - 1;

							v_bar(VDIhandle, pxyarray);
						}
						WWindGet(win, WF_NEXTXYWH, &temp.g_x, &temp.g_y, &temp.g_w, &temp.g_h);
					}

					graf_mouse(M_ON, NULL);
					wind_update(END_UPDATE);
				}
	}

	if (win->edobject && !win->edit_disp && win->handle == tophandle && !(win->state & W_MINIMIZED) && !(win->state & W_ICONIFIED)) {
		objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
		win->edit_disp = TRUE;
	}
}

/*
 *	Kills all windows
 *
 *	First asks all windows to terminate immediately,
 *	then kills any windows that still might hang around.
 */
GLOBAL void WKillAllWindows(void)
{
	WINDOW *win = WindowChain;

	while (win->next) {
		win = win->next;
		WCloseWindow(win->prev, WC_NOTOBJECTABLE);
	}

	while (WindowChain->next)
		WKillWindow(WindowChain);
}


/*
 *	Redraw all windows
 *
 *	win = Window to bring to top
 *
 *	If win = 0, bottommost window (if any) is topped
 */
GLOBAL void WRedrawAllWindows(void)
{
	WINDOW *win = WindowChain;

	while (win->next) {
		win = win->next;
		WRedrawWindow(win->prev, win->prev->size.g_x,
						win->prev->size.g_y, win->prev->size.g_w,
						win->prev->size.g_h);
	}
}

/*
 *	Find WINDOW structure
 *
 *	ident = 4 byte identification structure
 *	...	  = information to search for
 */
GLOBAL WINDOW *WLocateWindow(long ident, ...)
{
	WINDOW *win = WindowChain;
	va_list argptr;
	int intparm;
	OBJECT *intobj;

	switch((long)(ident)) {
		case 'HNDL':
		case 'STAT':
		case 'KIND':
		case 'EOBJ':
		case 'EPOS':
		case 'HASE':
		case 'EDSP':
		case 'TPLN':
		case 'AMTM':
		case 'TOP_':
		case 'ICON':
			va_start(argptr, 1);
			intparm = va_arg(argptr, int);
			va_end(argptr);
			break;

		case 'TREE':
			va_start(argptr, 1);
			intobj = va_arg(argptr, OBJECT *);
			va_end(argptr);
			break;
	}

	while(win->next) {
		switch((long)(ident)) {
			case 'HNDL':
				if (win->handle == intparm)
					return(win);
				break;

			case 'ICON':
				if (win->objnumber == intparm)
					return(win);
				break;

			case 'TREE':
				if (win->tree == intobj)
					return(win);
				break;
		}
		win = win->next;
	}
	return((WINDOW *) 0L);
}