//
// 
//	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
// 
//	This program is free software; you can redistribute it 
//	and/or modify it under the terms of the GLOBALBASE 
//	Library General Public License (G-LGPL) as published by 
//
//	http://www.globalbase.org/
// 
//	This program is distributed in the hope that it will be 
//	useful, but WITHOUT ANY WARRANTY; without even the 
//	implied warranty of MERCHANTABILITY or FITNESS FOR A 
//	PARTICULAR PURPOSE.
//
//

extern "C" {


#include <stdio.h>
#include "task.h"
#include "machine/v_types.h"
#include "pri_level.h"
#include "event_list.h"
#include "xl.h"
#include "CLEMWindow.h"

Bool	startup_flag = false;
LThread *	event_thread = nil;
Point	curMouse;

typedef struct {
	EVENT	new_event;
	VDISPLAY * new_d;
	int new_n;
} new_v_loop_type;

void _redraw(VWINDOW * win,int x,int y,int w,int h);
void _button(VWINDOW * win,int subtype,int t,int x,int y);
void _null();
void _invoke();
int get_tid();
void CheckICMapEntry();
int new__redraw(new_v_loop_type * arg);
int new__button(new_v_loop_type * arg);
int new__null();
int new__invoke();
void v_loop(VDISPLAY * d);

Bool
new_NextEvent(new_v_loop_type * arg);

Bool
new_NextEvent(new_v_loop_type * arg)
{
static Point last, pt;
Bool ret;
EVENT * newEvent = &arg->new_event;
EventRecord theEvent;
	ret = get_event(&arg->new_event);
	if ( ! ret && ! EventAvail(mUpMask, &theEvent) ) {
		if ( last.h != curMouse.h || last.v != curMouse.v ) {
			last = curMouse;
			
			WindowPtr		macWindowP;			// Ask Toolbox where the mouse is
			SInt16			thePart = ::MacFindWindow(curMouse, &macWindowP);
			if ((thePart == inContent) || (thePart == inGrow)) {	// Mouse is inside a Window
				Window	theWindow = dynamic_cast<Window>(LWindow::FetchWindowObject(macWindowP));
				if ( theWindow ) {
					theWindow->FocusDraw();
					GetMouse(&pt);
					newEvent->type = VE_BUTTON;
					newEvent->subtype = VES_BUTTON_MOTION;
					newEvent->x = pt.h;
					newEvent->y = pt.v;
					newEvent->t = ::TickCount();
					newEvent->win = theWindow;
					ret = true;
				}
			}
		}
	}
	return ret;
}


int
new__redraw(new_v_loop_type * arg)
{
	EVENT *e = &arg->new_event;
	_redraw(_get_vwin(arg->new_d, e->win), e->x, e->y, e->w, e->h);
	return 0;
}

int
new__button(new_v_loop_type * arg)
{
	EVENT *e = &arg->new_event;
	_button(_get_vwin(arg->new_d, e->win), e->subtype, e->t, e->x, e->y);
	return 0;
}

int
new__null()
{
	_null();
	return 0;
}

int
new__invoke()
{
	_invoke();
	return 0;
}


void
new_v_loop(TKEY d)
{
new_v_loop_type arg;
int null_flag;
XL_INTERPRETER * xli;

	arg.new_d = (VDISPLAY*)GET_TKEY(d);
	fprintf(stderr,"!!!!! start new_v_loop(threadID :=  %d)\n", get_tid());
	fflush(stdout);

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);
	
	null_flag = 0;
	for ( ; ; )
	{
		if ( ! new_NextEvent(&arg) )
		{
			if ( null_flag == 0 )
				new__null();
			null_flag = 1;
			event_thread = LThread::GetCurrentThread();
			event_thread->Suspend();
			event_thread = nil;
			continue;
		}
		if ( null_flag )
			new__invoke();
		null_flag = 0;
		switch ( arg.new_event.type )
		{
		case VE_REDRAW:
			new__redraw(&arg);
			break;
		case VE_BUTTON:
			new__button(&arg);
			break;
		}
	}
}

void
v_loop(VDISPLAY * d)
{
	startup_flag = true;
		// Check Internet Config to open ".gc" using this application.
	CheckICMapEntry();
	
	create_task((void(*)())new_v_loop,(int)d,PRI_TOOLKIT);
	ms_loop();
}

} // extern "C"