/**********************************************************************
 
	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.

**********************************************************************/


#include	<math.h>
#include	<string.h>
#include	"xl.h"
#include	"gbparam.h"
#include	"gbview.h"
#include	"win_flame.h"
#include	"pri_level.h"


typedef struct tc_type {
	char *		crd;
	int		tid;
} TC_TYPE;

TC_TYPE _test_crd[] = {
/*
	{"09.crd",0},
	{"08.crd",0},
	{"07.crd",0},
	{"06.crd",0},
*/
	{0,0}
};


void
set_test_crd(L_CHAR * res)
{
char * r;
int i;
int tid;
	tid = get_tid();
	r = n_string(std_cm,res);
	for ( i = 0 ; _test_crd[i].crd ; i ++ ) {
		if ( strcmp(r,_test_crd[i].crd) == 0 ) {
			_test_crd[i].tid = tid;
			break;
		}
		else if ( _test_crd[i].tid == tid )
			_test_crd[i].tid = 0;
	}
}

int
test_crd()
{
int i;
int tid;
	tid = get_tid();
	for ( i = 0 ; _test_crd[i].crd ; i ++ )
		if ( _test_crd[i].tid == tid )
			return 1;
	return 0;
}


void exit_task();

void
_sleep_at_exit_task_wp(GBVIEW_FLAME * gf,int flag)
{
	wf_sleep_task(gf,(int)&gf->exit_task_wp);
	if ( flag )
		wf_lock(gf);
}

void
_wakeup_at_exit_task_wp(GBVIEW_FLAME * gf)
{
	if ( gf->exit_task_wp == 0 ) {
		gf->exit_task_wp = 1;
		create_task(exit_task,(int)gf,PRI_DRAW_EXIT);
	}
	wakeup_task((int)&gf->exit_task_wp);
}

void
sleep_at_exit_task_wp(GBVIEW_FLAME * gf)
{
	wf_lock(gf);
	_sleep_at_exit_task_wp(gf,1);
	wf_unlock(gf);
}

void
wakeup_at_exit_task_wp(GBVIEW_FLAME * gf)
{
	wf_lock(gf);
	_wakeup_at_exit_task_wp(gf);
	wf_unlock(gf);
}

void
_sleep_at_redraw_wp(GBVIEW_FLAME * gf,int flag)
{
	wf_sleep_task(gf,(int)&gf->redraw_wp);
	if ( flag )
		wf_lock(gf);
}

void
_wakeup_at_redraw_wp(GBVIEW_FLAME * gf)
{
	wakeup_task((int)&gf->redraw_wp);
}

void
sleep_at_redraw_wp(GBVIEW_FLAME * gf)
{
	wf_lock(gf);
	_sleep_at_redraw_wp(gf,1);
	wf_unlock(gf);
}

void
wakeup_at_redraw_wp(GBVIEW_FLAME * gf)
{
	wf_lock(gf);
	_wakeup_at_redraw_wp(gf);
	wf_unlock(gf);
}



void
load_task(TKEY d)
{
WIN_FLAME * wf;
XL_INTERPRETER * xli;
int wid;
GBVIEW_FLAME * gf;




	gf = (GBVIEW_FLAME*)GET_TKEY(d);

	for ( ; gf->default_ws == 0 ; )
		sleep_sec(1);


	wf_lock(gf);
	gf->run_req_task_nos ++;
	wf_unlock(gf);

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);

start:
	change_pri(0,PRI_START_DRAW);

	wf = touch_wf(gf);
	if ( wf == 0 ) {
		wf_lock(gf);
		if ( gf->req_task_nos ) {
			wf_unlock(gf);
			goto start;
		}
		gf->run_req_task_nos --;
		wf_unlock(gf);
		close_self_interpreter();
		return;
	}

	printf("load task start %i\n",get_tid());



retry:
	change_pri(0,PRI_DRAW);



	if ( wf->flags & WFF_FREE )
		goto end;

	switch ( win_flame_redraw(gf,wf) ) {
	case 0:
		break;
	case 2:
		wf_lock(gf);
		if ( wf->flags & WFF_FREE ) {
			wf_unlock(gf);
			goto end;
		}
		if ( _check_exit_flame(gf) == 0 ) {
			wf_unlock(gf);
			goto retry;
		}
		wid = wf->id;
		_win_unlock(gf,wf);
		for ( ; _check_exit_flame(gf) ; ) {
			_wakeup_at_exit_task_wp(gf);
			_sleep_at_redraw_wp(gf,1);

			if ( _get_wf_ptr(gf,wid) != wf ) {
				wf_unlock(gf);
				goto start;
			}
			if ( wf->flags & WFF_FREE ) {
				wf_unlock(gf);
				goto start;
			}
		}
		if ( _get_wf_ptr(gf,wid) != wf ) {
			wf_unlock(gf);
			goto start;
		}
		if ( _win_lock(gf,wf) < 0 ) {
			wf_unlock(gf);
			goto start;
		}
		wf_unlock(gf);
		goto retry;
	default:
		goto retry;
	}



end:


	win_unlock(gf,wf);

	goto start;

}


void
exit_task(TKEY d)
{
WIN_FLAME * wf, * wf2;
XL_INTERPRETER * xli;
int fg;
GBVIEW_FLAME * gf;
RESOURCE * target;

printf("EXIT TASK --- START\n");
	gf = (GBVIEW_FLAME *)GET_TKEY(d);

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);
	

retry:
	wf_lock(gf);
	fg = 0;
	for ( wf = gf->flame ; wf ; ) {
		wf2 = wf->next;
		if ( wf->flags & WFF_FREE ) {

ss_printf("EXIT TASK-1 %ls\n",get_url_str2(&wf->draw->h.entry));
			exit_lock_resource(target = wf->draw,1);
			_win_wlock(gf,wf);
			_ex_lock(gf);
ss_printf("EXIT TASK-2 %ls\n",get_url_str2(&wf->draw->h.entry));

			exit_win_flame(gf,wf);
			exit_lock_resource(target,0);
			wakeup_task((int)wf);
			_wakeup_at_exit_task_wp(gf);
			_wakeup_at_redraw_wp(gf);
if ( gf->flame == 0 )
ss_printf("EXIT NO FLAME!!!\n");
			_ex_unlock(gf);


			fg = 1;
			break;
		}
/*
		else {
			_ex_unlock(gf);
			_win_unlock(gf,wf);
		}
*/
		wf = wf2;
	}
	wf_unlock(gf);


	if ( fg )

		goto retry;
	wf_lock(gf);
	gf->exit_task_wp --;
	wf_unlock(gf);

	close_self_interpreter();

}

void
change_task_gf(GBVIEW_FLAME * gf)
{
WIN_FLAME * wf;
int wfid;
WIN_FLAME_TABLE * tbl;
GB_RECT rr;

	wf_check_resource(gf);
	for ( wfid = get_next_wfid(gf,0) ; wfid ; 
			wfid = get_next_wfid(gf,wfid) ) {

		wf_lock(gf);
		ZONBIE_CHECK_BREAK(gf,wf_unlock(gf))
		wf = _get_wf_ptr(gf,wfid);
		if ( wf == 0 ) {
			wf_unlock(gf);
			continue;
		}
		if ( _win_wlock(gf,wf) < 0 ) {
			wf_unlock(gf);
			continue;
		}
		wf_unlock(gf);
		ex_lock(gf); 

		tbl = wf->tbl;
		switch ( (wf->flags&(WFF_POLY|WFF_PLOT|WFF_LUSTER|WFF_LUSTER_DIRTY)) ) {
		case 0:
		case WFF_PLOT:
			change_win_flame(gf,wf,0,WFT_PLOT);
			break;
		default:
			change_win_flame(gf,wf,0,WFT_STD);
		}
/*
		if ( wf->flags&(WFF_LUSTER_DIRTY) ) {
			change_win_flame(gf,wf,0,WFT_STD);
		}
*/
		if ( tbl != wf->tbl ) {
			rr.tl.x = rr.tl.y = 0;
			rr.br.x = gf->win_width;
			rr.br.y = gf->win_height;
			_win_flame_dirty(gf,wf,&rr,WFF_DIRTY,0);
		}
		ex_unlock(gf);
		win_unlock(gf,wf);
	}
}


void
change_task()
{
GBVIEW_FLAME * gf;
	gf = 0;
	for ( ; ; ) {
		gf = wf_next_gf(gf,GVFS_ACTIVE);
		if ( gf == 0 ) {
			new_timeout((int)change_task,2);
			sleep_task((int)change_task,SEM_NULL);
			del_timeout((int)change_task);
			continue;
		}
		change_task_gf(gf);
	}
}



void
force_change_task()
{
	wakeup_task((int)change_task);
}


