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


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;
int exe;
XL_INTERPRETER * xli;
int wid;
extern VDISPLAY * env_display;
GBVIEW_FLAME * gf;

set_cpu_thr_type(30);


	gf = (GBVIEW_FLAME*)GET_TKEY(d);

	for ( ; env_display == 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:


	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:

/*
ss_printf("****************** winflame %i %ls %x\n",get_tid(),
       get_url_str2(&wf->draw->h.entry),wf->flags);
*/

	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;
	}
/*
ss_printf("****************** spiral end %i %x\n",get_tid(),wf);
*/

end:


	win_unlock(gf,wf);

	goto start;

}


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

	gf = (GBVIEW_FLAME *)GET_TKEY(d);

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

set_cpu_thr_type(13);
	wf_lock(gf);
retry:
	fg = 0;
	for ( wf = gf->flame ; wf ; ) {
		wf2 = wf->next;
		exit_lock_resource(wf->draw,1);
		_win_wlock(gf,wf);
		exit_lock_resource(wf->draw,0);
		_ex_lock(gf);
		if ( wf->flags & WFF_FREE ) {

printf("EXIT TASK\n");
			exit_win_flame(gf,wf);
			wakeup_task((int)wf);
			_wakeup_at_exit_task_wp(gf);
			_wakeup_at_redraw_wp(gf);
if ( gf->flame == 0 )
printf("EXIT NO FLAME!!!\n");
			_ex_unlock(gf);
			fg = 1;
		}
		else {
			_ex_unlock(gf);
			_win_unlock(gf,wf);
		}
		wf = wf2;
	}
	if ( fg )
		goto retry;
	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)
		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)) ) {
		case 0:
		case WFF_PLOT:
			change_win_flame(gf,wf,0,WFT_PLOT);
			break;
		default:
			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 ) {
			sleep_sec(1);
			continue;
		}
		change_task_gf(gf);
	}
}

