/**********************************************************************
 
	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	"pri_level.h"
#include	"gbview.h"
#include	"xlerror.h"
#include	"xl.h"
#include	"win_flame.h"
#include	"gb.h"
#include	"radar.h"
#include	"lock_level.h"
#include	"memory_debug.h"

#define TOLL	5
#define ACCESS_TIME_LIMIT	20

typedef struct gvha_coordinate {
	struct gvha_coordinate *	next;
	int				id;
	L_CHAR *			url;
} GVHA_COORDINATE;

typedef struct gvha_pos {
	struct gvha_pos *		next;

	L_CHAR * 			target;
	GB_POINT			center;
	double				rotate;
	double				resolution;
} GVHA_POS;


typedef struct gvha_ids {
	int		org_id;
	int		gf_id;
	L_CHAR *	crd;
	int		status;
#define IDSS_INVISIBLE	0x00000000
#define IDSS_VISIBLE	0x00000001
#define IDSS_B		0x00000002
#define IDSS_L		0x00000004
} GVHA_IDS;

#define IDS_ORG	1
#define IDS_GF	2

typedef struct gvha_query {
	unsigned	mode:3;
#define GVHA_MODE_MOVE	1
#define GVHA_MODE_INFO1	2
#define GVHA_MODE_INFO2	3
#define GVHA_MODE_RSS	4
	unsigned	complete:1;
	GVHA_POS	pos;
	GVHA_IDS *	layer;
	int		layer_len;
	GVHA_IDS *	crd;
	int		crd_len;
	I_POINT		move;
	double		zoom;
	I_POINT		win_size;
} GVHA_QUERY;

typedef struct gvha_frame_cache {
	struct gvha_frame_cache *	next;
	GVHA_IDS *			layer;
	int				layer_len;
	GVHA_POS *			pos;

	I_POINT				win_size;
	GBVIEW_FLAME *			gf;

	void *				image;
	int				image_len;

	GBVIEW_STATUS			c_sts;
	GBVIEW_STATUS			sts;
	LOADING_STATUS			ls;
	int				all;

	int				complete_cnt;

	unsigned int			access_time;

	unsigned 			mv_lock:1;
	unsigned			lock:1;
} GVHA_FRAME_CACHE;

GVHA_COORDINATE * coord_list;
QUERY_THREAD * cond_list;
SEM gvha_lock;
GVHA_FRAME_CACHE * processed_cache;
int processed_cache_size;
int max_processed_cache_size;
/*
GVHA_FRAME_CACHE * complete_cache;
int complete_cache_size;
int max_complete_cache_size;
*/
XLISP_ENV * HTTP_setup_env;

XL_SEXP * xl_Coordinate();
XL_SEXP * xl_Condition();
XL_SEXP * xl_Cache();

XL_SEXP *
_xl_GET(
	XLISP_ENV * e,XL_SEXP * s,XLISP_ENV * ae,XL_SYM_FIELD * sf,
	GVHA_FRAME_CACHE * out_c);
XL_SEXP *
_xl_GET_call(
	XLISP_ENV * e,XL_SEXP * s,XLISP_ENV * ae,XL_SYM_FIELD * sf);
XL_SEXP * xl_GET();

void gv_flame_radar_indicate_event();
void call_gv_flame_event();


void
init_gv_http_agent(XLISP_ENV * e0,XLISP_ENV * e1)
{
XLISP_ENV * http_e0,* http_e1;
XL_SEXP * http_s0,* http_s1;


	gvha_lock = new_lock(LL_GV_HTTP_AGENT);

	http_e0 = new_env(e0);
	HTTP_setup_env = http_e1 = new_env(http_e0);
	http_s0 = get_env(http_e0);
	http_s1 = get_env(http_e1);

	set_env(e0,l_string(std_cm,"HTTP"),http_s0);
	set_env(e0,l_string(std_cm,"HTTPSetup"),http_s1);

	set_env(http_e1,l_string(std_cm,"Coordinate"),
		get_func_prim(xl_Coordinate,FO_APPLICATIVE,0,3,3));
	set_env(http_e1,l_string(std_cm,"Condition"),
		get_func_prim(xl_Condition,FO_APPLICATIVE,0,2,2));
	set_env(http_e1,l_string(std_cm,"Cache"),
		get_func_prim(xl_Cache,FO_APPLICATIVE,0,1,1));

	set_env(http_e0,l_string(std_cm,"_GET_call"),
		get_func_prim(_xl_GET_call,FO_APPLICATIVE,0,1,1));
	set_env(http_e0,l_string(std_cm,"GET"),
		get_func_prim(xl_GET,FO_APPLICATIVE,0,1,1));
}


void
_insert_gvha_coordinate(int id,L_CHAR * url)
{
GVHA_COORDINATE * c;
	c = d_alloc(sizeof(*c));
	c->id = id;
	c->url = ll_copy_str(url);
	c->next = coord_list;
	coord_list = c;
}

void
insert_gvha_coordinate(int id,L_CHAR * url)
{
	lock_task(gvha_lock);
	_insert_gvha_coordinate(id,url);
	unlock_task(gvha_lock,"insert_gvha_coordinate");
}


int
gvha_ids_cmp_org(GVHA_IDS * ids1,int len1,GVHA_IDS * ids2,int len2)
{
int i,j;


	for ( i = 0 ; i < len1 ; i ++ ) {
		for ( j = 0 ; j < len2 ; j ++ ) {
			if ( ids1[i].org_id == ids2[j].org_id ) {
				if ( ids1[i].status != ids2[j].status )
					return -1;
				break;
			}
		}
	}
	for ( j = 0 ; j < len2 ; j ++ ) {
		for ( i = 0 ; i < len1 ; i ++ ) {

			if ( ids1[i].org_id == ids2[j].org_id ) {
				if ( ids1[i].status != ids2[j].status )
					return -1;
				break;
			}
		}
		if ( i == len1 ) {
			if ( ids2[j].status )
				return -1;
		}
	}
	return 0;
}

int
gvha_ids_cmp_gf(GVHA_IDS * ids1,int len1,GVHA_IDS * ids2,int len2)
{
int i,j;
	if ( len1 != len2 )
		return -1;
	for ( i = 0 ; i < len1 ; i ++ ) {
		for ( j = 0 ; j < len2 ; j ++ ) {
			if ( ids1[i].gf_id == ids2[j].gf_id ) {
				if ( ids1[i].status != ids2[j].status )
					return -1;
			}
		}
	}
	return 0;
}

double
gvha_pos_cmp(GVHA_POS * p1,GVHA_POS * p2,int radius)
{
double dd;
double ret;
	if ( l_strcmp(p1->target,p2->target) )
		return -1;
	dd = p1->resolution - p2->resolution;
	if ( dd < 0 )
		dd = - dd;
	ret = (dd * radius)/p1->resolution;
	dd = p1->rotate - p2->rotate;
	if ( dd < 0 )
		dd = - dd;
	ret += (dd * 3.14 * radius)/180;
	dd = (p1->center.x - p2->center.x) * p1->resolution;
	if ( dd < 0 )
		dd = - dd;
	ret += dd;
	dd = (p1->center.y - p2->center.y) * p1->resolution;
	if ( dd < 0 )
		dd = - dd;
	ret += dd;

	return ret;
}

void
free_gvha_pos(GVHA_POS * p)
{
	if ( p->target )
		d_f_ree(p->target);
}

void
free_gvha_ids(GVHA_IDS * ids,int len)
{
int i;
	for ( i = 0 ; i < len ; i ++ ) {
		if ( ids[i].crd )
			d_f_ree(ids[i].crd);
	}
}

void
free_gvha_query(GVHA_QUERY * q)
{
	free_gvha_pos(&q->pos);
	if ( q->layer ) {
		free_gvha_ids(q->layer,q->layer_len);
		d_f_ree(q->layer);
	}
	if ( q->crd ) {
		free_gvha_ids(q->crd,q->crd_len);
		d_f_ree(q->crd);
	}
}

GVHA_FRAME_CACHE *
_search_gvha_frame_cache(
	GVHA_FRAME_CACHE ** root,
	GVHA_QUERY * q,
	int layer_flag,int complete_flag)
{
GVHA_FRAME_CACHE ** rp, * ret, ** rpp, ** rpp_crd;
GVHA_POS * p;
double dist,d;
 double dist_crd;
int ws_flag;
int tim;
	ws_flag = layer_flag & 0x4;
	layer_flag &= 3;

retry:
	if ( layer_flag == 2 ) {
		if ( *root == 0 )
			return 0;
		dist = -1;
		rpp = 0;

		dist_crd = -1;
		rpp_crd = 0;
		for ( rp = root ; (*rp)->next ; rp = &(*rp)->next ) {
			if ( (*rp)->mv_lock )
				continue;
			if ( complete_flag && (*rp)->complete_cnt )
				continue;
			if ( ws_flag == 0 ) {
				if ( (*rp)->win_size.x != q->win_size.x )
					continue;
				if ( (*rp)->win_size.y != q->win_size.y )
					continue;
			}
			tim = get_xltime() - (*rp)->access_time;
			if ( tim < ACCESS_TIME_LIMIT ) {
				tim = TOLL*(ACCESS_TIME_LIMIT - tim);
			}
			else	tim = 0;
			for ( p = (*rp)->pos ; p ; p = p->next ) {
				d = gvha_pos_cmp(p,&q->pos,
					q->win_size.x + q->win_size.y);
				if ( d < 0 ) {
					if ( dist_crd == -1 ||
							tim < dist_crd ) {
						rpp_crd = rp;
						dist_crd = tim;
					}
				}
				else {
					d += tim;
					if ( dist == -1 || d < dist ) {
						rpp = rp;
						dist = d;
					}
				}
			}
		}
		if ( rpp )
			rp = rpp;
		else	rp = rpp_crd;
	}
	else {
		for ( rp = root ; *rp ; rp = &(*rp)->next ) {
			if ( (*rp)->mv_lock )
				continue;
			if ( complete_flag && (*rp)->complete_cnt )
				continue;
			if ( ws_flag == 0 ) {
				if ( (*rp)->win_size.x != q->win_size.x )
					continue;
				if ( (*rp)->win_size.y != q->win_size.y )
					continue;
			}
			for ( p = (*rp)->pos ; p ; p = p->next ) {
				d = gvha_pos_cmp(p,&q->pos,
					 q->win_size.x + q->win_size.y);
				if ( d < 0 )
					continue;
				if ( d < TOLL )
					break;
			}
			if ( p == 0 )
				continue;
			if ( layer_flag == 0 )
				break;
			if ( gvha_ids_cmp_org(q->layer,q->layer_len,
					(*rp)->layer,
					(*rp)->layer_len) )
				continue;
			break;
		}
	}
	if ( rp == 0 )
		return 0;
	if ( (*rp) == 0 )
		return 0;
	ret = *rp;
	*rp = ret->next;
	ret->next = *root;
	*root = ret;
	for ( ; ret->lock ; ) {
		if ( ret->mv_lock )
			goto retry;
		if ( complete_flag && ret->complete_cnt )
			goto retry;
		sleep_task((int)ret,gvha_lock);
		lock_task(gvha_lock);
	}
	ret->lock = 1;
	ret->access_time = get_xltime();
	return ret;
}

GVHA_FRAME_CACHE *
search_gvha_frame_cache(
	GVHA_FRAME_CACHE ** root,
	GVHA_QUERY * q,int layer_flag,int c_flag)
{
GVHA_FRAME_CACHE * ret;
	lock_task(gvha_lock);
	ret = _search_gvha_frame_cache(root,q,layer_flag,c_flag);
	unlock_task(gvha_lock,"insert_gvha_coordinate");
	return ret;
}

void
unlock_frame_lock(GVHA_FRAME_CACHE * c)
{
	lock_task(gvha_lock);
	c->lock = 0;
	c->mv_lock = 0;
	wakeup_task((int)c);
	unlock_task(gvha_lock,"c");
}


int
lock_mv_lock(GVHA_FRAME_CACHE * c)
{
int ret;
	lock_task(gvha_lock);
	if ( c->complete_cnt ) {
		ret = -1;
		goto finish;
	}
	c->mv_lock = 1;
	wakeup_task((int)c);
	ret = 0;
finish:
	unlock_task(gvha_lock,"c");
	return ret;
}

void
complete_lock(GVHA_FRAME_CACHE * c)
{
	lock_task(gvha_lock);
	c->complete_cnt ++;
	wakeup_task((int)c);
	unlock_task(gvha_lock,"c");
}

void
complete_unlock(GVHA_FRAME_CACHE * c)
{
	lock_task(gvha_lock);
	c->complete_cnt --;
	if ( c->complete_cnt < 0 )
		er_panic("complete_unlock");
	wakeup_task((int)c);
	unlock_task(gvha_lock,"c");
}


char *
get_str(char ** ptr,char * ch,char * inp,char * list)
{
char * ret;
int len;
char * lp;
	for ( len = 0 ; inp[len] ; len ++ ) {
		for ( lp = list ; *lp ; lp ++ )
			if ( inp[len] == *lp )
				goto next;
	}
next:
	ret = d_alloc(len+1);
	memcpy(ret,inp,len);
	ret[len] = 0;
	*ch = inp[len];
	if ( inp[len] == 0 )
		*ptr = &inp[len];
	else	*ptr = &inp[len+1];
	return ret;
}

L_CHAR * 
get_crd_by_id(int id)
{
GVHA_COORDINATE * c;
	for ( c = coord_list ; c ; c = c->next )
		if ( c->id == id )
			return ll_copy_str(c->url);
	return 0;
}

int
get_id_by_crd(L_CHAR * crd)
{
GVHA_COORDINATE * c;
	for ( c = coord_list ; c ; c = c->next )
		if ( l_strcmp(c->url,crd) == 0 )
			return c->id;
	return -1;
}


char *
get_str_list(GVHA_IDS ** ids,int * len,char *dir)
{
char * str;
int _len;
GVHA_IDS * ret;
char * p;
char ch;
	ret = 0;
	_len = 0;
	for ( ; *dir ; ) {
		if ( *dir == '&' ) {
			dir ++;
			break;
		}
		str = get_str(&dir,&ch,dir,"[");
		if ( ch != '[' ) {
			*ids = 0;
			*len = 0;
			return dir;
		}
		ret = d_re_alloc(ret,(_len+1)*sizeof(GVHA_IDS));
		memset(&ret[_len],0,sizeof(GVHA_IDS));
		if ( '0' <= str[0] && str[0] <= '9' ) {
			ret[_len].org_id = atoi(str);
		}
		else {
			ret[_len].crd = nl_copy_str(std_cm,str);
		}
		d_f_ree(str);
		str = get_str(&dir,&ch,dir,"]");
		if ( ch != ']' ) {
			*ids = 0;
			*len = 0;
			return dir;
		}
		for ( p = str ; *p ; p ++ ) {
			switch ( *p ) {
			case '0':
				break;
			case '1':
				ret[_len].status |= IDSS_VISIBLE;
				break;
			case 'B':
				ret[_len].status |= IDSS_B;
				break;
			case 'L':
				ret[_len].status |= IDSS_L;
				break;
			}
		}
		d_f_ree(str);
		_len ++;
	}
	*len = _len;
	*ids = ret;
	return dir;
}


int
get_gvha_query(GVHA_QUERY * q,char * dir)
{
char * str;
char ch;
int i;
	memset(q,0,sizeof(*q));
	q->zoom = 1;
	q->mode = GVHA_MODE_MOVE;
	for ( ; *dir && *dir != '?' ; dir ++ );
	if ( *dir == 0 )
		return -1;
	dir++;
	for ( ; *dir ; ) {
//ss_printf("TARGET = %s\n",dir);
		switch ( *dir ) {
		case 't':
			dir++;
			if ( *dir != '=' )
				return -2;
			dir ++;
			str = get_str(&dir,&ch,dir,"_");
			if ( '0' <= str[0] && str[0] <= '9' ) {
				q->pos.target = get_crd_by_id(atoi(str));
				if ( q->pos.target == 0 )
					return -3;
			}
			else {
				q->pos.target = 
					nl_copy_str(std_cm,str);
			}
			d_f_ree(str);
			if ( *dir == 0 )
				return -4;
			switch ( *dir ) {
			case 'a':
				dir++;
				if ( *dir != '_' )
					return -22;
				dir++;
				str = get_str(&dir,&ch,dir,"_");
				sscanf(str,"%f",&q->pos.center.x);
				d_f_ree(str);
				if ( *dir == 0 )
					return -5;
				str = get_str(&dir,&ch,dir,"_");
				sscanf(str,"%f",&q->pos.center.y);
				d_f_ree(str);
				if ( *dir == 0 )
					return -6;
				str = get_str(&dir,&ch,dir,"_");
				sscanf(str,"%lf",&q->pos.rotate);
				d_f_ree(str);
				if ( *dir == 0 )
					return -7;
				str = get_str(&dir,&ch,dir,"&");
				sscanf(str,"%lf",&q->pos.resolution);
				d_f_ree(str);
				break;
			default:
				return -8;
			}
			break;
		case 'm':
			dir++;
			switch ( *dir ) {
			case 'v':
				dir ++;
				if ( *dir != '=' )
					return -9;
				dir ++;
				str = get_str(&dir,&ch,dir,"_");
				sscanf(str,"%i",&q->move.x);
				d_f_ree(str);
				if ( *dir == 0 )
					return -10;
				str = get_str(&dir,&ch,dir,"&");
				sscanf(str,"%i",&q->move.y);
				d_f_ree(str);
				break;
			case 'd':
				dir ++;
				if ( *dir != '=' )
					return -11;
				dir ++;
				str = get_str(&dir,&ch,dir,"&");
				if ( strcmp(str,"move") == 0 )
					q->mode = GVHA_MODE_MOVE;
				else if ( strcmp(str,"info1") == 0 )
					q->mode = GVHA_MODE_INFO1;
				else if ( strcmp(str,"info2") == 0 )
					q->mode = GVHA_MODE_INFO2;
				else if ( strcmp(str,"rss") == 0 )
					q->mode = GVHA_MODE_RSS;
				else	return -12;
				d_f_ree(str);
				break;
			default:
				return -13;
			}
			break;
		case 'r':
			dir ++;
			if ( *dir != '=' )
				return -14;
			dir ++;
			str = get_str(&dir,&ch,dir,"&");
			sscanf(str,"%lf",&q->pos.rotate);
			d_f_ree(str);
			break;
		case 'z':
			dir ++;
			if ( *dir != '=' )
				return -15;
			dir ++;
			str = get_str(&dir,&ch,dir,"&");
			sscanf(str,"%lf",&q->zoom);
			d_f_ree(str);
			break;
		case 'l':
			dir ++;
			if ( *dir != '=' )
				return -21;
			dir ++;
			dir = get_str_list(&q->layer,&q->layer_len,dir);
			break;
		case 'c':
			dir ++;
			if ( *dir != '=' )
				return -16;
			dir ++;
			dir = get_str_list(&q->crd,&q->crd_len,dir);
			if ( q->crd_len == 0 )
				return -17;
			for ( i = 0 ; i < q->crd_len ; i ++ )
				q->crd[i].crd 
					= get_crd_by_id(q->crd[i].org_id);
			break;
		case 'p':
			dir ++;
			if ( *dir != '=' )
				return -18;
			dir ++;
			str = get_str(&dir,&ch,dir,"&");
			q->complete = atoi(str);
			d_f_ree(str);
			break;
		case 's':
			dir ++;
			if ( *dir != '=' )
				return -19;
			dir ++;
			str = get_str(&dir,&ch,dir,"_");
			q->win_size.x = atoi(str);
			d_f_ree(str);
			str = get_str(&dir,&ch,dir,"&");
			q->win_size.y = atoi(str);
			d_f_ree(str);
			break;
		case 'n':
			dir ++;
			if ( *dir != '=' )
				return -23;
			dir ++;
			str = get_str(&dir,&ch,dir,"&");
			d_f_ree(str);
			break;
		default:
			return -20;
		}
		if ( *dir == 0 )
			break;
	}
	return 0;
}


GVHA_FRAME_CACHE *
new_frame_cache(GVHA_QUERY * q)
{
GBVIEW_FLAME * gf;
GBVIEW_STATUS sts;
GVHA_FRAME_CACHE * ret, * r;
QUERY_THREAD * qt, * qt2, * qt3;
int _ret;
int len;
int i;

	gf = wf_open();

	wf_init_status(&sts);
	sts.flags = SF_DEFAULT_WS|SF_WIDTH|SF_HEIGHT;
//	sts.event = call_gv_flame_event;
//	sts.event_user_arg = (void*)gf->id;
	sts.default_ws = get_ws(l_string(std_cm,"DefaultStyle"));
	sts.width = q->win_size.x;
	sts.height = q->win_size.y;
	wf_set_status(gf,&sts);
/*
	rc_set_indicate_event((RADAR_CACHE*)gf->radar_ptr,
		gv_flame_radar_indicate_event, (void*)gf->id);
*/
	qt = copy_q_thread(cond_list);
	len = 0;
	for ( qt2 = qt ; qt2 ; qt2 = qt2->next , len ++ )
		qt2->id = 0;

	_ret = rc_insert_q_thread((RADAR_CACHE*)gf->radar_ptr,qt);
	

	ret = d_alloc(sizeof(*ret));
	memset(ret,0,sizeof(*ret));
	ret->gf = gf;
	ret->layer = d_alloc(len * sizeof(GVHA_IDS));
	memset(ret->layer,0,sizeof(GVHA_IDS)*len);
	ret->layer_len = len;
	ret->win_size.x = q->win_size.x;
	ret->win_size.y = q->win_size.y;
	ret->access_time = get_xltime();

	i = 0;
	for ( qt2 = qt , qt3 = cond_list ; 
			qt3 ; qt2 = qt2->next , qt3 = qt3->next , i ++ ) {
		ret->layer[i].org_id = qt3->id;
		ret->layer[i].gf_id = qt2->id;
	}

	free_query_thread(qt);

	lock_task(gvha_lock);
	ret->next = 0;
	if ( processed_cache ) {
		r = processed_cache;
		for ( ; r->next ; r = r->next );
		r->next = ret;
	}
	else {
		processed_cache = ret;
	}
	unlock_task(gvha_lock,"new_frame_cache");
	return ret;
}


XL_SEXP *
xl_Coordinate(
	XLISP_ENV * e,XL_SEXP * s,XLISP_ENV * ae,XL_SYM_FIELD * sf)
{
XL_SEXP * _id;
XL_SEXP * _url;

	_id = get_el(s,1);
	_url = get_el(s,2);
	if ( get_type(_id) != XLT_INTEGER )
		goto type_missmatch;
	if ( get_type(_url) != XLT_STRING )
		goto type_missmatch;
	insert_gvha_coordinate(_id->integer.data,_url->string.data);
	return 0;

type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"HTTP/Coordinate"),
		0);
}




XL_SEXP *
xl_Condition(
	XLISP_ENV * e,XL_SEXP * s,XLISP_ENV * ae,XL_SYM_FIELD * sf)
{
XL_SEXP * cnd;
QUERY_THREAD * qth, * n, * n2;

	cnd = get_el(s,1);
	qth = sexp_to_q_thread(cnd);
	if ( qth == 0 )
		goto type_missmatch;
	lock_task(gvha_lock);
	for ( n = qth ; n ; n = n->next ) {
		for ( n2 = cond_list ; n2 ; n2 = n2->next )
			if ( n->id == n2->id )
				goto id_error;
	}
	for ( n = qth ; n->next ; n = n->next );
	n->next = cond_list;
	cond_list = qth;
	unlock_task(gvha_lock,"insert_gvha_coordinate");
	return 0;

type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"HTTP/Condition"),
		0);
id_error:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_DUP_DEFINITION,
		l_string(std_cm,"HTTP/Condition"),
		n_get_string("duplicate id"));
}

typedef struct _Cache_WORK {
	int		_g;
	XLISP_ENV *	e;
	XL_SEXP * 	s;
	XLISP_ENV *	ae;
	XL_SYM_FIELD *	sf;
	GVHA_QUERY	q;
	int		get_flag;
} Cache_WORK;

void
Cache_thread(TKEY d)
{
Cache_WORK * w;
GVHA_FRAME_CACHE *c;
XL_SEXP * ret, * sym;
XL_INTERPRETER * xli;

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

	gc_push(0,0,"cache_thread");

	w = (Cache_WORK*)GET_TKEY(d);

	ret = 0;
	ret = cons(get_env(w->e),ret);
	ret = cons(w->s,ret);
	if ( w->ae )
		ret = cons(get_env(w->ae),ret);
	sym = n_get_symbol("d");
	sym->symbol.field = w->sf;
	ret = cons(sym,ret);

	lock_task(gvha_lock);
	w->get_flag = 1;
	wakeup_task((int)w);
	unlock_task(gvha_lock,"cache_thread");

	for ( ; w->_g ; w->_g -- ) {
		c = new_frame_cache(&w->q);
		ret = _xl_GET(w->e,w->s,w->ae,w->sf,c);
		if ( get_type(ret) == XLT_ERROR )
			break;
		sleep_sec(5);
	}
	free_gvha_query(&w->q);
	d_f_ree(w);

	gc_pop(0,0);

	close_self_interpreter();
}


XL_SEXP *
xl_Cache(
	XLISP_ENV * e,XL_SEXP * s,XLISP_ENV * ae,XL_SYM_FIELD * sf)
{
GVHA_FRAME_CACHE * c;
L_CHAR * g;
XL_SEXP * ret;
L_CHAR * dir;
int rcode;
Cache_WORK * w;
	w = d_alloc(sizeof(*w));
	g = get_sf_attribute(sf,l_string(std_cm,"generate"));
	if ( g == 0 )
		w->_g = 1;
	else {
		w->_g = atoi(n_string(std_cm,g));
		if ( w->_g == 0 )
			w->_g = 1;
	}
	dir = get_sf_attribute(sf,l_string(std_cm,"dir"));
	if ( dir == 0 )
		goto sys_error;
	rcode = get_gvha_query(&w->q,n_string(std_cm,dir));
	if ( rcode < 0 )
		goto invalid_url;
	c = new_frame_cache(&w->q);
	ret = _xl_GET(e,s,ae,sf,c);
	if ( get_type(ret) == XLT_ERROR )
		return ret;
	w->_g --;
	if ( w->_g <= 0 ) {
		free_gvha_query(&w->q);
		d_f_ree(w);
	}
	else {
		w->e = e;
		w->s = s;
		w->ae = ae;
		w->sf = sf;
		w->get_flag = 0;
		create_task(Cache_thread,(int)w,PRI_FETCH);
		lock_task(gvha_lock);
		for ( ; w->get_flag == 0 ; ) {
			sleep_task((int)w,gvha_lock);
			lock_task(gvha_lock);
		}
		unlock_task(gvha_lock,"Cache_thread");
	}
	return 0;
sys_error:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_FIELD_NAME,
		l_string(std_cm,"gbview/Cache"),
		n_get_string("dir attribute is required"));
invalid_url:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_FIELD_NAME,
		l_string(std_cm,"gbview/Cache"),
		List(n_get_string("invalid URL"),
			get_integer(rcode,0),-1));
}

void
change_layer(GVHA_FRAME_CACHE * c,GVHA_QUERY * q)
{
QUERY_THREAD * qt, * qt2, * del;
QUERY_THREAD ** pp;
int i,j;
int cg;
	qt = copy_q_thread(cond_list);
	i = 0;
	for ( qt2 = qt ; qt2 ; qt2 = qt2->next , i ++ ) {
		qt2->flags = 0;
		qt2->id = c->layer[i].gf_id;
		cg = 0;
		for ( j = 0 ; j < q->layer_len ; j ++ ) {
			if ( c->layer[i].org_id != q->layer[j].org_id )
				continue;
			if ( (q->layer[j].status & IDSS_VISIBLE)
				!= (c->layer[i].status & IDSS_VISIBLE) )
				cg = 1;
			else	cg = 0;
			if ( q->layer[j].status & IDSS_VISIBLE )
				c->layer[i].status |= IDSS_VISIBLE;
			else	c->layer[i].status &= ~IDSS_VISIBLE;
			break;
		}
		if ( j == q->layer_len ) {
			if ( c->layer[i].status & IDSS_VISIBLE )
				cg = 1;
			c->layer[i].status &= ~IDSS_VISIBLE;
		}
		if ( cg ) {
			if ( c->layer[i].status & IDSS_VISIBLE )
				qt2->flags = QTF_ACTIVE;
			else	qt2->flags = 0;
			qt2->mask = QTF_ACTIVE;
		}
		else {
			qt2->flags = 0;
			qt2->mask = 0;
		}
	}
	del = 0;
	for ( pp = &qt ; *pp ; ) {
		qt2 = *pp;
		if ( qt2->mask == 0 ) {
			*pp = qt2->next;
			qt2->next = del;
			del = qt2;
			continue;
		}
		pp = &qt2->next;
	}
	free_query_thread(del);
/*
ss_printf("QT=\n");
for ( qt2 = qt ; qt2 ; qt2 = qt2->next )
ss_printf("QT %i %x:%x\n",qt2->id,qt2->flags,qt2->mask);
*/
	rc_set_q_thread((RADAR_CACHE*)c->gf->radar_ptr,qt);
	free_query_thread(qt);
}

void
loading_status_cal(GVHA_FRAME_CACHE  *c)
{
int i;
int all;
LOADING_STATUS * ls;
	ls = &c->ls;

	all = 0;
	all += ls->rc.search_loading;
//ss_printf("rc.search_loading = %i\n",ls->rc.search_loading);
	all += ls->rc.layer_management;
//ss_printf("rc.layer_management = %i\n",ls->rc.layer_management);
	all += ls->rc.change_base_coord;
//ss_printf("rc.change_base_cord = %i\n",ls->rc.change_base_coord);
	all += ls->rc.ri.d.beam;
//ss_printf("rc.ri.d.beam = %i\n",ls->rc.ri.d.beam);
	for ( i = CRT_MAX ; i >= 0 ; i -- ) {
		all += ls->rc.ri.d.loading_res[i];
//ss_printf("rc.ri.d.loading_res[%i] = %i\n",i,ls->rc.ri.d.loading_res[i]);
	}
	for ( i = CRT_MAX ; i >= 0 ; i -- ) {
		all += ls->rc.ri.d.ready_res[i];
//ss_printf("rc.ri.d.ready_res[%i] = %i\n",i,ls->rc.ri.d.ready_res[i]);
	}
	all += ls->rc.ri.d.load_to_beam;
//ss_printf("rc.ri.d.load_to_beam = %i\n",ls->rc.ri.d.load_to_beam);
	all += ls->rc.ri.d.beam_to_resource;
//ss_printf("rc.ri.d.beam_to_resource = %i\n",ls->rc.ri.d.beam_to_resource);
	all += ls->rc.ri.d.retrieve1;
//ss_printf("rc.ri.d.retrieve1 = %i\n",ls->rc.ri.d.retrieve1);
	all += ls->rc.ri.d.retrieve2;
//ss_printf("rc.ri.d.retrieve2 = %i\n",ls->rc.ri.d.retrieve2);

	all += ls->wf.draw;
//ss_printf("rc.wf.draw = %i\n",ls->wf.draw);
	all += ls->wf.exit;
//ss_printf("rc.wf.exit = %i\n",ls->wf.exit);
	all += ls->wf.load_structure;
//ss_printf("rc.wf.load_structure = %i\n",ls->wf.load_structure);
	all += ls->wf.data_request;
//ss_printf("rc.wf.data_request = %i\n",ls->wf.data_request);
	all += ls->wf.indicate_request;
//ss_printf("rc.wf.indicate_request = %i\n",ls->wf.indicate_request);
	all += ls->wf.indicate;
//ss_printf("rc.wf.indicate = %i\n",ls->wf.indicate);
	all += ls->wf.raw_image_request;
//ss_printf("rc.wf.raw_image_request = %i\n",ls->wf.raw_image_request);
	c->all = all;
}


char *
get_next_target(GVHA_FRAME_CACHE * c,L_CHAR * path,int mode)
{
char * _path;
char * base,* str,* _base;
char ch;
int id;
int p;
int len;
int i;
WF_ID wfid;
GBVIEW_LAYER_STATUS * ls;
GVHA_POS * gp, * gp2;
double d;
XL_SEXP * url;
int port;
L_CHAR * site;
	url = eval(HTTP_setup_env,
			n_get_symbol("url"));
	if ( get_type(url) != XLT_STRING ) {
		port = get_my_port();
		site = get_xllisp_site();
		if ( site ) {
			if ( port == 0 ) {
				base = d_alloc(100);
				sprintf(base,"http://%s",
					n_string(std_cm,site));
			}
			else {
				base = d_alloc(100);
				sprintf(base,"http://%s:%i",
					n_string(std_cm,site),
					port);
			}
			goto make_base;
		}
		else {
			base = get_str(&_path,
				&ch,n_string(std_cm,path),"?");
		}
	}
	else {
		base = copy_str(n_string(std_cm,url->string.data));
	make_base:
		p = strlen(base);
		if ( base[p-1] == '/' )
			p--;
		base = d_re_alloc(base,
			p + strlen(_base = n_string(std_cm,path))+10);
		_base = get_str(&_path,&ch,_base,"?");
		strcpy(&base[p],_base);
	}
	p = strlen(base);
	base = d_re_alloc(base,p+2);
	base[p] = '?';
	p++;
	wfid = c->sts.current;
/*
	for ( ls = c->sts.layers ; ls ; ls = ls->next )
		if ( ls->id == wfid )
			break;
*/
	ls = c->sts.current_ls;
	if ( ls == 0 )
		er_panic("get_next_target");
	id = get_id_by_crd(ls->entry_url);
	if ( id < 0 ) {
		str = n_string(std_cm,ls->entry_url);
		base = d_re_alloc(base,p+(len=strlen(str))+100);
		sprintf(&base[p],"s=%i_%i&t=%s_a_%f_%f_%f_%f&l=",
			c->win_size.x,
			c->win_size.y,
			str,
			c->sts.flame_base_center.x,
			c->sts.flame_base_center.y,
			c->sts.flame_base_rotate,
			c->sts.flame_base_resolution);
	}
	else {
		base = d_re_alloc(base,p+100);
		sprintf(&base[p],"s=%i_%i&t=%i_a_%f_%f_%f_%f&l=",
			c->win_size.x,
			c->win_size.y,
			id,
			c->sts.flame_base_center.x,
			c->sts.flame_base_center.y,
			c->sts.flame_base_rotate,
			c->sts.flame_base_resolution);
	}
	gp = d_alloc(sizeof(*gp));
	gp->center = c->sts.flame_base_center;
	gp->rotate = c->sts.flame_base_rotate;
	gp->resolution = c->sts.flame_base_resolution;
	gp->target = ll_copy_str(ls->entry_url);

	lock_task(gvha_lock);
	for ( gp2 = c->pos ; gp2 ; gp2 = gp2->next ) {
		d = gvha_pos_cmp(gp,gp2,c->win_size.x + c->win_size.y);
		if ( d < 0 )
			continue;
		if ( d < TOLL )
			break;
	}
	if ( gp2 ) {
		d_f_ree(gp->target);
		d_f_ree(gp);
	}
	else {
		gp->next = c->pos;
		c->pos = gp;
	}
	unlock_task(gvha_lock,"return_rdf");


	p = strlen(base);
	for ( i = 0 ; i < c->layer_len ; i ++ ) {
		if ( (c->layer[i].status & IDSS_VISIBLE) == 0 )
			continue;
		base = d_re_alloc(base,p+10);
		sprintf(&base[p],"%i%%5B1%%5D",c->layer[i].org_id);
		p = strlen(base);
	}
	base = d_re_alloc(base,p+20);
	switch ( mode ) {
	case GVHA_MODE_MOVE:
		break;
	case GVHA_MODE_INFO1:
		sprintf(&base[p],"&md=info1");
		break;
	case GVHA_MODE_INFO2:
		sprintf(&base[p],"&md=info2");
		break;
	case GVHA_MODE_RSS:
		sprintf(&base[p],"&md=rss");
		break;
	default:
		er_panic("get_next_taerget");
	}
	p = strlen(base);
	if ( c->ls.wf.dirty == 0 && c->all == 0 ) {
		base = d_re_alloc(base,p+10);
		sprintf(&base[p],"&p=1");
	}
	return base;
}

XL_SEXP *
plot_element_area_list(GVHA_FRAME_CACHE * c)
{
GBVIEW_PLOT_ELEMENT * el, * el_1;
XL_SEXP * area, * ret;
char name[10],coords[100];
int area_i;
	el = wf_all_plot_element(c->gf);
	if ( el == 0 )
		return 0;
	gc_push(0,0,"peal");

	area_i = 1;
	ret = 0;
	for ( el_1 = el ; el_1 ; el_1 = el_1->next ) {
		area = n_get_symbol("area");
		sprintf(name,"area%i",area_i++);
		sprintf(coords,"%i,%i,%i,%i",
			(int)el_1->rect.tl.x,
			(int)el_1->rect.tl.y,
			(int)el_1->rect.br.x,
			(int)el_1->rect.br.y);
		set_attribute(area,
			l_string(std_cm,"href"),
			el_1->ref);
		set_attribute(area,
			l_string(std_cm,"coords"),
			l_string(std_cm,coords));
		set_attribute(area,
			l_string(std_cm,"shape"),
			l_string(std_cm,"rect"));
		set_attribute(area,
			l_string(std_cm,"name"),
			l_string(std_cm,name));
		ret = cons(List(area,-1),ret);
	}
	ret = List(cons(n_get_symbol("gb:html-map"),ret),-1);

	gc_pop(ret,gc_gb_sexp);
	return ret;
}

XL_SEXP *
return_rdf(GVHA_FRAME_CACHE * c,L_CHAR *path)
{
XL_SEXP * ret,* sym,* sym2;
XL_SEXP * cur, * channel, * item, * item2;
char * next_target;
char * rss_target;
	next_target = get_next_target(c,path,GVHA_MODE_MOVE);
	rss_target = get_next_target(c,path,GVHA_MODE_RSS);
	if ( next_target == 0 || rss_target == 0 ) {
		return 0;
	}

	sym = n_get_symbol("rdf:li");
	set_attribute(sym,
		l_string(std_cm,"rdf:resource"),
		l_string(std_cm,next_target));

	if ( c->c_sts.reference ) {
		sym2 = n_get_symbol("rdf:li");
		set_attribute(sym,
			l_string(std_cm,"rdf:resource"),
			c->c_sts.reference);
		cur = List(n_get_symbol("rdf:Seq"),
			List(sym,-1),List(sym2,-1),-1);

	}
	else {
		cur = List(n_get_symbol("rdf:Seq"),
			List(sym,-1),-1);
	}

	sym = n_get_symbol("channel");
	set_attribute(sym,
		l_string(std_cm,"rdf:about"),
		l_string(std_cm,rss_target));

	channel = List(sym,
		List(n_get_symbol("title"),
			n_get_string("GLOBALBASE HTTP GATEWAY"),
			-1),
		List(n_get_symbol("link"),
			n_get_string(next_target),
			-1),
		List(n_get_symbol("description"),
			n_get_string("GLOBALBASE HTTP GATEWAY"),
			-1),
		List(n_get_symbol("items"),
			cur,-1),
		-1);

	sym = n_get_symbol("item");
	set_attribute(sym,
		l_string(std_cm,"rdf:about"),
		l_string(std_cm,next_target));

	item = List(sym,
		List(n_get_symbol("title"),
			n_get_string("GLOBALBASE HTTP GATEWAY"),
			-1),
		List(n_get_symbol("link"),
			n_get_string(next_target),
			-1),
		List(n_get_symbol("description"),
			n_get_string("GLOBALBASE HTTP GATEWAY"),
			-1),
		List(n_get_symbol("gb:status1"),
			get_integer(c->all,0),
			-1),
		List(n_get_symbol("gb:status2"),
			get_integer(c->ls.wf.dirty,0),
			-1),
		-1);
	item = append(item,
		plot_element_area_list(c));

	if ( c->c_sts.reference ) {
		sym = n_get_symbol("item");
		set_attribute(sym,
			l_string(std_cm,"rdf:about"),
			c->c_sts.reference);

		item2 = List(sym2,
			List(n_get_symbol("title"),
				n_get_string("GLOBALBASE HTTP GATEWAY"),
				-1),
			List(n_get_symbol("link"),
				get_string(c->c_sts.reference),
				-1),
			List(n_get_symbol("description"),
				n_get_string("click reference"),
				-1),
			-1);
	}

	sym = n_get_symbol("rdf:RDF");
	set_attribute(sym,
		l_string(std_cm,"xml:lang"),
		l_string(std_cm,"ja"));
	set_attribute(sym,
		l_string(std_cm,"xmlns:gb"),
		l_string(std_cm,
			"http://www.globalbase.org/spec/http-rss/0.1/"));
	set_attribute(sym,
		l_string(std_cm,"xmlns:rdf"),
		l_string(std_cm,
		"http://www.w3.org/1999/02/22-rdf-syntax-ns#"));
	set_attribute(sym,
		l_string(std_cm,"xmlns"),
		l_string(std_cm,"http://purl.org/rss/1.0/"));
	ret = List(sym,channel,item,-1);
	d_f_ree(next_target);
	d_f_ree(rss_target);
	sym = n_get_symbol("?xml");
	set_attribute(sym,
		l_string(std_cm,"version"),
		l_string(std_cm,"1.0"));
	sym = List(sym,-1);
	ret = List(sym,ret,-1);

	sym = n_get_symbol("text/xml");
	set_attribute(sym,
		l_string(std_cm,"Cache-Control"),
		l_string(std_cm,"private"));
	set_attribute(sym,
		l_string(std_cm,"Expire"),
		l_string(std_cm,"-1"));
	return List(sym,ret,-1);
}

void
gvha_flush_pos(GVHA_FRAME_CACHE * c)
{
GVHA_POS * p;
	for ( ; c->pos ; ) {
		p = c->pos;
		c->pos = p->next;
		d_f_ree(p->target);
		d_f_ree(p);
	}
}



XL_SEXP *
_xl_GET(
	XLISP_ENV * e,XL_SEXP * s,XLISP_ENV * ae,XL_SYM_FIELD * sf,
	GVHA_FRAME_CACHE * out_c)
{
L_CHAR * _dir;
GVHA_QUERY q;
GVHA_FRAME_CACHE * c;
XL_SEXP * ret;
int c_flag;
int retry_cnt;
I_POINT from,to;
GB_RECT rr;
GBVIEW_PLANE gbp;
char * err_msg;
int rcode;
char * tmp;
int flush_pos;
int sts_load;
XL_SEXP * sym;


	sts_load = 0;
	flush_pos = 0;
	retry_cnt = 5;
	c_flag = 0;
	_dir = get_sf_attribute(sf,l_string(std_cm,"dir"));
	if ( _dir == 0 )
		goto sys_error;
	err_msg = 0;
	rcode = get_gvha_query(&q,n_string(std_cm,_dir));
	if ( rcode < 0 ) {
		err_msg = "query parsing";
		goto invalid_url;
	}
	if ( out_c ) {
		c = out_c;
		goto warp;
	}
retry:

	c = search_gvha_frame_cache(
			&processed_cache,
			&q,1,c_flag);
	if ( c )
		goto move;
	c = search_gvha_frame_cache(
			&processed_cache,
			&q,0,c_flag);
	if ( c )
		goto change_layer;
	c = search_gvha_frame_cache(
			&processed_cache,
			&q,2,c_flag);
	if ( c == 0 ) {
		c = search_gvha_frame_cache(
			&processed_cache,
			&q,2+4,c_flag);
		if ( c ) {
			c->sts.width = q.win_size.x;
			c->sts.height = q.win_size.y;
			c->sts.flags = SF_WIDTH|SF_HEIGHT;
			wf_set_status(c->gf,&c->sts);
			wf_status(c->gf,&c->sts);
			gvha_flush_pos(c);
			tmp = get_next_target(c,_dir,GVHA_MODE_RSS);
			if ( tmp )
				d_f_ree(tmp);
			c->win_size = q.win_size;
			unlock_frame_lock(c);
			goto retry;
		}
		if ( retry_cnt <= 0 )
			goto busy_err;
		retry_cnt --;
		sleep_sec(1);
		goto retry;
	}
	if ( lock_mv_lock(c) < 0 ) {
		c_flag = 1;
		goto retry;
	}
warp:

ss_printf("POS (%f %f) %f %f\n",
q.pos.center.x,
q.pos.center.y,
q.pos.resolution,
q.pos.rotate);

	flush_pos = 1;
	rc_warp((RADAR_CACHE*)c->gf->radar_ptr,
		WT_CENTER,0,
		&q.pos.center,
		q.pos.resolution,
		q.pos.rotate,
		q.pos.target);
change_layer:

ss_printf("CHANGE LAYER\n");
	if ( lock_mv_lock(c) < 0 ) {
		c_flag = 1;
		goto retry;
	}
	flush_pos = 1;
	change_layer(c,&q);
move:

ss_printf("MOVE\n");
	if ( q.move.x == 0 && q.move.y == 0 )
		goto zoom;

	if ( lock_mv_lock(c) < 0 ) {
		c_flag = 1;
		goto retry;
	}

ss_printf("MOVE-1\n");

	flush_pos = 1;

	to.x = c->win_size.x/2;
	to.y = c->win_size.y/2;
	from.x = q.move.x + to.x;
	from.y = q.move.y + to.y;
	if ( from.x < 0 )
		from.x = 0;
	else if ( from.x >= c->win_size.x )
		from.x = c->win_size.x-1;
	if ( from.y < 0 )
		from.y = 0;
	else if ( from.y >= c->win_size.y )
		from.y = c->win_size.y-1;

	wf_move(c->gf,from,to);

zoom:

ss_printf("ZOOM\n");

	if ( q.zoom == 1 )
		goto finish;
	if ( lock_mv_lock(c) < 0 ) {
		c_flag = 1;
		goto retry;
	}

ss_printf("ZOOM-1\n");

	flush_pos = 1;

	wf_zoom(c->gf,0,q.zoom);
finish:

ss_printf("FINISH\n");
	c_flag = 0;
	if ( q.complete ) {
		complete_lock(c);
		unlock_frame_lock(c);
		c_flag = 1;
		for ( ; ; ) {
			get_rc_loading_status(
				(RADAR_CACHE*)c->gf->radar_ptr,&c->ls.rc);
			wf_free_status(&c->sts);
			sts_load = 1;
			wf_status(c->gf,&c->sts);
			c->ls.wf = c->sts.loading_status;
			loading_status_cal(c);

ss_printf("COMPLETE %i %i\n",c->all,c->ls.wf.dirty);
			if ( c->all == 0 )
				break;

			sleep_sec(1);
		}
	}

	switch ( q.mode ) {
	case GVHA_MODE_MOVE:
ss_printf("MOVE FM = %i\n",c->gf->id);
		rr.tl.x = rr.tl.y = 0;
		rr.br.x = c->win_size.x;
		rr.br.y = c->win_size.y;

		set_redraw_rect(c->gf,&rr);

		if ( ! wf_redraw(c->gf,&gbp,
				0,0,c->win_size.x,c->win_size.y) )
			er_panic("GVHA_MODE_MOVE");
		ret = _gbp2list(&gbp, l_string(std_cm,"jpeg"),80);

		wf_free_plane(&gbp);

		wf_status(c->gf,&c->sts);

ss_printf("MOVE DIRTY = %i\n",c->sts.loading_status.dirty);

		sym = n_get_symbol("image/jpeg");
		set_attribute(sym,
			l_string(std_cm,"Expires"),
			l_string(std_cm,"-1"));
		set_attribute(sym,
			l_string(std_cm,"Cache-Control"),
			l_string(std_cm,"private"));
		ret = List(sym,get_el(ret,3),
			-1);
		break;
	case GVHA_MODE_INFO1:
		wf_free_status(&c->c_sts);
		wf_click(c->gf,&c->c_sts,0,q.move.x,q.move.y);

		get_rc_loading_status(
			(RADAR_CACHE*)c->gf->radar_ptr,&c->ls.rc);
		wf_free_status(&c->sts);
		sts_load = 1;
		wf_status(c->gf,&c->sts);
		c->ls.wf = c->sts.loading_status;
		loading_status_cal(c);

		ret = return_rdf(c,_dir);

		wf_free_status(&c->c_sts);
		break;
	case GVHA_MODE_INFO2:
		err_msg = "info2 unsupport";
		goto invalid_url;
	case GVHA_MODE_RSS:
		get_rc_loading_status(
			(RADAR_CACHE*)c->gf->radar_ptr,&c->ls.rc);
		wf_free_status(&c->sts);
		sts_load = 1;
		wf_status(c->gf,&c->sts);
		c->ls.wf = c->sts.loading_status;
		loading_status_cal(c);

		ret = return_rdf(c,_dir);

ss_printf("RSS FM = %i\n",c->gf->id);

		break;
	default:
		er_panic("xl_GET");
	}

	if ( flush_pos )
		gvha_flush_pos(c);

	if ( sts_load == 0 || flush_pos )
		wf_status(c->gf,&c->sts);
	tmp = get_next_target(c,_dir,GVHA_MODE_RSS);
	if ( tmp )
		d_f_ree(tmp);


	free_gvha_query(&q);
	if ( c_flag )
		complete_unlock(c);
	else	unlock_frame_lock(c);
	return ret;

sys_error:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_FIELD_NAME,
		l_string(std_cm,"gbview/GET"),
		n_get_string("dir attribute is required"));
busy_err:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_BUSY,
		l_string(std_cm,"gbview/GET"),
		n_get_string("home page is BUSY"));
invalid_url:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_FIELD_NAME,
		l_string(std_cm,"gbview/GET"),
		List(n_get_string("invalid URL"),
			n_get_string(err_msg),
			get_integer(rcode,0),-1));
}


XL_SEXP *
_xl_GET_call(
	XLISP_ENV * e,XL_SEXP * s,XLISP_ENV * ae,XL_SYM_FIELD * sf)
{
	return _xl_GET(e,s,ae,sf,0);
}

XL_SEXP *
xl_GET(
	XLISP_ENV * e,XL_SEXP * s,XLISP_ENV * ae,XL_SYM_FIELD * sf)
{
XL_SEXP * sym;
XL_SEXP * xl_Thread();
	sym = n_get_symbol("_GET_call");
	sym->symbol.field = sf;
	s = cons(sym,cdr(s));
	return xl_Thread(e,
		List(n_get_symbol("Thread"),s,-1),
		ae,0);
}

