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

extern "C" {
#include	<stdlib.h>
#include	"memory_debug.h"
#include	"memory_routine.h"
#include	"xl.h"
#include	"xlerror.h"
#include	"utils.h"
#include	"gbview.h"
#include	"win_flame.h"
#include	"lock_level.h"
#include	"viewindex.h"
#include	"radar.h"
}
#include	"v/v_switch.h"


#define FS_HASH_SIZE	101

SEM view_agent_session_lock;
FLAME_SWITCH ** flame_sw_hash;

int list2loading_status(LOADING_STATUS * ,XL_SEXP *);



INLINE_STATIC XL_SEXP * view_agent_session(const FLAME_SWITCH * sw,L_CHAR * center_cmd, XL_SEXP * cmd);


XL_SEXP *
xl_win_flame_event(
	XLISP_ENV * e,
	XL_SEXP * s,
	XLISP_ENV * a,
	XL_SYM_FIELD * sf);

XL_SEXP *
xl_win_flame_indicate_event(
	XLISP_ENV * e,
	XL_SEXP * s,
	XLISP_ENV * a,
	XL_SYM_FIELD * sf);



extern "C" void
init_gv_flame_switch(XLISP_ENV * env)
{
int i;
	view_agent_session_lock = new_lock(LL_VIEW_AGENT_SESSION);
	
	flame_sw_hash = (FLAME_SWITCH**)d_alloc(sizeof(FLAME_SWITCH)*FS_HASH_SIZE);
	for ( i = 0 ; i < FS_HASH_SIZE ; i ++ )
		flame_sw_hash[i] = 0;
	set_env(gblisp_top_env0, l_string(std_cm,"win-flame-event"),
			get_func_prim((xl_sexp*(*)())xl_win_flame_event,FO_APPLICATIVE,0,3,3));
	set_env(gblisp_top_env0, l_string(std_cm,"win-flame-indicate-event"),
			get_func_prim((xl_sexp*(*)())xl_win_flame_indicate_event,FO_APPLICATIVE,0,2,2));
}


FLAME_SWITCH *
_search_sw_id(int id)
{
int key;
FLAME_SWITCH * sp;
	key = id % FS_HASH_SIZE;
	for ( sp = flame_sw_hash[key] ; sp ; sp = sp->next )
		if ( sp->id == id )
			return sp;
	return 0;
}

void
_insert_sw_hash(FLAME_SWITCH * sw)
{
int key;
	key = sw->id % FS_HASH_SIZE;
	sw->next = flame_sw_hash[key];
	flame_sw_hash[key] = sw;
}

void
_delete_sw_hash(FLAME_SWITCH * sw)
{
int key;
FLAME_SWITCH ** sp;
	if ( sw->id == 0 )
		return;
	key = sw->id % FS_HASH_SIZE;
	for ( sp = &flame_sw_hash[key];
			*sp;
			sp = &(*sp)->next )
		if ( *sp == sw ) {
			*sp = sw->next;
			sw->id = 0;
			return;
		}
}

FLAME_SWITCH *
search_sw_id(int id)
{
FLAME_SWITCH * ret;
	lock_task(view_agent_session_lock);
	ret = _search_sw_id(id);
	unlock_task(view_agent_session_lock,"search_sw_id");
	return ret;
}

void
insert_sw_hash(FLAME_SWITCH * sw)
{
	lock_task(view_agent_session_lock);
	_insert_sw_hash(sw);
	unlock_task(view_agent_session_lock,"search_sw_id");
}

void
delete_sw_hash(FLAME_SWITCH * sw)
{
	lock_task(view_agent_session_lock);
	_delete_sw_hash(sw);
	unlock_task(view_agent_session_lock,"search_sw_id");
}


INLINE_STATIC XL_SEXP *
view_agent_session(const FLAME_SWITCH * sw,L_CHAR * center_cmd, XL_SEXP * cmd)
{
XL_SEXP * ret;

	if ( get_my_xli() == 0 ) {
		XL_INTERPRETER *xli = new_xl_interpreter();
		xli->a_type = XLA_SELF;
		setup_i(xli);
	}
fflush(stdout);
s_printf(s_stdout," <- ");
print_sexp(s_stdout,cmd,0);
s_printf(s_stdout,"\n");
fflush(stdout);

	lock_task(view_agent_session_lock);
	ret = remote_session(
		gblisp_top_env0,
		sw->view_agent_ses,
		const_cast<URL*>(&sw->view_agent_url),
		l_string(std_cm,"gbview"),
		l_string(std_cm,"user"),
		center_cmd,
		List(cmd,-1),
		0,0,1,0);
	unlock_task(view_agent_session_lock,"view_agent_session");

s_printf(s_stdout," -> ");
print_sexp(s_stdout,ret,PF_RAW_DISABLE);
s_printf(s_stdout,"\n");
fflush(stdout);

	return ret;
}

void
gvagent_redraw(FLAME_SWITCH * sw)
{
// why this func is called by tick thread
// now enabled tick thread. if it does not go well, let it be before.
	if ( sw->gvagent_need_redraw ) {
//		if ( fw->ix.type == 0 ) {
			sw->gvagent_need_redraw = 0;
			if ( sw->sw_event_func )
				(*sw->sw_event_func)(
					sw->gf,
					ET_REDRAW,
					0,
					sw->sw_event_user_arg);
//		}
	}
}

XL_SEXP * 
n_get_symbol_with_fid(const FLAME_SWITCH * sw, char * name)
{
	XL_SEXP * ret = n_get_symbol(name);
	char buf[20];
	sprintf(buf,"%d",sw->id);
	set_attribute(ret,l_string(std_cm,"flame-id"),l_string(std_cm,buf));
	return ret;
}

XL_SEXP * 
n_get_symbol_with_format(const FLAME_SWITCH * sw, char * name)
{
	XL_SEXP * ret = n_get_symbol_with_fid(sw,name);
	if ( sw->gv_redraw_format )
		set_attribute(ret,l_string(std_cm,"format"),sw->gv_redraw_format);
	if ( sw->gv_redraw_quality )
		set_attribute(ret,l_string(std_cm,"quality"),sw->gv_redraw_quality);
	return ret;
}

int
call_wf_set_flame_switch(
	FLAME_SWITCH * sw,
	int mode,
	L_CHAR * url,
	L_CHAR * parameter,
	L_CHAR * peripheral,
	L_CHAR * format,
	L_CHAR * quality)
{
XL_SEXP * result, *gbview_first_cmd;

printf("FLAME SWITCH\n");
	if ( format )
		sw->gv_redraw_format = ll_copy_str(format);
	if ( quality )
		sw->gv_redraw_quality = ll_copy_str(quality);

	switch ( mode ) {
	case SW_MODE_IDLE:
		if ( sw->mode == SW_MODE_REMOTE ) {
			gc_push(0,0,"call_wf_set_flame_switch");
			result = view_agent_session(sw,l_string(std_cm,"gv-flame-close"),
				List(n_get_symbol_with_fid(sw,"gv-flame-close"),-1));
			close_session(sw->view_agent_ses);
			gc_pop(0,0);
			sw->view_agent_ses = 0;
			delete_sw_hash(sw);
		}
		else {
			wf_close(sw->gf);
		}
		sw->mode = mode;
		sw->id = 0;
		sw->gf = 0;
		if ( sw->gv_redraw_format )
			d_f_ree(sw->gv_redraw_format);
		sw->gv_redraw_format = 0;
		if ( sw->gv_redraw_quality )
			d_f_ree(sw->gv_redraw_quality);
		sw->gv_redraw_quality = 0;
		if ( sw->parameter )
			d_f_ree(sw->parameter);
		sw->parameter = 0;
		if ( sw->peripheral )
			d_f_ree(sw->peripheral);
		sw->peripheral = 0;
		return 0;
	case SW_MODE_LOCAL:
		sw->mode = mode;
		delete_sw_hash(sw);
		sw->gf = wf_open();
		if ( sw->gv_redraw_format )
			d_f_ree(sw->gv_redraw_format);
		sw->gv_redraw_format = 0;
		if ( sw->gv_redraw_quality )
			d_f_ree(sw->gv_redraw_quality);
		sw->gv_redraw_quality = 0;
		if ( sw->parameter )
			d_f_ree(sw->parameter);
		sw->parameter = 0;
		if ( sw->peripheral )
			d_f_ree(sw->peripheral);
		sw->peripheral = 0;
		return 0;
	case SW_MODE_REMOTE:
		sw->mode = mode;
		sw->gf = 0;
		break;
	default:
		er_panic("not support_mode");
	}

	free_url(&sw->view_agent_url);
	if ( !url || get_url2(&sw->view_agent_url,url) < 0 )
		goto param_error;

	sw->view_agent_ses = open_session(SEST_OPTIMIZE);
	gc_push(0,0,"xl_gv_flame_switch");

	gbview_first_cmd = eval(gblisp_top_env0, n_get_symbol("gbview-first-cmd"));
	if ( get_type(gbview_first_cmd) == XLT_PAIR ) {
		result = view_agent_session(sw,l_string(std_cm,"gbview-first-cmd"),
			gbview_first_cmd);
		if ( get_type(result) == XLT_ERROR ) {
			ss_printf("gbview-first-cmd failure : ");
			print_sexp(s_stdout,result,0);
			ss_printf("\n");
		}
	}

	result = view_agent_session(sw,l_string(std_cm,"gv-flame-open"),
		List(n_get_symbol("gv-flame-open"),-1));
	switch ( get_type(result) ) {
	case XLT_INTEGER:
		sw->id = result->integer.data;
		break;
	default:
		ss_printf("gv-flame-open failure : ");
		print_sexp(s_stdout,result,0);
		ss_printf("\n");
		gc_pop(0,0);
		goto param_error;
	}
	gc_pop(0,0);

	insert_sw_hash(sw);
	new_tick((void(*)(int))gvagent_redraw,1,(int)sw);
	return 0;

param_error:
	return -1;
}


XL_SEXP *
xl_win_flame_event(
	XLISP_ENV * e,
	XL_SEXP * s,
	XLISP_ENV * a,
	XL_SYM_FIELD * sf)
{
GBVIEW_PLANE gbp;
GBVIEW_STATUS sts;
XL_SEXP * type, * w;
L_CHAR * id;
FLAME_SWITCH * sw;

	id = get_sf_attribute(sf,l_string(std_cm,"flame-id"));
	if ( id == 0 )
		sw = search_sw_id(1);
	else	sw = search_sw_id(atoi(n_string(std_cm,id)));
	if ( sw == 0 )
		er_panic("xl_win_flame_indicate_event : invalid flame-id");

	type = get_el(s,1);
	if ( get_type(type) != XLT_INTEGER )
		goto type_missmatch;
		
print_sexp(s_stdout,s,PF_RAW_DISABLE);
s_printf(s_stdout,"\n");

	switch ( type->integer.data ) {
	case ET_REDRAW:
		sw->gvagent_need_redraw = 1;
		gvagent_redraw(sw);
		break;
	case ET_CLICK:
		w = get_el(s,2);
		if ( list2gbp(w,&gbp) == 0 )
			goto param_error;
		if ( sw->sw_event_func )
			(*sw->sw_event_func)(
				sw->gf,
				type->integer.data,
				&gbp,
				sw->sw_event_user_arg);
		wf_free_plane(&gbp);
		break;
	case ET_INFO:
		w = get_el(s,2);
		if ( list2gvstatus(w,&sts) < 0 )
			goto param_error;
		if ( sts.flags & (SF_REFERENCE | SF_ERROR) )
			if ( sw->sw_event_func )
				(*sw->sw_event_func)(
					sw->gf,
					type->integer.data,
					&sts,
					sw->sw_event_user_arg);
				// SF_INFOLIST is not supported
		wf_free_status(&sts);
		break;
	case ET_INSERT:
	case ET_CHANGE_BASE:
	case ET_LOCK_BASE:
		if ( sw->sw_event_func )
			(*sw->sw_event_func)(
				sw->gf,
				type->integer.data,
				0,
				sw->sw_event_user_arg);
		break;
	default:
		er_panic("xl_win_flame_event");
	}
	return 0;
	
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"win-flame-event"),
		List(n_get_string("type missmatch"),
			-1));
param_error:
	fflush(stdout);
	print_sexp(s_stdout,s,0);
	s_printf(s_stdout," - INVALID PARAM\n");
	
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"win-flame-event"),
		List(n_get_string("invalid event parameter"),
			-1));
}




int
call_wf_status(FLAME_SWITCH * sw,GBVIEW_STATUS * sts, int call_sts_cache_flag)
{
XL_SEXP * result;
INDICATE * in, * in1;
GBVIEW_LAYER_STATUS * ls, * ls1;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		memset(sts,0,sizeof(*sts));
		return -1;
	case SW_MODE_LOCAL:
		wf_status(sw->gf,sts);
		return 0;
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_status");
	}

	if ( call_sts_cache_flag == CALL_STS_CACHE_NORMAL && sw->call_sts_cache_valid ) {
		lock_task(view_agent_session_lock);
		*sts = sw->sts_cache;
		sts->indicate = 0;
		for ( in = sw->sts_cache.indicate ; in ; in = in->next ) {
			in1 = (INDICATE*)d_alloc(sizeof(*in1));
			*in1 = *in;
			copy_url(&in1->url,&in->url);
			if ( in->unit )
				in1->unit = ll_copy_str(in->unit);
			in1->next = sts->indicate;
			sts->indicate = in1;
		}
		sts->layers = 0;
		for ( ls = sw->sts_cache.layers ; ls ; ls = ls->next ) {
			ls1 = (GBVIEW_LAYER_STATUS*)d_alloc(sizeof(*ls1));
			*ls1 = *ls;
			ls1->entry_url = ll_copy_str(ls->entry_url);
			ls1->target_url = ll_copy_str(ls->target_url);
			ls1->next = sts->layers;
			sts->layers = ls1;
		}
		if ( sw->sts_cache.flame_base_unit )
			sts->flame_base_unit = ll_copy_str(sw->sts_cache.flame_base_unit);
		unlock_task(view_agent_session_lock,"call_wf_status(1)");
		return 0;
	}

	gc_push(0,0,"call_wf_status");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-status"),
			List(n_get_symbol_with_fid(sw,"gv-flame-status"),-1));

	lock_task(view_agent_session_lock);
	list2gvstatus(result, sts);
	if ( sts->layer_nos ) {
		wf_free_status(&sw->sts_cache);
		sw->sts_cache = *sts;
		sw->sts_cache.indicate = 0;
		for ( in = sts->indicate ; in ; in = in->next ) {
			in1 = (INDICATE*)d_alloc(sizeof(*in1));
			*in1 = *in;
			copy_url(&in1->url,&in->url);
			if ( in->unit )
				in1->unit = ll_copy_str(in->unit);
			in1->next = sw->sts_cache.indicate;
			sw->sts_cache.indicate = in1;
		}
		sts->layers = 0;
		for ( ls = sts->layers ; ls ; ls = ls->next ) {
			ls1 = (GBVIEW_LAYER_STATUS*)d_alloc(sizeof(*ls1));
			*ls1 = *ls;
			ls1->entry_url = ll_copy_str(ls->entry_url);
			ls1->target_url = ll_copy_str(ls->target_url);
			ls1->next = sw->sts_cache.layers;
			sw->sts_cache.layers = ls1;
		}
		if ( sts->flame_base_unit )
			sw->sts_cache.flame_base_unit = ll_copy_str(sts->flame_base_unit);
		sw->call_sts_cache_valid = 1;
	}
	unlock_task(view_agent_session_lock,"call_wf_status(2)");
	gc_pop(0,0);
	return 0;
}

int
call_wf_set_status(FLAME_SWITCH * sw,GBVIEW_STATUS * e)
{
XL_SEXP * result;
int ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return wf_set_status(sw->gf,e);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_set_status");
	}
	
	sw->call_sts_cache_valid = 0;

	gc_push(0,0,"call_wf_set_status");

	if ( e->flags & SF_EVENT ) {
		sw->sw_event_func = e->event;
		sw->sw_event_user_arg = e->event_user_arg;
	}

	result = view_agent_session(sw,l_string(std_cm,"gv-flame-set-status"),
				List(n_get_symbol_with_fid(sw,"gv-flame-set-status"),
					List(n_get_symbol("quote"),gvstatus2list(e),-1),
					-1));
	if ( get_type(result) == XLT_INTEGER )
		ret = result->integer.data;
	else
		ret = 0;
	gc_pop(0,0);

	return ret;
}

int
call_wf_set_overlay(FLAME_SWITCH * sw,L_CHAR * u,int flags,int mask)
{
XL_SEXP * result;
int ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return wf_set_overlay(sw->gf,u,flags,mask);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_set_status");
	}
	
	gc_push(0,0,"call_wf_set_overlay");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-set-overlay"),
		List(n_get_symbol_with_fid(sw,"gv-flame-set-overlay"),
			get_string(u),
			get_integer(flags,0),
			get_integer(mask,0),
			-1));
	if ( get_type(result) == XLT_INTEGER )
		ret = result->integer.data;
	else
		ret = -1;
	gc_pop(0,0);
	return ret;
}

int
call_wf_click(FLAME_SWITCH * sw,GBVIEW_STATUS * sts,GBVIEW_PLANE * p,int x,int y)
{
XL_SEXP * result, * seq;
int ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return wf_click(sw->gf,sts,p,x,y);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_click");
	}
	
	sw->call_sts_cache_valid = 0;

	gc_push(0,0,"call_wf_set_status");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-click"),
		List(n_get_symbol_with_format(sw,"gv-flame-click"),
		get_integer(x,0),get_integer(y,0),-1));
	ret = 0;
	if ( get_type(result) != XLT_ERROR ) {
		seq = car(result);
		if ( get_type(seq) == XLT_INTEGER )
			ret = seq->integer.data;
		if ( ret && p )
			list2gbp(car(cdr(cdr(result))),p);
		list2gvstatus(car(cdr(result)),sts);
	}
	else {
		fflush(stdout);
		s_printf(s_stdout,"gv-flalme-click -> ");
		print_sexp(s_stdout,result,0);	
		s_printf(s_stdout,"\n");
	}
	gc_pop(0,0);
	return ret;
}

int
call_wf_zoom(FLAME_SWITCH * sw,GBVIEW_PLANE * p,REAL1 zoom)
{
int ret;
XL_SEXP * result;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return wf_zoom(sw->gf,p,zoom);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_zoom");
	}
	
	sw->call_sts_cache_valid = 0;

	gc_push(0,0,"call_wf_zoom");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-zoom"),
		List(n_get_symbol_with_fid(sw,"gv-flame-zoom"),
			get_floating(zoom,0),-1));
	if ( get_type(result) != XLT_INTEGER ) {
		gc_pop(0,0);
		return 0;
	}
	ret = result->integer.data;
	gc_pop(0,0);
	
	if ( p ) {
	GBVIEW_STATUS sts;
		sts.flags = SF_WIDTH|SF_HEIGHT;
		call_wf_status(sw,&sts,CALL_STS_CACHE_NORMAL);

		p->h.type = GPT_ZOOM;
		p->h.seq = ret;
		p->z.index_x = (int*)d_alloc(sizeof(int)*sts.width);
		p->z.index_y = (int*)d_alloc(sizeof(int)*sts.height);
		wf_make_zoom_index(p->z.index_x,p->z.index_y,zoom,
				sts.width,sts.height);
	}
	return ret;
}

int
call_wf_move(FLAME_SWITCH * sw,I_POINT from,I_POINT to)
{
XL_SEXP * result;
int ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return wf_move(sw->gf,from,to);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_move");
	}
	
	sw->call_sts_cache_valid = 0;

	gc_push(0,0,"call_wf_move");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-move"),
		List(n_get_symbol_with_fid(sw,"gv-flame-move"),
			get_integer(from.x,0),
			get_integer(from.y,0),
			get_integer(to.x,0),
			get_integer(to.y,0),
			-1));
	if ( get_type(result) == XLT_INTEGER )
		ret = result->integer.data;
	else
		ret = 0;
	gc_pop(0,0);
	return ret;
}

int
call_wf_rotate(FLAME_SWITCH * sw,GB_POINT from,GB_POINT to)
{
XL_SEXP * result;
int ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return wf_rotate(sw->gf,from,to);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_Wf_rottate");
	}
	
	sw->call_sts_cache_valid = 0;

	gc_push(0,0,"call_wf_rotate");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-rotate"),
		List(n_get_symbol_with_fid(sw,"gv-flame-rotate"),
			get_floating(from.x,0),
			get_floating(from.y,0),
			get_floating(to.x,0),
			get_floating(to.y,0),
			-1));
	if ( get_type(result) == XLT_INTEGER )
		ret = result->integer.data;
	else
		ret = 0;
	gc_pop(0,0);
	return ret;
}

int
call_wf_redraw(FLAME_SWITCH * sw,GBVIEW_PLANE * p,int x,int y,int w,int h)
{
XL_SEXP * result, * seq;
int ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return wf_redraw(sw->gf,p,x,y,w,h);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_redraw");
	}

	gc_push(0,0,"call_wf_redraw");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-redraw"),
		List(n_get_symbol_with_format(sw,"gv-flame-redraw"),
			get_integer(x,0),
			get_integer(y,0),
			get_integer(w,0),
			get_integer(h,0),
			-1));
/*
	if ( get_type(result) != XLT_PAIR ) {
		fflush(stdout);
		s_printf(s_stdout, "gv-flame-redraw -> ");
		print_sexp(s_stdout, result, 0);
		s_printf(s_stdout, "\n");
		fflush(stdout);
	}
*/
	seq = car(result);
	if ( get_type(seq) == XLT_INTEGER )
		ret = seq->integer.data;
	else
		ret = 0;
	if ( ret != 0 ) {
		list2gbp(result,p);
	}
	else {
		p->h.type = GPT_REDRAW;
		p->h.seq = 0;
		p->r.r.tl.x = p->r.r.br.x = 0;
		p->r.r.tl.y = p->r.r.br.y = 0;
		p->r.plane = 0;
		ret = 0;
	}
	gc_pop(0,0);
	return ret;
}

void
call_wf_indicate(FLAME_SWITCH * sw,GBVIEW_STATUS * sts,int x,int y,int button)
{
XL_SEXP * result;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return;
	case SW_MODE_LOCAL:
		wf_indicate(sw->gf,sts,x,y,button);
		return;
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_Wf_indicate");
	}
	
	sw->call_sts_cache_valid = 0;

	gc_push(0,0,"call_wf_indicate");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-point-status"),
		List(n_get_symbol_with_fid(sw,"gv-flame-point-status"),
			get_integer(x,0),
			get_integer(y,0),
			-1));
	if ( sts && get_type(result) == XLT_PAIR )
		list2gvstatus(result,sts);
	gc_pop(0,0);
}

int
call_wf_purge_select(FLAME_SWITCH * sw)
{
XL_SEXP * result;
int ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return wf_purge_select(sw->gf);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_Wf_purge_select");
	}
	
	sw->call_sts_cache_valid = 0;

	gc_push(0,0,"call_wf_purge_select");
	result = view_agent_session(sw,l_string(std_cm,"gv-flame-purge-select"),
		cons(n_get_symbol_with_fid(sw,"gv-flame-purge-select"),0));
	if ( get_type(result) == XLT_INTEGER )
		ret = result->integer.data;
	else
		ret = 0;
	gc_pop(0,0);
	return ret;
}

void
call_wf_get_coordinate_info(FLAME_SWITCH * sw,L_CHAR ** name,int * rid,GB_POINT * ptr,int ptr_len)
{
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return;
	case SW_MODE_LOCAL:
		wf_get_coordinate_info(sw->gf,name,rid,ptr,ptr_len);
		return;
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_get_coordinate_info");
	}

	*rid = 0;
	return;
}

QUERY_THREAD *
call_wf_radar_get_query(const FLAME_SWITCH * sw)
{
XL_SEXP * _ret;
QUERY_THREAD * ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return rc_get_q_thread((RADAR_CACHE*)sw->gf->radar_ptr);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_radar_get_query");
	}

	gc_push(0,0,"call_wf_radar_get_query");
	_ret = view_agent_session(sw,l_string(std_cm,"gv-flame-radar-get-query"),
		List(n_get_symbol_with_fid(sw,"gv-flame-radar-get-query"),-1));
	ret = sexp_to_q_thread(_ret);
	gc_pop(0,0);
	return ret;
}


int
call_wf_radar_set_query(const FLAME_SWITCH * sw,QUERY_THREAD * query)
{
int _ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return rc_set_q_thread((RADAR_CACHE*)sw->gf->radar_ptr,
				query);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_radar_set_query");
	}

	gc_push(0,0,"call_wf_radar_set_query");
	XL_SEXP *ret = view_agent_session(sw,l_string(std_cm,"gv-flame-radar-set-query"),
		List(n_get_symbol_with_fid(sw,"gv-flame-radar-set-query"),
			List(n_get_symbol("quote"), 
				q_thread_to_sexp(query,QTH_MAXIMUM_INFO), -1),-1));
	if ( get_type(ret) != XLT_INTEGER )
		_ret = -1;
	else	_ret = ret->integer.data;
	gc_pop(0,0);
	return _ret;
}

int
call_wf_radar_replace_query(const FLAME_SWITCH * sw,QUERY_THREAD * query)
{
int _ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return rc_replace_q_thread((RADAR_CACHE*)sw->gf->radar_ptr,
				query);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_radar_replace_query");
	}

	gc_push(0,0,"call_wf_radar_replace_query");
	XL_SEXP *ret = view_agent_session(sw,l_string(std_cm,"gv-flame-radar-replace-query"),
		List(n_get_symbol_with_fid(sw,"gv-flame-radar-replace-query"),
			List(n_get_symbol("quote"), 
				q_thread_to_sexp(query,QTH_MAXIMUM_INFO), -1),-1));
	if ( get_type(ret) != XLT_INTEGER )
		_ret = -1;
	else	_ret = ret->integer.data;
	gc_pop(0,0);
	return _ret;
}

int
call_wf_radar_insert_query(const FLAME_SWITCH * sw,QUERY_THREAD * query)
{
int _ret;
QUERY_THREAD * qth;
XL_SEXP * q;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return rc_insert_q_thread((RADAR_CACHE*)sw->gf->radar_ptr,
				query);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_radar_insert_query");
	}

	gc_push(0,0,"call_wf_radar_set_query");
	XL_SEXP *ret = view_agent_session(sw,l_string(std_cm,"gv-flame-radar-insert-query"),
		List(n_get_symbol_with_fid(sw,"gv-flame-radar-insert-query"),
			List(n_get_symbol("quote"), 
				q_thread_to_sexp(query,QTH_MAXIMUM_INFO),-1),-1));
	if ( get_type(ret) != XLT_PAIR )
		goto err;
	q = car(ret);
	if ( get_type(q) != XLT_INTEGER )
		goto err;
	_ret = q->integer.data;
	if ( _ret < 0 )
		goto err;
	ret = cdr(ret);
	qth = query;
	for ( ; get_type(ret) == XLT_PAIR && qth ; 
	      		ret = cdr(ret), qth = qth->next ) {
		q = car(ret);
		if ( get_type(q) != XLT_INTEGER )
			continue;
		qth->id = q->integer.data;
	}
	gc_pop(0,0);
	return _ret;
err:
	gc_pop(0,0);
	return -1;
}


int
call_wf_radar_delete_query(const FLAME_SWITCH * sw,int no)
{
int _ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		return rc_delete_q_thread((RADAR_CACHE*)sw->gf->radar_ptr,
				no);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_radar_delete_query");
	}

	gc_push(0,0,"call_wf_radar_delete_query");
	XL_SEXP *ret = view_agent_session(sw,l_string(std_cm,"gv-flame-radar-delete-query"),
		List(n_get_symbol_with_fid(sw,"gv-flame-radar-delete-query"),get_integer(no,0),-1));
	if ( get_type(ret) != XLT_INTEGER )
		_ret = -1;
	else	_ret = ret->integer.data;
	gc_pop(0,0);
	return _ret;
}


int
call_wf_radar_set_indicate_event(FLAME_SWITCH * sw,
	void (*func)(RADAR_INDICATE*,void*),
	void * work)
{
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		rc_set_indicate_event(
			(RADAR_CACHE*)sw->gf->radar_ptr,
			func,work);
		return 0;
	case SW_MODE_REMOTE:
		sw->sw_ri_event_func = func;
		sw->sw_ri_event_user_arg = work;
		break;
	default:
		er_panic("call_wf_radar_set_indicate_event");
	}
	return 0;
}

int
call_wf_radar_set_condition_event(FLAME_SWITCH * sw,
	void (*func)(QUERY_THREAD*,void*),
	void * work)
{
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return 0;
	case SW_MODE_LOCAL:
		rc_set_condition_event(
			(RADAR_CACHE*)sw->gf->radar_ptr,
			func,work);
		return 0;
	case SW_MODE_REMOTE:
		sw->sw_rc_event_func = func;
		sw->sw_rc_event_user_arg = work;
		break;
	default:
		er_panic("call_wf_radar_set_indicate_event");
	}
	return 0;
}



XL_SEXP *
xl_win_flame_indicate_event(
	XLISP_ENV * e,
	XL_SEXP * s,
	XLISP_ENV * a,
	XL_SYM_FIELD * sf)
{
int i;
XL_SEXP *arg, *w1, *w2, *w3, *t;
L_CHAR *id;
FLAME_SWITCH *sw;
RADAR_INDICATE ri;

print_sexp(s_stdout,s,PF_RAW_DISABLE);
s_printf(s_stdout,"\n");

	id = get_sf_attribute(sf,l_string(std_cm,"flame-id"));
	if ( id == 0 )
		sw = search_sw_id(1);
	else	sw = search_sw_id(atoi(n_string(std_cm,id)));
	if ( sw == 0 )
		er_panic("xl_win_flame_indicate_event : invalid flame-id");

	arg = get_el(s,1);
	if ( get_type(arg) != XLT_PAIR )
		goto type_missmatch;
	w1 = get_el(arg,0);
	w2 = get_el(arg,1);
	w3 = get_el(arg,2);
	if ( get_type(w1) != XLT_INTEGER )
		goto type_missmatch;
	
	ri.d.beam = w1->integer.data;
	
	for ( i = 0 ; i <= CRT_MAX ; i++ ) {
		if ( get_type(w2) != XLT_PAIR )
			goto type_missmatch;
		t = car(w2);
		if ( get_type(t) != XLT_INTEGER )
			goto type_missmatch;
		ri.d.loading_res[i] = t->integer.data;
		w2 = cdr(w2);
	}

	for ( i = 0 ; i <= CRT_MAX ; i++ ) {
		if ( get_type(w3) != XLT_PAIR )
			goto type_missmatch;
		t = car(w3);
		if ( get_type(t) != XLT_INTEGER )
			goto type_missmatch;
		ri.d.ready_res[i] = t->integer.data;
		w3 = cdr(w3);
	}
	
	if ( sw->sw_ri_event_func )
		(*sw->sw_ri_event_func)(&ri, sw->sw_ri_event_user_arg);
	
	return 0;
	
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"win-flame-indicate-event"),
		List(n_get_string("type missmatch"),
			-1));
}


int
call_wf_radar_warp(FLAME_SWITCH * sw,
	int type,
	GB_RECT * rect,
	GB_POINT * center,
	REAL1 resolution,
	REAL1 rotate,
	L_CHAR * target)
{
int _ret;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return -1;
	case SW_MODE_LOCAL:
		return rc_warp(
			(RADAR_CACHE*)sw->gf->radar_ptr,
			type,rect,center,resolution,rotate,target);
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_warp");
	}
	
	gc_push(0,0,"call_wf_radar_set_query");
	XL_SEXP *ret = view_agent_session(sw,l_string(std_cm,"gv-flame-radar-warp"),
		List(n_get_symbol_with_fid(sw,"gv-flame-radar-warp"),
			get_integer(type, 0),
			rect ? gb_rect_to_xl(rect) : 0,
			center ? gb_point_to_xl(center) : 0,
			get_floating(resolution, 0),
			get_floating(rotate, 0),
			get_string(target),
			-1));
	if ( get_type(ret) != XLT_INTEGER )
		_ret = -1;
	else	_ret = ret->integer.data;
	gc_pop(0,0);
	return _ret;
}

int
list2loading_status(LOADING_STATUS * ls,XL_SEXP * lst)
{
XL_SEXP * rc,* wf;
XL_SEXP * d,* _d;
int i;
	rc = get_el_by_symbol(lst,l_string(std_cm,"rc"),0);
	if ( rc ) {
		d = get_el_by_symbol(rc,l_string(std_cm,"status"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.status = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"search-loading"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.search_loading = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"layer-management"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.layer_management = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"change-base-coord"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.change_base_coord = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"beam"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.ri.d.beam = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"loading-res"),0);
		if ( d ) {
			for ( i = 0 ; i < CRT_MAX+1 ; i ++ ) {
				_d = get_el(d,i+1);
				if ( get_type(_d) != XLT_INTEGER )
					goto err;
				ls->rc.ri.d.loading_res[i] = _d->integer.data;
			}
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"ready_res"),0);
		if ( d ) {
			for ( i = 0 ; i < CRT_MAX+1 ; i ++ ) {
				_d = get_el(d,i+1);
				if ( get_type(_d) != XLT_INTEGER )
					goto err;
				ls->rc.ri.d.ready_res[i] = _d->integer.data;
			}
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"load-to-beam"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.ri.d.load_to_beam = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"beam-to-resource"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.ri.d.beam_to_resource = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"retrieve1"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.ri.d.retrieve1 = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"retrieve2"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->rc.ri.d.retrieve2 = _d->integer.data;
		}
	}
	wf = get_el_by_symbol(lst,l_string(std_cm,"wf"),0);
	if ( wf ) {
		d = get_el_by_symbol(rc,l_string(std_cm,"draw"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->wf.draw = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"exit"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->wf.exit = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"load-structure"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->wf.load_structure = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"dirty"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->wf.dirty = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"data-request"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->wf.data_request = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"indicate-request"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->wf.indicate_request = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"indicate"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->wf.indicate = _d->integer.data;
		}
		d = get_el_by_symbol(rc,l_string(std_cm,"raw-image-request"),0);
		if ( d ) {
			_d = get_el(d,1);
			if ( get_type(_d) != XLT_INTEGER )
				goto err;
			ls->wf.raw_image_request = _d->integer.data;
		}
	}
	return 0;
err:
	return -1;
}

int call_wf_loading_status(const FLAME_SWITCH * sw,LOADING_STATUS * ls)
{
int ret;
GBVIEW_STATUS sts;
	switch ( sw->mode ) {
	case SW_MODE_IDLE:
		return -1;
	case SW_MODE_LOCAL:
		ret = get_rc_loading_status(
			(RADAR_CACHE*)sw->gf->radar_ptr,&ls->rc);
		if ( ret < 0 )
			return ret;
		wf_status(sw->gf,&sts);
		ls->wf = sts.loading_status;
		wf_free_status(&sts);
		return 0;
	case SW_MODE_REMOTE:
		break;
	default:
		er_panic("call_wf_warp");
	}
	gc_push(0,0,"call_wf_radar_set_query");
	XL_SEXP *_ret = view_agent_session(sw,l_string(std_cm,"gv-flame-loading-status"),
		List(n_get_symbol_with_fid(sw,"gv-flame-loading-status"),
			-1));
	if ( get_type(_ret) == XLT_ERROR ) {
		ret = -1;
		goto end;
	}
	list2loading_status(ls,_ret);
	ret = 0;
end:
	gc_pop(0,0);
	return ret;
}


