//	Zinc Application Framework - W_MOUSE.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <z_evtmgr.hpp>
#include <z_i18n.hpp>
#include <z_mouse2.hpp>
#include <z_string.hpp> // For strcmp().
#include <z_sysevt.hpp>
#include <w_app.hpp>
//??? All mouse images don't need to be included.
#define ZAF_MOUSE_INFO
#include "img_def.cpp"
#include "gbl_def.cpp"

// ----- ZafMouse ----------------------------------------------------------

ZafMouseData **ZafMouse::imageTable = ZAF_NULLP(ZafMouseData *);

ZafMouse::ZafMouse(ZafDeviceState _state, ZafDeviceImage _imageType) :
	ZafDevice(E_MOUSE, _state), imageType(_imageType)
{
	// Check the image information.
	ImageAllocate();
	SetStringID(className);
	SetNumberID((ZafNumberID)classID);

	// Initialize the mouse information.
	position.column = position.line = 0;
	offset.column = offset.line = 0;
	installed = true;
}

ZafMouse::~ZafMouse(void)
{
	// Check the image information.
	ImageFree();
	installed = false;
}

ZafEventType ZafMouse::Event(const ZafEventStruct &event)
{
	// Switch on the event type.
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	case D_OFF:
	case D_ON:
		deviceState = ccode;
		ShowCursor((deviceState == D_OFF) ? false : true);
		break;

	case D_STATE:
		return (deviceState);

	case D_POSITION:
		// Move the mouse pointer.
		SetCursorPos(event.position.column, event.position.line);
		break;

	default:
		// See if it is a change cursor request.
		if (ccode >= DM_MOUSE_FIRST && ccode <= DM_MOUSE_LAST)
		{
			// Reset the image type.
			imageType = (ZafDeviceImage)ccode;
			if (!imageTable)
				break;

			// Change the cursor image.
			for (int i = 0; imageTable[i]; i++)
				if (imageTable[i]->NumberID() == imageType)
				{
					SetCursor(imageTable[i]->handle);
					break;
				}
		}
		break;
	}

	// Return the ccode.
	return (ccode);
}

void ZafMouse::ImageAllocate(void)
{
	// Check for an allocated table.
	if (imageTable)
		return;

	// Define mouse system resources.
	static struct SYS_MOUSE
	{
		ZafDeviceImage imageID;
#if defined(ZAF_WIN32)
		const TCHAR *windowsResource;
#else
		const char *windowsResource;
#endif
		ZafMouseStruct *image;
	} _mouse[] = 
	{
		{ DM_VIEW, IDC_ARROW, &_view_ZafMouse },
		{ DM_SELECT, IDC_ARROW, &_view_ZafMouse },
		{ DM_EDIT, IDC_IBEAM, &_edit_ZafMouse },
		{ DM_WAIT, IDC_WAIT, &_wait_ZafMouse },
#if defined(ZAF_WIN32)
		{ DM_MOVE, IDC_SIZEALL, &_move_ZafMouse },
#else
		{ DM_MOVE, 0, &_move_ZafMouse },
#endif
		{ DM_LEFT_SIDE, IDC_SIZEWE, &_horizontal_ZafMouse },
		{ DM_RIGHT_SIDE, IDC_SIZEWE, &_horizontal_ZafMouse },
		{ DM_TOP_SIDE, IDC_SIZENS, &_vertical_ZafMouse },
		{ DM_BOTTOM_SIDE, IDC_SIZENS, &_vertical_ZafMouse },
		{ DM_TOP_LEFT_CORNER, IDC_SIZENWSE, &_left_ZafMouse },
		{ DM_TOP_RIGHT_CORNER, IDC_SIZENESW, &_right_ZafMouse },
		{ DM_BOTTOM_LEFT_CORNER, IDC_SIZENESW, &_left_ZafMouse },
		{ DM_BOTTOM_RIGHT_CORNER, IDC_SIZENWSE, &_right_ZafMouse },
		{ DM_CROSS_HAIRS, IDC_CROSS, &_crossHairs_ZafMouse },
		{ DM_CANCEL, 0, &_cancel_ZafMouse },
		{ DM_DRAG_MOVE, 0, &_dragMove_ZafMouse },
		{ DM_DRAG_COPY, 0, &_dragCopy_ZafMouse },
		{ DM_DRAG_MOVE_MULTIPLE, 0, &_dragMoveMultiple_ZafMouse },
		{ DM_DRAG_COPY_MULTIPLE, 0, &_dragCopyMultiple_ZafMouse },
		{ DM_VERTICAL_SPLIT, 0, &_vertical_split_ZafMouse },
		{ DM_HORIZONTAL_SPLIT, 0, &_horizontal_split_ZafMouse },
		{ 0, 0, 0 }
	};

	// Initialize the mouse images.
	ZafI18nData::AddStaticModule(ImageFree);
	imageTable = new ZafMouseData *[sizeof(_mouse) / sizeof(SYS_MOUSE)];

	int i;
	for (i = 0; _mouse[i].imageID; i++)
	{
		imageTable[i] = new ZafMouseData(*_mouse[i].image);
		imageTable[i]->hotSpotX = _mouse[i].image->hotSpotX;
		imageTable[i]->hotSpotY = _mouse[i].image->hotSpotY;
		if (_mouse[i].windowsResource)
		{
			imageTable[i]->handle = LoadCursor(NULL, _mouse[i].windowsResource);
			imageTable[i]->staticHandle = true;
		}
		else
			display->ConvertToOSMouse(*imageTable[i]);
		imageTable[i]->SetNumberID((ZafNumberID)_mouse[i].imageID);
	}
	imageTable[i] = ZAF_NULLP(ZafMouseData);
}

void ZafMouse::ImageFree(bool globalRequest)
{
	// Destroy the static images.
	if (globalRequest && imageTable)
	{
		for (int i = 0; imageTable[i]; i++)
			delete imageTable[i];
		delete []imageTable;
		imageTable = ZAF_NULLP(ZafMouseData *);
	}
}

bool ZafMouse::IsA(ZafClassID compareID) const
{
	return ((compareID == classID) ? true : ZafDevice::IsA(compareID));
}

bool ZafMouse::IsA(ZafClassName compareName) const
{
	return (!strcmp(compareName, className) ? true : ZafDevice::IsA(compareName));
}

void ZafMouse::Poll(void)
{
	// This code takes events off the queue if mouse is turned off.
	ZafEventStruct event;
	if (DeviceState() == D_OFF &&
		eventManager->Get(event, Q_BEGIN | Q_NO_DESTROY | Q_NO_POLL) == 0 &&
		(event.type == E_MOUSE || (event.type == E_MSWINDOWS && event.InputType() == E_MOUSE)))
		eventManager->Get(event, Q_BEGIN | Q_NO_POLL);
}

ZafDeviceImage ZafMouse::SetImageType(ZafDeviceImage newImageType)
{
	imageType = newImageType;
	return (imageType);
}

