// CIOThread.cpp
// Just for scanning the keyboard right now.
// Casey Fleser
// October 24, 1997

#include <BeHeaders>

#include "CIOThread.h"
#include "CMAMEDisplay.h"
#include "osdepend.h"

extern bool	gUseMouse;

bool			gOSDKeys[OSD_MAX_KEY+1];
key_info		CIOThread::sTheKeys[2];
int32		CIOThread::sCurIndex;

CIOThread::CIOThread(
	CMAMEDisplay	*inDisplay)
{
	mDisplay = inDisplay;
	ClearKeys();
	mQuitting = false;
	mActive = true;
}

CIOThread::~CIOThread()
{
	status_t		val;
	
	mQuitting = true;

	wait_for_thread(mID, &val);
}

int32
CIOThread::Entry(
	void		*arg)
{
	CIOThread	*obj = (CIOThread *)arg;
	
	return (obj->MainLoop());
}

void
CIOThread::ClearKeys()
{
	int32	i;
	
	for(i=0; i<OSD_MAX_KEY+1; i++)
		gOSDKeys[i] = false;
}

uchar
CIOThread::GetKey()
{
	uchar	theKey = 0xFF;
	int32	i;
	
	while (theKey == 0xFF) {
		for(i=0; i<OSD_MAX_KEY+1 && theKey == 0xFF; i++) {
			if (gOSDKeys[i])
				theKey = i;
		}
		
		if (theKey == 0xFF)
			snooze(100.0);
	}
	
	return theKey;
}

void
CIOThread::ReadKeys()
{
	int32	i;
	key_info	*lastKeys, *curKeys;
	
	sCurIndex = !sCurIndex;

	curKeys = &sTheKeys[sCurIndex];
	lastKeys = &sTheKeys[!sCurIndex];
	get_key_info(curKeys);

	for(i=0; i<OSD_MAX_KEY+1; i++) {
		bool		lastKey, curKey;
		
		lastKey = lastKeys->key_states[i>>3] & (1 << (7 - (i%8))) ? true : false;
		curKey = curKeys->key_states[i>>3] & (1 << (7 - (i%8))) ? true : false;
	
		if (curKey ^ lastKey)
			gOSDKeys[i] = curKey;
	}
	
}

void
CIOThread::Activate(
	bool		inState)
{
	mActive = inState;
	
	if (!mActive)
		ClearKeys();
}

int32
CIOThread::MainLoop()
{
	// service 60 times a second
	mNextTime = system_time() + (1000000/60);

	while (!mQuitting) {
		Snooze();
		
		if (mActive) {
			ReadKeys();
			if (gUseMouse)
				mDisplay->PollMouse();
		}
		
		SetNextTime();
	}
	return 0;
}

void
CIOThread::Snooze()
{
	if (mNextTime > system_time())
		snooze(mNextTime - system_time());
}

void
CIOThread::SetNextTime()
{
	bigtime_t		curTime;
	
	curTime = system_time();
	
	do {
		mNextTime += (1000000/60);
	} while (mNextTime < curTime);
}

int32
CIOThread::Go()
{
	mID = spawn_thread(Entry, "IOThread", B_URGENT_PRIORITY, this);
	return (resume_thread(mID));
}

