/**********************************************************************
 
	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	<stdlib.h>
#include	<string.h>
#include	"u_math.h"
#include	"memory_debug.h"
#include	"gbparam.h"
#include	"utils.h"
#include	"win_flame.h"
#include	"memory_routine.h"
#include	"xlerror.h"
#include	"lock_level.h"
#include	"pri_level.h"
#include	"xl.h"



typedef struct _bw_map {
	RESOURCE *		r;
	BROWSE_WORK *		bw;
	int			cnt;
	int			end;
} BW_MAP;

#define BW_MAP_TASKS		4

SEM bw_lock;
BW_MAP bw_map;

extern SEM res_lock;

#define BWT_ROUTE	3

void browse_children_map_task();

XL_SEXP * gv_set_status_coordinate_gbview();


void
init_coordinate_browse()
{
int i;
XLISP_ENV * e;
extern XLISP_ENV * gv_resource_env[];
	bw_lock = new_lock(LL_BW);
	/*
	for ( i = 0 ; i < BW_MAP_TASKS ; i ++ )
		create_task(browse_children_map_task,0,PRI_FETCH);
	*/

	e = gv_resource_env[RT_COORDINATE];
	if ( e == 0 )
		er_panic("init_coordinate_browse");
	set_env(e,l_string(std_cm,"gv-set-status"),
			get_func_prim(gv_set_status_coordinate_gbview,
			FO_APPLICATIVE,0,1,-1));
}

void
load_coordinate_option()
{
	assert_ls_all(LSF_ASSERT);
}

void
in_memcpy(void * a,void * b,int size)
{
char * aa,* bb;
int s;
printf("in_memcpy size = %i %i %i\n",size,a,b);
	aa = a;
	bb = b;
	for ( s = 0 ; s < size ; s ++ ) {
		if ( s == 4093 )
			printf("bbbbbb\n");
		*aa++ = *bb++;
	}
}


void
setup_minrect(MAP * m)
{
GB_RECT r;
GB_POINT p;
GB_RECT *mr;
REAL1 reso;
	if ( m->map_file->h.minrect.tl.x <=
		m->map_file->h.minrect.br.x )
		return;
	if ( m->src == 0 )
		return;
	mr = &m->src->h.minrect;
	p = mr->tl;
	reso = 1;
	map_conv_forward(m->map_file,&p,&reso,1);
	if ( reso < 0 )
		return;
	r.tl = r.br = p;

	p = mr->br;
	reso = 1;
	map_conv_forward(m->map_file,&p,&reso,1);
	if ( reso < 0 )
		return;
	insert_rect(&r,p);

	p.x = mr->tl.x;
	p.y = mr->br.y;
	reso = 1;
	map_conv_forward(m->map_file,&p,&reso,1);
	if ( reso < 0 )
		return;
	insert_rect(&r,p);

	p.x = mr->br.x;
	p.y = mr->tl.y;
	reso = 1;
	map_conv_forward(m->map_file,&p,&reso,1);
	if ( reso < 0 )
		return;
	insert_rect(&r,p);


	m->map_file->h.minrect = r;
}

int
browse_children(RESOURCE * r,BROWSE_WORK * bw,int * hit_route)
{
MAP * m;
BROWSE_WORK bw1;
int ret,this_coord;
MAP_HISTORY * mh;
GB_RECT * g;
int g_len,i;

	ret = 0;
	this_coord = 0;

	*hit_route = 0;
	for ( m = R_NEXT(MAP*,&r->c.map_children);
			m != (MAP*)&r->c.map_children;
			m = R_NEXT(MAP*,&m->h) ) {
		if ( bw->type == BWT_ROUTE ) {
		int len;
			len = l_strlen(m->src_url.resource);
			if ( l_strcmp(&m->src_url.resource[len-4],
					l_string(std_cm,".crd")) )
				continue;
			if ( url_cmp_str(&m->map_url,&bw->route[0]) )
				continue;
			if ( url_cmp_str(&m->src_url,&bw->route[1]) )
				continue;
			*hit_route = 1;
		}
		else {
		int len;
			len = l_strlen(m->src_url.resource);
			if ( l_strcmp(&m->src_url.resource[len-4],
					l_string(std_cm,".crd")) == 0 )
				continue;
		}
		lock_task(res_lock);
		if ( m->flags & MF_BROWSE ) {
			unlock_task(res_lock,"write_lock");
			continue;
		}
		m->flags |= MF_BROWSE;
		unlock_task(res_lock,"write_lock");
		if ( m->map_file == 0 ) {
			m->map_file
			  = load_resource(bw->ses,&m->map_url,Q_PRI_OBJ);
			if ( m->map_file == 0 )
				goto err;
			if ( url_cmp_str(&m->map_file->map.dest,
					&r->h.entry) )
				goto err;
			ret = 1;
			this_coord = 1;
		}
		setup_minrect(m);
		if ( bw->type != BWT_ROUTE || bw->rr->check ||
				bw->route_len == 2 ) {
			g = get_surp_rect(&g_len,&bw->surp,r);
			if  ( check_nan_rect(&m->map_file->h.minrect) == 0 ) {
				for ( i = 0 ; i < g_len ; i ++ ) {
					if ( cross_rect_rect(
							&m->map_file->h.minrect,&g[i])
							== 0 )
						continue;
					goto g_ok;
				}

				lock_task(res_lock);
				m->flags &= ~MF_BROWSE;
				unlock_task(res_lock,"write_lock");

				if ( bw->route_len == 2 )
					bw->rr->last_check = -1;
				if ( bw->type != BWT_ROUTE || bw->rr->check ) {
					if ( g )
						d_f_ree(g);
					continue;
				}
			g_ok:	;
			}
			if ( g )
				d_f_ree(g);
		}
		if ( m->src == 0 ) {
			m->src = load_resource(bw->ses,&m->src_url,Q_PRI_OBJ);
			if ( m->src == 0 )
				goto err;
			ret = 1;
			this_coord = 1;
		}
		bw1 = *bw;
		map_conv_reverse(m->map_file,
			bw1.surp.ptr,bw1.surp.reso,SURP_NOS);
		lock_task(res_lock);
		m->flags &= ~MF_BROWSE;
		unlock_task(res_lock,"write_lock");
		if ( bw->type != BWT_ROUTE || bw->rr->check ||
				bw->route_len == 2 ) {
		GB_RECT *sr;
		int sr_len;
			sr = get_surp_rect(&sr_len,&bw1.surp,r);
			if  ( check_nan_rect(&m->src->h.minrect) == 0 ) {
				for ( i = 0 ; i < sr_len ; i ++ ) {
					if ( cross_rect_rect(
						&m->src->h.minrect,&sr[i]) == 0 )
						continue;
					goto sr_ok;
				}
				if ( bw->route_len == 2 )
					bw->rr->last_check = -1;
				if ( bw->type != BWT_ROUTE || 
					bw->rr->check ) {
					if ( sr )
						d_f_ree(sr);
					continue;
				}
			sr_ok:	;
			}
			if ( sr )
				d_f_ree(sr);
		}
		bw1.mh = add_mh(bw->mh,mh = new_mh(m->map_file,MHD_REVERSE));
		free_mh(mh);
		if ( bw->route_len == 2 && bw->rr->last_check == 0 )
			bw->rr->last_check = 1;
		if ( bw1.type == BWT_ROUTE ) {
			bw1.route = &bw1.route[2];
			bw1.route_len -= 2;
		}
		if ( browse_resource(m->src,&bw1) )
			ret = 1;
		free_mh(bw1.mh);
		if ( bw->type == BWT_ROUTE ) {
			*hit_route = 2;
			break;
		}
		continue;
	err:
		lock_task(res_lock);
		DELETE_RING(&m->h);
		unlock_task(res_lock,"write_lock");
		free_url(&m->map_url);
		free_url(&m->src_url);
		free_url(&m->dest_url);
		d_f_ree(m);
	}
	if ( this_coord ) {
	WF_ID wfid;
	GBVIEW_FLAME * gf;
		gf = wf_search(&wfid,r);
		if ( wfid )
			win_flame_dirty(gf,wfid,0,
				WFF_DIRTY,
				0);
	}
	return ret;
}

LOAD_RESOURCE_WORK *
load_children_map(RESOURCE * r,BROWSE_WORK * bw)
{
MAP * m;
LOAD_RESOURCE_WORK * ret;
int len;
GB_RECT *g;
int g_len;
int i;

int cnt;
cnt = 0;

	if ( r->h.flags & (RF_LOAD_EXTEND|RF_LOAD_EXTEND_PROC) == 0 )
		lr_extend(r,0);
	for ( ; (r->h.flags & RF_LOAD_EXTEND) == 0 ; )
		sleep_sec(1);
	ret = 0;
	for ( m = R_NEXT(MAP*,&r->c.map_children);
			m != (MAP*)&r->c.map_children &&
			bw->load_max > 0 ; 
			m = R_NEXT(MAP*,&m->h) ) {
cnt ++;
		len = l_strlen(m->src_url.resource);
		if ( l_strcmp(&m->src_url.resource[len-4],
				l_string(std_cm,".crd")) == 0 )
			continue;

		g = get_surp_rect(&g_len,&bw->surp,r);
/*
if ( l_strcmp(r->h.entry.resource,l_string(std_cm,"05.crd")) == 0 )
ss_printf("***************************\n");
ss_printf("CC / %ls\n",get_url_str2(&r->h.entry));
ss_printf("CC-- %i %i ++ %i\n",m->cindex_time,m->mod_time,
m->cindex_time - m->mod_time);
*/
/*
		if ( m->cindex_time >= m->mod_time &&
				m->cindex_mr.tl.x <= m->cindex_mr.br.x ) {
			if ( cross_rect_rect(&m->cindex_mr,&g) == 0 ) {
				lock_task(res_lock);
				m->flags &= ~MF_BROWSE;
				unlock_task(res_lock,"write_lock");
				continue;
			}
		}
*/
		if ( m->cindex_mr.tl.x <= m->cindex_mr.br.x ) {
			for ( i = 0 ; i < g_len ; i ++ ){
				if ( cross_rect_rect(&m->cindex_mr,&g[i]) )
					goto cross_next;
			}
			lock_task(res_lock);
			m->flags &= ~MF_BROWSE;
			unlock_task(res_lock,"write_lock");
			if ( g )
				d_f_ree(g);
			continue;
		cross_next:	;
		}

		if ( m->src == 0 ) {
			ret = new_lrw(ret);
			copy_url(&ret->url,&m->src_url);
			bw->load_max --;
		}


		if ( m->map_file == 0 ) {
			ret = new_lrw(ret);
			copy_url(&ret->url,&m->map_url);
			bw->load_max --;
		}

		if ( g )
			d_f_ree(g);

	}

	return ret;
}

int
browse_children_map(int ses,RESOURCE * r,BROWSE_WORK * bw,
	LOAD_RESOURCE_WORK * w)
{
MAP * m;
BROWSE_WORK bw1;
int ret,this_coord;
MAP_HISTORY * mh;
GB_RECT * g;
int g_len;
int i;
int len;
LOAD_RESOURCE_WORK * wp;

	ret = 0;
	wp = w;
	this_coord = 0;
	for ( m = R_NEXT(MAP*,&r->c.map_children);
			m != (MAP*)&r->c.map_children;
			m = R_NEXT(MAP*,&m->h) ) {

		len = l_strlen(m->src_url.resource);
		if ( l_strcmp(&m->src_url.resource[len-4],
				l_string(std_cm,".crd")) == 0 )
			continue;

		lock_task(res_lock);
		if ( m->flags & MF_BROWSE ) {
			unlock_task(res_lock,"write_lock");
			continue;
		}
		m->flags |= MF_BROWSE;
		unlock_task(res_lock,"write_lock");

		if ( m->map_file == 0 ) {
			m->map_file
				= get_lrw(w,&m->map_url);
			if ( m->map_file == 0 )
				goto err;
			if ( url_cmp_str(&m->map_file->map.dest,
					&r->h.entry) ) {
				m->map_file = 0;
				goto err;
			}
			if ( url_cmp_str(&m->map_file->map.src,
					&m->src_url) ) {
				m->map_file = 0;
				goto err;
			}
			ret = 1;
			this_coord = 1;
		}

/***/
		g = get_surp_rect(&g_len,&bw->surp,r);
		if  ( check_nan_rect(&m->map_file->h.minrect) == 0 ) {
			for ( i = 0 ; i < g_len ; i ++ ) {
				if ( cross_rect_rect(
					&m->map_file->h.minrect,&g[i]) == 0 )
					continue;
				goto c_next;
			}
			lock_task(res_lock);
			m->flags &= ~MF_BROWSE;
			unlock_task(res_lock,"write_lock");
				if ( bw->route_len == 2 )
				bw->rr->last_check = -1;
			if ( bw->type != BWT_ROUTE || bw->rr->check ) {
				if ( g )
					d_f_ree(g);
				continue;
			}
		c_next:	;
		}
		if ( g )
			d_f_ree(g);
		if ( m->src == 0 ) {
			m->src = get_lrw(w,&m->src_url);

			if ( m->src == 0 )
				goto err;
			ret = 1;
			this_coord = 1;
			if ( m->src->h.notes )
				call_gv_event(m->src->h.no,
					l_string(std_cm,"set-note"));
		}


		setup_minrect(m);

		bw1 = *bw;
		map_conv_reverse(m->map_file,
			bw1.surp.ptr,bw1.surp.reso,SURP_NOS);

		lock_task(res_lock);
		m->flags &= ~MF_BROWSE;
		unlock_task(res_lock,"write_lock");
		bw1.mh = add_mh(bw->mh,mh = new_mh(m->map_file,MHD_REVERSE));
		free_mh(mh);
/*
		if ( browse_resource(m->src,&bw1) )
			ret = 1;
*/
		free_mh(bw1.mh);
	err:
		lock_task(res_lock);
		m->flags &= ~MF_BROWSE;
		unlock_task(res_lock,"write_lock");


	}
	if ( this_coord ) {
	WF_ID wfid;
	GBVIEW_FLAME * gf;
		gf = wf_search(&wfid,r);
		if ( wfid )
			win_flame_dirty(gf,wfid,0,
				WFF_DIRTY,
				0);
	}
	return ret;
}

void
browse_children_map_task()
{
XL_INTERPRETER * xli;
int ses;

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


	ses = open_session(SEST_DIRECT);

	for ( ; ; ) {
		lock_task(bw_lock);
		for ( ; bw_map.cnt == 0 ; ) {
			sleep_task((int)&bw_map,bw_lock);
			lock_task(bw_lock);
		}
		bw_map.cnt --;
		unlock_task(bw_lock,"browse_children");
		gc_push(0,0,"browse");
		browse_children_map(ses,bw_map.r,bw_map.bw,0);
		gc_pop(0,0);
		lock_task(bw_lock);
		bw_map.end ++;
		if ( bw_map.end == BW_MAP_TASKS )
			wakeup_task((int)&bw_map.bw);
		unlock_task(bw_lock,"browse_children");
	}
}


int
browse_children_obj(RESOURCE * r,BROWSE_WORK * bw)
{
MAP * m;
BROWSE_WORK bw1;
int ret,this_coord;
MAP_HISTORY * mh;
GB_RECT * g;
int g_len;
int i;
	ret = 0;
	this_coord = 0;

	for ( m = R_NEXT(MAP*,&r->c.map_children);
			m != (MAP*)&r->c.map_children;
			m = R_NEXT(MAP*,&m->h) ) {
		{
		int len;
			len = l_strlen(m->src_url.resource);
			if ( l_strcmp(&m->src_url.resource[len-4],
					l_string(std_cm,".crd")) == 0 )
				continue;
		}
		lock_task(res_lock);
		if ( m->flags & MF_BROWSE ) {
			unlock_task(res_lock,"browse_children_obj");
			continue;
		}
		m->flags |= MF_BROWSE;
		unlock_task(res_lock,"browse_children_obj");
		if ( m->map_file == 0 ) {
			continue;
		}
		g = get_surp_rect(&g_len,&bw->surp,r);
		if  ( check_nan_rect(&m->map_file->h.minrect) == 0 ) {
			for ( i = 0 ; i < g_len ; i ++ ) {
				if ( cross_rect_rect(
					&m->map_file->h.minrect,&g[i]) == 0 )
					continue;
				goto cc_next;
			}
			lock_task(res_lock);
			m->flags &= ~MF_BROWSE;
			unlock_task(res_lock,"browse_children_obj");
				if ( bw->route_len == 2 )
				bw->rr->last_check = -1;
			if ( bw->type != BWT_ROUTE || bw->rr->check ) {
				if ( g )
					d_f_ree(g);
				continue;
			}
		cc_next:;
		}
		if ( g )
			d_f_ree(g);

		if ( m->src == 0 ) {
			m->src = load_resource(bw->ses,&m->src_url,Q_PRI_OBJ);
			if ( m->src == 0 )
				goto err;
			ret = 1;
			this_coord = 1;
		}
		bw1 = *bw;
		map_conv_reverse(m->map_file,
			bw1.surp.ptr,bw1.surp.reso,SURP_NOS);
		lock_task(res_lock);
		m->flags &= ~MF_BROWSE;
		unlock_task(res_lock,"obj");
		bw1.mh = add_mh(bw->mh,mh = new_mh(m->map_file,MHD_REVERSE));
		free_mh(mh);
		if ( browse_resource(m->src,&bw1) )
			ret = 1;
		free_mh(bw1.mh);
		continue;
	err:
		lock_task(res_lock);
		DELETE_RING(&m->h);
		unlock_task(res_lock,"obj");
		free_url(&m->map_url);
		free_url(&m->src_url);
		free_url(&m->dest_url);
		d_f_ree(m);
	}
	if ( this_coord ) {
	WF_ID wfid;
	GBVIEW_FLAME * gf;
		gf = wf_search(&wfid,r);
		if ( wfid ) {
			win_flame_dirty(gf,wfid,0,
				WFF_DIRTY,
				0);
		}
	}
	return ret;
}


int
browse_parents(RESOURCE * r,BROWSE_WORK * bw,int *hit_route)
{
int ret;
BROWSE_WORK bw1;
MAP * m;
MAP_HISTORY * mh;

	ret = 0;
	*hit_route = 0;
	for ( m = R_NEXT(MAP*,&r->c.map_parents);
			m != (MAP*)&r->c.map_parents;
			m = R_NEXT(MAP*,&m->h) ) {
		if ( bw->type == BWT_ROUTE ) {
		int len;
			len = l_strlen(m->dest_url.resource);
			if ( l_strcmp(&m->dest_url.resource[len-4],
					l_string(std_cm,".crd")) )
				continue;
			if ( url_cmp_str(&m->map_url,&bw->route[0]) )
				continue;
			if ( url_cmp_str(&m->dest_url,&bw->route[1]) )
				continue;
			*hit_route = 1;
		}
		else {
		int len;
			len = l_strlen(m->dest_url.resource);
			if ( l_strcmp(&m->dest_url.resource[len-4],
					l_string(std_cm,".crd")) == 0 )
				continue;
		}
		lock_task(res_lock);
		if ( m->flags & MF_BROWSE ) {
			unlock_task(res_lock,"write_lock");
			continue;
		}
		m->flags |= MF_BROWSE;
		unlock_task(res_lock,"write_lock");
		if ( m->map_file == 0 ) {
			m->map_file
			  = load_resource(bw->ses,&m->map_url,Q_PRI_OBJ);
			if ( m->map_file == 0 )
				goto err;
			ret = 1;
		}
		if ( m->dest == 0 ) {
			m->dest = load_resource(bw->ses,&m->dest_url,Q_PRI_OBJ);
			if ( m->dest == 0 )
				goto err;
			ret = 1;
		}
		bw1 = *bw;
		map_conv_forward(m->map_file,
			bw1.surp.ptr,bw1.surp.reso,SURP_NOS);
		if ( bw->type != BWT_ROUTE || bw->rr->check ||
				bw->route_len == 2) {
		GB_RECT	* sr;
		int sr_len;
		int i;
			sr = get_surp_rect(&sr_len,&bw1.surp,m->dest);
			if ( check_nan_rect(&m->dest->h.minrect) == 0 ) {
				for ( i = 0 ; i < sr_len ; i ++ ) {
					if ( cross_rect_rect(
						&m->dest->h.minrect,&sr[i]) == 0 )
						continue;
					goto sr_ok;
				}
				if ( bw->route_len == 2 )
					bw->rr->last_check = -1;
				if ( bw->type != BWT_ROUTE || bw->rr->check ) {
					if ( sr )
						d_f_ree(sr);
					continue;
				}
			sr_ok:	;
			}
			if ( sr )
				d_f_ree(sr);
		}
		lock_task(res_lock);
		m->flags &= ~MF_BROWSE;
		unlock_task(res_lock,"write_lock");
		bw1.mh = add_mh(bw->mh,mh = new_mh(m->map_file,MHD_FORWARD));
		free_mh(mh);
		if ( bw->route_len == 2 && bw->rr->last_check == 0 )
			bw->rr->last_check = 1;
		if ( bw1.type == BWT_ROUTE ) {
			bw1.route = &bw1.route[2];
			bw1.route_len -= 2;
		}
		if ( browse_resource(m->dest,&bw1) )
			ret = 1;
		free_mh(bw1.mh);
		if ( bw->type == BWT_ROUTE ) {
			*hit_route = 2;
			break;
		}
		continue;
	err:
		lock_task(res_lock);
		DELETE_RING(&m->h);
/***/
		unlock_task(res_lock,"write_lock");
		free_url(&m->map_url);
		free_url(&m->src_url);
		free_url(&m->dest_url);
		d_f_ree(m);
	}
	return ret;
}

int
browse_coord_route(RESOURCE * r,BROWSE_WORK * bw)
{
int hit;
int ret;
	if ( bw->route_len == 0 ) {
		bw->rr->mh = copy_mh(bw->mh);
		bw->rr->route_len = 0;
		return 0;
	}
	ret = browse_children(r,bw,&hit);
	switch ( hit ) {
	case 0:
		break;
	case 1:
		bw->rr->route_len = bw->route_len;
		return -1;
	case 2:
		return ret;
	}
	ret = browse_parents(r,bw,&hit);
	switch ( hit ) {
	case 0:
	case 1:
		bw->rr->route_len = bw->route_len;
		return -1;
	case 2:
		return ret;
	}
	er_panic("browse_coor_route");
	return 0;
}

XL_SEXP *
gv_set_status_coordinate_gbview(XLISP_ENV * e,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
RESOURCE * r;
XL_SEXP * ret, * obj;
char * e_param;
L_CHAR * pointer;
XL_SEXP * gv_set_status_coordinate();



	r = get_resource_ptr(&ret,e,s->h.file,s->h.line);
	if ( r == 0 )
		return ret;
	pointer = get_sf_attribute(sf,l_string(std_cm,"pointer"));
	if ( pointer == 0 )
		goto end;
	e_param = "pointer";
	if ( l_strcmp(pointer,l_string(std_cm,"on")) == 0 )
		set_pointer_indicate(wf_next_gf(0,GVFM_LIVE),IF_COORDINATE,&r->h.entry);
	else if ( l_strcmp(pointer,l_string(std_cm,"off")) == 0 )
		set_pointer_indicate(wf_next_gf(0,GVFM_LIVE),0,&r->h.entry);
	else	goto invalid_param;
end:

	return gv_set_status_coordinate(e,s,a,sf);
invalid_param:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"gv-set-status"),
		List(n_get_string("invalid parameter"),
			n_get_string(e_param),
			-1));
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"gv-set-status"),
		List(n_get_string("type missmatch"),
			-1));
}

void
do_initial(RESOURCE * r)
{
XL_SEXP * s;
XLISP_ENV * env;
XL_SEXP * ret;
extern XLISP_ENV * gv_resource_env[];

	gc_push(0,0,"do_initial");
	env = new_env(
		new_env_pair(gv_resource_env[r->h.type],
			gblisp_top_env0));
	set_env(env,l_string(std_cm,"__resource"),
		get_ptr(r,0));
	for ( s = r->c.initial_cmd ; get_type(s) == XLT_PAIR ; s = cdr(s) ) {
		ret = eval(env,car(s));
		if ( get_type(ret) == XLT_ERROR ) {
			print_sexp(s_stdout,ret,0);
			ss_printf("\n");
		}
	}
	gc_pop(0,0);
}


int
do_button_action(RESOURCE * r,char * type,L_CHAR * name)
{
XL_SEXP * s, * case_list;
XLISP_ENV * env;
XL_SEXP * ret, * sym;
L_CHAR * _action,* _target, * _mode;
extern XLISP_ENV * gv_resource_env[];
char * e_param;

	gc_push(0,0,"do_initial");
	env = new_env(
		new_env_pair(gv_resource_env[r->h.type],
			gblisp_top_env0));
	set_env(env,l_string(std_cm,"__resource"),
		get_ptr(r,0));
	case_list = 0;
	for ( s = r->c.button_action ; get_type(s) == XLT_PAIR ; s = cdr(s) ) {
		case_list = car(s);
		if ( get_type(case_list) != XLT_PAIR ) {
			e_param = "not list element";
			goto err;
		}
		sym = car(case_list);
		if ( get_type(sym) != XLT_SYMBOL ) {
			e_param = "not symbol tag";
			goto err;
		}
		if ( l_strcmp(sym->symbol.data,l_string(std_cm,"case")) ) {
			e_param = "not case tag";
			goto err;
		}
		_action = get_sf_attribute(sym->symbol.field,
				l_string(std_cm,"action"));
		if ( _action == 0 ) {
			e_param = "undefine action";
			goto err;
		}
		_mode = get_sf_attribute(sym->symbol.field,
				l_string(std_cm,"mode"));
		if ( _action == 0 ) {
			e_param = "undefine mode";
			goto err;
		}
		_target = get_sf_attribute(sym->symbol.field,
				l_string(std_cm,"target"));
		if ( _action == 0 ) {
			e_param = "undefine target";
			goto err;
		}
		if ( l_strcmp(_action,l_string(std_cm,type)) )
			continue;
		if ( l_strcmp(_target,name) )
			continue;
		break;
	err:
		ss_printf("invalid case statement in button_action (%s)\n",
			e_param);
		print_sexp(s_stdout,r->c.button_action,0);
		ss_printf("\n");
	}
	if ( get_type(s) != XLT_PAIR ) {
		gc_pop(0,0);
		return 0;
	}
	if ( r->c.mode )
		d_f_ree(r->c.mode);
	r->c.mode = ll_copy_str(_mode);
	for ( s = cdr(case_list) ; get_type(s) == XLT_PAIR ; s = cdr(s) ) {
		ret = eval(env,car(s));
		if ( get_type(ret) == XLT_ERROR ) {
			ss_printf("button-action error\n");
			print_sexp(s_stdout,ret,0);
			ss_printf("\n");
		}
	}
	gc_pop(0,0);
	return 1;
}

int
browse_coord(RESOURCE * r,BROWSE_WORK * bw)
{
LOAD_RESOURCE_WORK * w;
int ret;
	if ( bw->type == BWT_ROUTE ) {
		er_panic("BROWSE");
		return 0 ;
	}
	else {

		w = load_children_map(r,bw);
		load_resource_list(w,Q_PRI_OBJ,1);
		ret = browse_children_map(bw->ses,r,bw,w);
		free_lrw_req_next(w);

		if ( ret )
			do_initial(r);
		return 0;
	}
}

void
limit_reso_control(
	REAL1 * dest,
	REAL1 src)
{
#define LR_RESO 	0.99
#define LR_SRC_RESO 	2
	if ( *dest < src )
		*dest = src* LR_SRC_RESO;
	else {
		*dest = (*dest) * LR_RESO + src * (1-LR_RESO);
	}
}

void
draw_coordinate(
	GBVIEW_FLAME * gf,
	RESOURCE * r,
	DRAW_WORK * dw)
{
MAP * m1;
DRAW_WORK dw1;
int i;
GB_POINT center;
REAL1 radius;
extern int spiral_count;
GB_RECT * sr;
int sr_len;
int f;

int reso_cnt,minus_cnt,rect_cnt;
int proc;


	proc = 0;

	dw->limit_reso = 0;
	if ( dw->pt_list &&
	     (r->c.geometory_type & GT_T_MASK) == GT_T_GLOBE_SUR )
		adjust_lambda(
			r->h.cu.unit,
			r->h.minrect.tl.x,
			dw->pt_list,
			dw->pt_reso,
			0,
			dw->size);

	lock_task(res_lock);

	for ( m1 = R_NEXT(MAP*,&r->c.map_children) ; 
			m1 != (MAP*)&r->c.map_children ;
			m1 = R_NEXT(MAP*,&m1->h) ) {

		if ( m1->flags & MF_BROWSE ) {
			proc = 1;
			continue;
		}
		if ( m1->src == 0 ) {
			if ( l_strcmp(&m1->src_url.resource
					[l_strlen(m1->src_url.resource)-4],
					l_string(std_cm,".crd")) )
				proc = 2;
			continue;
		}
		if ( m1->map_file == 0 ) {
			if ( l_strcmp(&m1->src_url.resource
					[l_strlen(m1->src_url.resource)-4],
					l_string(std_cm,".crd")) )
				proc = 3;
			continue;
		}
		if ( m1->src->h.type == RT_COORDINATE )
			continue;
		proc = 4;
		if ( (m1->src->h.flags & RF_INDICATE) == RF_I_OFF )
			continue;
		setup_minrect(m1);

		sr = get_surp_rect(&sr_len,&dw->surp,r);
		if  ( check_nan_rect(&m1->map_file->h.minrect) == 0 ) {
			for ( i = 0 ; i < sr_len ; i ++ ) {
				if ( cross_rect_rect(
						&m1->map_file->h.minrect,&sr[i])
						== 0 )
					continue;
				goto sr_ok;
			} 

			if ( m1->src->h.type == RT_DRAW_GB ) {
				if ( m1->src->draw_gb.hit_outofcircle
						> spiral_count*2 ) {
					m1->src->draw_gb.hit_level
						= m1->src->draw_gb.level;
				}
				else m1->src->draw_gb.hit_outofcircle ++;
			}
			if ( sr )
				d_f_ree(sr);
			continue;
		sr_ok:	;
		}
		if ( sr )
			d_f_ree(sr);

		if ( m1->src->h.type == RT_DRAW_GB )
			m1->src->draw_gb.hit_outofcircle = 0;
		dw1.limit_reso = -1;
		switch ( m1->src->h.type ) {
		case RT_DRAW_GB:

			if ( (dw->flags & (WFF_PLOT_DIRTY|WFF_POLY_DIRTY))
					== 0 )
				break;
			dw1 = *dw;
			dw1.parent = dw;
			dw1.pt_list = 0;
			dw1.pt_reso = 0;
			dw1.map = m1;
			dw1.limit_reso = 0;
			map_conv_reverse(m1->map_file,
				dw1.surp.ptr,dw1.surp.reso,SURP_NOS);

			if ( m1->src->h.visible_resolution != 0 &&
				m1->src->h.visible_resolution >
					dw->surp.reso[4] )
				break;

			unlock_task(res_lock,"draw_coordinate");
			draw_resource(
				gf,
				m1->src,
				&dw1);
			lock_task(res_lock);
			dw->flags |= dw1.flags;
			break;
		case RT_PIXEL_MAP_R64:
			if ( (dw->flags & WFF_LUSTER_DIRTY) == 0 )
				break;
			dw1 = *dw;
			dw1.parent = dw;
			dw1.pt_list = d_alloc(sizeof(GB_POINT)*dw1.size);
			dw1.limit_reso = 0;
			memcpy(dw1.pt_list,dw->pt_list,
				dw1.size*sizeof(GB_POINT));
			dw1.pt_reso = d_alloc(sizeof(REAL1)*dw1.size);
			memcpy(dw1.pt_reso,dw->pt_reso,dw1.size*sizeof(REAL1));

reso_cnt = 0;
minus_cnt = 0;
rect_cnt = 0;


			f = 0;
			for ( i = 0 ; i < dw1.size ; i ++ ) {
				if ( dw1.pt_reso[i] < 0 )
{reso_cnt ++;
					continue;
}
				if ( inside_rect(
						&m1->map_file->h.minrect,
						dw1.pt_list[i]) == 0 ) {
					dw1.pt_reso[i] = -1;
rect_cnt ++;
					continue;
				}
				f = 1;
			}
			if ( f == 0 ) {
				d_f_ree(dw1.pt_list);
				d_f_ree(dw1.pt_reso);
				proc = 6;
				continue;
			}

			map_conv_reverse(
				m1->map_file,
				dw1.pt_list,dw1.pt_reso,dw1.size);

			if ( m1->src->h.visible_resolution != 0 &&
				m1->src->h.visible_resolution >
					dw->surp.reso[4] )
				break;

			dw1.map = m1;
			map_conv_reverse(m1->map_file,
				dw1.surp.ptr,dw1.surp.reso,SURP_NOS);
			unlock_task(res_lock,"draw_coordinate");
			draw_resource(
				gf,
				m1->src,
				&dw1);
			lock_task(res_lock);
			d_f_ree(dw1.pt_list);
			d_f_ree(dw1.pt_reso);
			dw->flags |= dw1.flags;
			break;
		default:
			er_panic("no support");
		}

		if ( dw1.limit_reso >= 0 ) {
			map_conv_forward(m1->map_file,
				&dw1.limit_ptr,
				&dw1.limit_reso,1);
			if ( dw1.limit_reso >= 0 ) {
				if ( dw->limit_reso == 0 ||
					dw->limit_reso < dw1.limit_reso )
				dw->limit_reso = dw1.limit_reso;
			}
		}
	}
	if ( proc == 0 && dw->limit_reso == 0 )
			dw->limit_reso = r->h.visible_resolution*2;
	if ( r->c.flags & CF_FIX_LIMIT_RESO ) {
		if ( dw->limit_reso &&
				r->c.limit_resolution > dw->limit_reso )
			limit_reso_control(
				&r->c.limit_resolution,
				dw->limit_reso);
	}
	else if ( dw->limit_reso )
		limit_reso_control(
				&r->c.limit_resolution,
				dw->limit_reso);
	unlock_task(res_lock,"draw_coordinate");
}

int
select_coordinate(
	RESOURCE * r,
	SELECT_WORK * sw)
{
MAP * m1;
SELECT_WORK sw1;
int i;

	lock_task(res_lock);
	for ( m1 = R_NEXT(MAP*,&r->c.map_children) ; 
			m1 != (MAP*)&r->c.map_children ;
			m1 = R_NEXT(MAP*,&m1->h) ) {
		if ( m1->flags & MF_BROWSE )
			continue;
		if ( m1->src == 0 )
			continue;
		if ( m1->map_file == 0 )
			continue;
		if ( m1->src->h.type == RT_COORDINATE )
			continue;
		sw1 = *sw;
		sw1.map = m1;
		unlock_task(res_lock,"select_coordinate");
		if ( select_resource(
				m1->src,
				&sw1) )
			return 1;
		lock_task(res_lock);
	}
	unlock_task(res_lock,"select_coordinate");
	return 0;
}

int
check_coordinate(
	RESOURCE * r,
	CHECK_WORK * chk)
{
MAP * m1;
	if ( chk->max_coord_level <= chk->coord_level )
		return 0;
	chk->type[RT_COORDINATE] ++;
	if ( chk->resource == r )
		chk->flags |= CWF_RESOURCE;

	lock_task(res_lock);

	for ( m1 = R_NEXT(MAP*,&r->c.map_children) ; 
			m1 != (MAP*)&r->c.map_children ;
			m1 = R_NEXT(MAP*,&m1->h) ) {
		if ( m1->flags & MF_BROWSE )
			continue;
		if ( m1->src == 0 )
			continue;
		if ( m1->map_file == 0 )
			continue;
		unlock_task(res_lock,"check_coordinate");
		chk->coord_level ++;
		if ( check_resource(
				m1->src,
				chk) )
			return 1;
		if ( check_resource(
				m1->map_file,
				chk) )
			return 1;
		chk->coord_level --;
		lock_task(res_lock);
	}
	unlock_task(res_lock,"check_coordinate");
	return 0;
}

void
get_point_coordinate(
	GBVIEW_FLAME * gf,
	RESOURCE* r,
	GET_POINT_WORK * w)
{
MAP * m1;
int ret;
REAL1 dummy;
INDICATE * in;
GB_POINT pp,p;
GET_POINT_WORK ww;

	p = w->pt;
	in = _search_indicate(gf,&r->h.entry);
	if ( in && (in->flags&IF_COORDINATE) ) {
		in->status = IS_COORDINATE;
		in->result = p;
	}
	lock_task(res_lock);
	for ( m1 = R_PREV(MAP*,&r->c.map_children) ;
			m1 != (MAP*)&r->c.map_children;
			m1 = R_PREV(MAP*,&m1->h) ) {
		if ( m1->flags & MF_BROWSE )
			continue;
		if ( m1->src == 0 )
			continue;
		if ( m1->map_file == 0 )
			continue;
		if ( m1->src->h.type == RT_COORDINATE )
			continue;
		dummy = 1;
		pp = p;
		map_conv_reverse(m1->map_file,&pp,&dummy,1);
		if ( dummy < 0 )
			continue;
		ww = *w;
		ww.pt = pp;
		unlock_task(res_lock,"point");
		if ( get_point_resource(
				gf,
				m1->src,&ww) == 0 ) {
			if ( in && in->flags&IF_OBJECT ) {
				in->status |= IS_OBJECT;
				in->res_object = m1->src;
			}
		}
		lock_task(res_lock);
	}
	unlock_task(res_lock,"point");
}

int
exit_lock_coord(
	RESOURCE * r,
	int data)
{
MAP * m1;

	lock_task(res_lock);

	for ( m1 = R_NEXT(MAP*,&r->c.map_children) ; 
			m1 != (MAP*)&r->c.map_children ;
			m1 = R_NEXT(MAP*,&m1->h) ) {
		if ( m1->flags & MF_BROWSE )
			continue;
		if ( m1->src == 0 )
			continue;
		if ( m1->map_file == 0 )
			continue;
		unlock_task(res_lock,"check_coordinate");
		exit_lock_resource(m1->src,data);
		exit_lock_resource(m1->map_file,data);
		lock_task(res_lock);
	}
	unlock_task(res_lock,"check_coordinate");
	return 0;
}
