/********************************************************************
 *																	*
 *	New mouse driver and creation									*
 *																	*
 *	Copyright (C) 1993 - 1994, Bitgate Software and Clever Bits.	*
 *	All rights reserved.											*
 *																	*
 *	Handles the changing of mouse forms, the animation (crude) of	*
 *	mouse forms, and the management of current and previous mouse	*
 *	forms.  These routines are just plain smart.					*
 *																	*
 ********************************************************************
 *																	*
 *	Update log:														*
 *																	*
 *	[21.11.93 - 13.3.94] Ken Hollis									*
 *		WGrafMouse		- created									*
 *						- added new icons for mice					*
 *						- added option to return current mouse form	*
 *						- added option to store mouse form after	*
 *							found from special mouse settings		*
 *						- added fix for no more compilation warnings*
 *						- made mouse changes smarter (no change if	*
 *							mouse is already the assigned form)		*
 *																	*
 *	Need to add animated mice via assembly routines, multi-coloured	*
 *	mice.  Also need to add M_SAVE, M_RESTORE, M_PREVIOUS for		*
 *	compatibility.													*
 *																	*
 ********************************************************************/

#include <aes.h>
#include <stdio.h>
#include <string.h>

#include "winlib.h"

#ifndef __MOUSE__
#define __MOUSE__
#endif

MICE mouseform;	/* forms */
int cur_mouse = 1, cur_mouse_form = BUSYBEE;

int init_mouse[37] =
{ 8, 8, 1, 0, 1, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7FFE, 0xFFFF,
  0xFFFF, 0xFFFF, 0x0000, 0x7FFE, 0x4002, 0x43C2, 0x47E2, 0x47E2,
  0x43C2, 0x4002, 0x43C2, 0x4002, 0x7FFE, 0x1008, 0x2D74, 0x4002,
  0x7FFE, 0x0000 };

int loadresource_mouse[37] =
{ 8, 8, 1, 0, 1, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  0xFFFF, 0xFFFF, 0x0000, 0x1FFE, 0x28F2, 0x48F2, 0x48F2, 0x48F2,
  0x4FF2, 0x4002, 0x5DDA, 0x5512, 0x59D2, 0x5452, 0x55DA, 0x4002,
  0x7FFE, 0x0000 };

int lrmove_mouse[37] =
{ 8, 8, 1, 0, 1, 0x0000, 0x0000, 0x0000, 0x1E78, 0x3E7C, 0x7E7E,
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7E7E, 0x3E7C, 0x1E78, 0x0000,
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C30, 0x1C38,
  0x3C3C, 0x7FFE, 0x7FFE, 0x3C3C, 0x1C38, 0x0C30, 0x0000, 0x0000,
  0x0000, 0x0000 };

int lrsize_mouse[37] =
{ 8, 8, 1, 0, 1, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0,
  0xFFE0, 0xFFF7, 0xFFFF, 0xFFFF, 0xFFFF, 0x01FF, 0x00FF, 0x01FF,
  0x01FF, 0x01FF, 0x0000, 0x03C0, 0x03C0, 0x03C0, 0x03C0, 0x03C0,
  0x03C0, 0x7FC0, 0x7FE2, 0x7FF6, 0x00FE, 0x007E, 0x003E, 0x007E,
  0x00FE, 0x0000 };

int llsize_mouse[37] =
{ 8, 8, 1, 0, 1, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0, 0x07E0,
  0x07FF, 0xEFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFF80, 0xFF00, 0xFF80,
  0xFF80, 0xFF80, 0x0000, 0x03C0, 0x03C0, 0x03C0, 0x03C0, 0x03C0,
  0x03C0, 0x03FE, 0x47FE, 0x6FFE, 0x7F00, 0x7E00, 0x7C00, 0x7E00,
  0x7F00, 0x0000};

int ulsize_mouse[37] =
{ 8, 8, 1, 0, 1, 0xFF80, 0xFF80, 0xFF80, 0xFF00, 0xFF80, 0xFFFF,
  0xFFFF, 0xFFFF, 0xEFFF, 0x07FF, 0x07E0, 0x07E0, 0x07E0, 0x07E0,
  0x07E0, 0x07E0, 0x0000, 0x7F00, 0x7E00, 0x7C00, 0x7E00, 0x7F00,
  0x6FFE, 0x47FE, 0x03FE, 0x03C0, 0x03C0, 0x03C0, 0x03C0, 0x03C0,
  0x03C0, 0x0000 };

int ursize_mouse[37] =
{ 8, 8, 1, 0, 1, 0x01FF, 0x01FF, 0x01FF, 0x00FF, 0x01FF, 0xFFFF,
  0xFFFF, 0xFFFF, 0xFFF7, 0xFFE0, 0x07E0, 0x07E0, 0x07E0, 0x07E0,
  0x07E0, 0x07E0, 0x0000, 0x00FE, 0x007E, 0x003E, 0x007E, 0x00FE,
  0x7FF6, 0x7FE2, 0x7FC0, 0x03C0, 0x03C0, 0x03C0, 0x03C0, 0x03C0,
  0x03C0, 0x0000 };

int udmove_mouse[37] =
{ 8, 8, 1, 0, 1, 0x0000, 0x03C0, 0x07E0, 0x0FF0, 0x1FF8, 0x1FF8,
  0x1FF8, 0x03C0, 0x03C0, 0x1FF8, 0x1FF8, 0x1FF8, 0x0FF0, 0x07E0,
  0x03C0, 0x0000, 0x0000, 0x0000, 0x0180, 0x03C0, 0x07E0, 0x0FF0,
  0x0180, 0x0180, 0x0180, 0x0180, 0x0FF0, 0x07E0, 0x03C0, 0x0180,
  0x0000, 0x0000 };

int clip_mouse[37] =
{ 0x0008,0x0008,0x0001,0x0000,0x0001, 0x03C0,0x0660,0x1DB8,0xF18F,
	0x87E1,0xBFFD,0xBFFD,0xBFFD, 0xBFFD,0xBFFD,0xBFFD,0xBFFD,
	0xBFFD,0xBFFD,0x8001,0xFFFF, 0x0000,0x0180,0x0240,0x0E70,
	0x781E,0x5FFA,0x500A,0x570A, 0x514A,0x500A,0x536A,0x500A,
	0x5FFA,0x4002,0x7FFE,0x0000 };

int dial_mouse[37] =
{ 0x0008,0x0008,0x0001,0x0000,0x0001, 0xFFFF,0x8001,0xBFFD,0xBFFD,
	0xBFFD,0xBFFD,0xBFFD,0xBFFD, 0xBFFD,0xBFFD,0xBFFD,0xBFFD,
	0xBFFD,0xBFFD,0x8001,0xFFFF, 0x0000,0x7FFE,0x4422,0x55AA,
	0x4422,0x7FFE,0x4002,0x47C2, 0x4662,0x4662,0x4662,0x4662,
	0x47C2,0x4002,0x7FFE,0x0000 };

int text_mouse[37] =
{ 0x0008,0x0008,0x0001,0x0000,0x0001, 0xFFFF,0x8001,0xBFFD,0xBFFD,
	0xBFFD,0xBFFD,0xBFFD,0xBFFD, 0xBFFD,0xBFFD,0xBFFD,0xBFFD,
	0xBFFD,0xBFFD,0x8001,0xFFFF, 0x0000,0x7FFE,0x4422,0x55AA,
	0x4422,0x7FFE,0x4002,0x5EDA, 0x4CDA,0x4C72,0x4C72,0x4CDA,
	0x4CDA,0x4002,0x7FFE,0x0000 };

int timer_mouse[37] =
{ 0x0008,0x0008,0x0001,0x0000,0x0001, 0xFFFF,0x8001,0xBFFD,0xBFFD,
	0xBFFD,0xBFFD,0xBFFD,0xBFFD, 0xBFFD,0xBFFD,0xBFFD,0xBFFD,
	0xBFFD,0xBFFD,0x8001,0xFFFF, 0x0000,0x7FFE,0x4422,0x55AA,
	0x4422,0x7FFE,0x4002,0x47E2, 0x4182,0x4182,0x4182,0x4182,
	0x4182,0x4002,0x7FFE,0x0000 };

int trash_mouse[37] =
{ 0x0008,0x0008,0x0001,0x0000,0x0001, 0x07E0,0x0420,0x3DBC,0x6186,
	0xCFFB,0xBFFD,0xBFFD,0xBFFD, 0xBFFD,0xBFFD,0xBFFD,0xBFFD,
	0x9FF9,0xDFFB,0x4002,0x7FFE, 0x0000,0x03C0,0x0240,0x1E78,
	0x324C,0x4002,0x524A,0x520A, 0x52AA,0x524A,0x520A,0x4852,
	0x6C36,0x2004,0x3FFC,0x0000 };

/*
 *	Custom mouse routine
 *	by Ken Hollis
 *
 *	Returns: (0) on any type of failure
 *			 (-1) on successful custom mouse transaction
 *			 (any other number) to report the mouse result or a
 *								successful AES mouse transaction
 */
GLOBAL int WGrafMouse(int mo_sfield, ...)
{
	va_list	argptr;
	int	mform, store;

	switch(mo_sfield) {
		case GET_MOUSE:
			va_start(argptr, mo_sfield);
			mform = va_arg(argptr, int);
			store = va_arg(argptr, int);
			va_end(argptr);

			if (mouseform.forms[cur_mouse]!=0) {
				if (store) cur_mouse_form = (mouseform.forms[cur_mouse] == 0) ? cur_mouse_form : mouseform.forms[cur_mouse];
				return((mouseform.forms[cur_mouse] == 0) ? 0 : mouseform.forms[cur_mouse]);
			} else
				return(0);

		case SAVE_MOUSE:
			va_start(argptr, mo_sfield);
			mform = va_arg(argptr, int);
			store = va_arg(argptr, int);
			va_end(argptr);

			if (cur_mouse==16)
				return(0);
			else {
				if (store) cur_mouse_form = mform;
				mouseform.forms[cur_mouse++] = mform;
			}

			return(-1);

		case PREV_MOUSE:
			va_start(argptr, mo_sfield);
			mform = va_arg(argptr, int);
			store = va_arg(argptr, int);
			va_end(argptr);

			if (cur_mouse==1)
				return(0);
			else {
				if (store) cur_mouse_form = (mouseform.forms[(cur_mouse-1)] == 0) ? cur_mouse_form : mouseform.forms[(cur_mouse-1)];
				return((mouseform.forms[(cur_mouse-1)] == 0) ? 0 : mouseform.forms[(cur_mouse-1)]);
			}

		case NEXT_MOUSE:
			va_start(argptr, mo_sfield);
			mform = va_arg(argptr, int);
			store = va_arg(argptr, int);
			va_end(argptr);

			if (cur_mouse==16)
				return(0);
			else {
				if (store) cur_mouse_form = (mouseform.forms[(cur_mouse+1)] == 0) ? cur_mouse_form : mouseform.forms[(cur_mouse+1)];
				return((mouseform.forms[(cur_mouse+1)] == 0) ? 0 : mouseform.forms[(cur_mouse+1)]);
			}

		case FIRST_MOUSE:
			va_start(argptr, mo_sfield);
			mform = va_arg(argptr, int);
			store = va_arg(argptr, int);
			va_end(argptr);

			if (cur_mouse==1) {
				if (store) cur_mouse_form = (mouseform.forms[cur_mouse] == 0) ? cur_mouse_form : mouseform.forms[cur_mouse];
				return((mouseform.forms[cur_mouse] == 0) ? 0 : mouseform.forms[cur_mouse]);
			} else {
				if (store) cur_mouse_form = (mouseform.forms[1] == 0) ? cur_mouse_form : mouseform.forms[1];
				return((mouseform.forms[1] == 0) ? 0 : mouseform.forms[1]);
			}

		case LAST_MOUSE:
			{
				int pos = 1;

				va_start(argptr, mo_sfield);
				mform = va_arg(argptr, int);
				store = va_arg(argptr, int);
				va_end(argptr);

				do {
					if(mouseform.forms[pos]!=0) pos++;
					else {
						if (store) cur_mouse_form = mouseform.forms[pos];
						return(mouseform.forms[pos]);
					}
				} while(pos<16);

				return(0);
			}

		case CLEAR_MOUSE:
			{
				int pos = 1;

				do {
					mouseform.forms[pos++] = 0;
				} while(pos<16);

				return(-1);
			}

		case FIND_MOUSE:
			{
				int pos = 1;

				va_start(argptr, mo_sfield);
				mform = va_arg(argptr, int);
				store = va_arg(argptr, int);
				va_end(argptr);

				do {
					if(mouseform.forms[pos]==mform) {
						if (store) cur_mouse_form = mouseform.forms[pos];
						return(pos);
					} else pos++;
				} while(pos<16);

				return(0);
			}

		case NEWPOS_MOUSE:
			va_start(argptr, mo_sfield);
			mform = va_arg(argptr, int);
			va_end(argptr);

			cur_mouse = mform;

			return(-1);

		case ARROW:
		case TEXT_CRSR:
		case BUSYBEE:
		case POINT_HAND:
		case FLAT_HAND:
		case THIN_CROSS:
		case THICK_CROSS:
		case OUTLN_CROSS:
		case M_OFF:
		case M_ON:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(mo_sfield, 0L));
			}
			break;

		case M_SAVE:
		case M_RESTORE:
		case M_PREVIOUS:
			return(graf_mouse(mo_sfield, 0L));

		case INIT_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) init_mouse));
			}
			break;

		case LOAD_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) loadresource_mouse));
			}
			break;

		case LRSLIDE_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) lrmove_mouse));
			}
			break;

		case UDSLIDE_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) udmove_mouse));
			}
			break;

		case URMOVE_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) ursize_mouse));
			}
			break;

		case ULMOVE_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) ulsize_mouse));
			}
			break;

		case LLMOVE_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) llsize_mouse));
			}
			break;

		case LRMOVE_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) lrsize_mouse));
			}
			break;

		case CLIP_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) clip_mouse));
			}
			break;

		case DIALOG_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) dial_mouse));
			}
			break;

		case TEXT_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) text_mouse));
			}
			break;

		case TIMER_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) timer_mouse));
			}
			break;

		case TRASH_MOUSE:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(USER_DEF, (MFORM *) trash_mouse));
			}
			break;

		default:
			if (cur_mouse_form != mo_sfield) {
				mouseform.forms[cur_mouse] = cur_mouse_form = mo_sfield;
				return(graf_mouse(mo_sfield, 0L));
			}
			break;
	}
	return(-1);
}