/*	CursorUtil.c
 *
 *		Custom cursor utilities
 */

/*  YAAF - Yet another application framework
 *  Copyright (C) 1997, 1998 William Edward Woody
 *  
 *  This library is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU Library
 *  General Public License as published by the Free Software
 *  Foundation; either version 2 of the License, or any
 *  later version.
 *  
 *  This library is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABIILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the GNU Library General Public License for
 *  more details.
 *  
 *  You should have received a copy of the GNU Library General
 *  Public License along with this library; if not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#include <XConfig.h>			// must be first to optimize compile on MSVC++
#include <stdlib.h>
#include <XCursorUtil.h>
#include <XConfig.h>

#if OPT_XWIN == 1
#include <X11/cursorfont.h>
#include <X11/Intrinsic.h>

#include <XWindow.h>
#endif


/************************************************************************/
/*																		*/
/*	Globals																*/
/*																		*/
/************************************************************************/

static short			*GCursor;
static short			GCurCursor = KNormalCursor;
static short			GCurWatch = -1;

#if OPT_MACOS || OPT_WINOS
static unsigned long	GWaitTime;
#endif

#if OPT_WINOS

extern "C" {
	extern HINSTANCE _GInstance;	// Needed for me to work...
}

#endif

/************************************************************************/
/*																		*/
/*	Initialization														*/
/*																		*/
/************************************************************************/

/*	@F"InitCursorAnimation"
 *	@H"XCursorUtil.h"
 *	@I
 *
 *		Initialize the cursor animation sequence. This is an optional call
 *	with an array of cursor resource numbers which is repeatedly sequenced
 *	through as WaitCursor() is called.
 */

void InitCursorAnimation(short *l)
{
	GCursor = l;
}

/************************************************************************/
/*																		*/
/*	Set the cursor stuff												*/
/*																		*/
/************************************************************************/

/*	_SetCursorID
 *
 *		Set the cursor by the specified identifier
 */

static void _SetCursorID(short id)
{
#if OPT_MACOS == 1
	CursHandle c;
	CCrsrHandle cc;
	
	/*
	 *	Macintosh world--first, find the color cursor
	 */
	
	if (id == KNormalCursor) {
		// Trap out this one--KNormalCursor is in global memory
		SetCursor(&qd.arrow);
	} else {
		// Get the color cursor if possible
		cc = GetCCursor(id);
		if (cc) {
			SetCCursor(cc);
			DisposeCCursor(cc);
		} else {
			// Color cursor is not there--try black and white
			c = GetCursor(id);
			if (c) {
				HLock((Handle)c);
				SetCursor(*c);
				HUnlock((Handle)c);
				ReleaseResource((Handle)c);
			} else {
				SetCursor(&qd.arrow);
			}
		}
	}
#endif

#if OPT_WINOS == 1
	HCURSOR cursor;
	HCURSOR oldCursor;
	
	if (id == 0) {					// Arrow cursor
		cursor = LoadCursor(NULL,IDC_ARROW);
	} else if (id == 1) {			// iBeamCursor
		cursor = LoadCursor(NULL,IDC_IBEAM);
	} else if (id == 2) {			// crossCursor
		cursor = LoadCursor(NULL,IDC_CROSS);
	} else if (id == 3) {			// plusCursor
		cursor = LoadCursor(NULL,IDC_CROSS);
	} else if (id == 4) {			// watchCursor
		cursor = LoadCursor(NULL,IDC_WAIT);
	} else {
		cursor = LoadCursor(_GInstance,MAKEINTRESOURCE(id));
		if (cursor == NULL) {
			id = 0;
			cursor = LoadCursor(NULL,IDC_ARROW);
		}
	}
	
	oldCursor = SetCursor(cursor);
	
	if (oldCursor != cursor) {
		DestroyCursor(oldCursor);
	}
#endif

#if OPT_XWIN == 1
	/*
	 *	Get the shell window
	 */

	XGWindow *w = XGWindow::GetFrontWindow();
	if (w == NULL) return;
	extern Display *_GDisplay;
	Cursor cursor;						/* This really is a bit of a kludge... */
	
	if (w->fCursorID != id) {
		w->fCursorID = id;
		cursor = XCreateFontCursor(_GDisplay,id);
		XDefineCursor(_GDisplay,w->GetWindow(),cursor);
	}
#endif
}

/*	@F"SetCursorID"
 *	@H"XCursorUtil.h"
 *	@I
 *
 *		Sets the current cursor to the one specified. This is stored away
 *	so that the specified cursor can be redisplayed after a wait sequence.
 */

void SetCursorID(short id)
{
#if OPT_MACOS || OPT_WINOS
	GWaitTime = 0;
#endif

	GCurWatch = -1;
	GCurCursor = id;
	_SetCursorID(id);
}

/*	@F"NormalCursor"
 *	@H"XCursorUtil.h"
 *	@I
 *
 *		Restore the prior cursor after a wait cursor loop
 */

void NormalCursor(void)
{
	if (GCurWatch != -1) {
#if OPT_MACOS || OPT_WINOS
		GWaitTime = 0;
#endif
		GCurWatch = -1;
		_SetCursorID(GCurCursor);
	}
}

/*	@F"WaitCursor"
 *	@H"XCursorUtil.h"
 *	@I
 *
 *		Wait cursor. This spins the cursor animation sequence if any, or
 *	else just puts up the standard 'wait' cursor if no sequence was provided.
 */

void WaitCursor(void)
{
	if (GCursor == NULL) {
		/*
		 *	No animation
		 */
		
		if (GCurWatch == -1) {
			GCurWatch = 0;
			_SetCursorID(KWatchCursor);		/* Default without animation */
		}
	} else {
#if OPT_MACOS
		if (GWaitTime == 0) {
			GWaitTime = TickCount() + 20;
			return;
		}
		if (GWaitTime > TickCount()) return;
		GWaitTime = TickCount() + 10;
#endif

#if OPT_WINOS
		if (GWaitTime == 0) {
			GWaitTime = GetTickCount() + 300;
			return;
		}
		if (GWaitTime > GetTickCount()) return;
		GWaitTime = GetTickCount() + 150;
#endif

		GCurWatch++;
		if (GCursor[GCurWatch] == 0) GCurWatch = 0;
		_SetCursorID(GCursor[GCurWatch]);
	}
}

