/**********************************************************************
 
	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	"machine/u_math.h"
#include	"memory_debug.h"
#include	"memory_routine.h"
#include	"task.h"
#include	"lock_level.h"
#include	"resource.h"
#include	"radar.h"
#include	"routing.h"
#include	"avt.h"
#include	"xlerror.h"
#include	"xl.h"
#include	"pri_level.h"
#include	"lump.h"
#include	"win_flame.h"

/*
#define LOG_GET_RADAR_MATRIX
#define LOG_RADAR_STREAM
#define LOG_RADAR_STREAM_2
#define LOG_RADAR_STREAM_3
*/

SEM		radar_lock,query_lock;
XLISP_ENV *	radar_env;
REAL1		resolution_width = WIN_RESO_WINDOW_MAX;
int radar_zonbie_count;

RADAR_CACHE *	radar_cache_list;

int opening_state;
/*
int main_tid;
*/
SYS_QUEUE lump_que_1,lump_que_2;
RADAR_LUMP *	lump_list;

void _clean_radar_matrix(RADAR_CACHE *,Q_THREAD_LIST *);

void _wakeup_win_manage(RADAR_CACHE *);
void wakeup_win_manage(RADAR_CACHE *);
void loading_task(TKEY);
void _wakeup_loading_task(RADAR_CACHE *);
void wakeup_loading_task(RADAR_CACHE *);
void min_route_task(TKEY);
void _wakeup_min_route_task(RADAR_CACHE *);
void wakeup_min_route_task(RADAR_CACHE *);
void win_manage_task(TKEY);
void gc_gb_sexp(XL_SEXP *);
void beam_task(TKEY);
void beam_load_resource_task(TKEY);
void beam_insert_task(TKEY);
void retrieve_lump_task(TKEY);
void retrieve_lump_task_1(TKEY);
void retrieve_lump_task_2(TKEY);
void _flush_radar_crd(RADAR_CRD * c);
void
_free_radar_matrix(RADAR_CACHE * rc_ptr,RADAR_MATRIX * mx);
void
_free_radar_crd(RADAR_CACHE* rc_ptr,RADAR_CRD * c);

void _query_trigger(RADAR_CACHE *,int fn_flag);
void _free_query_thread(RADAR_CACHE * rc_ptr,QUERY_THREAD * qt);

void gc_load_to_beam(T_LOAD_TO_BEAM *);
void gc_load_to_beam_get(T_LOAD_TO_BEAM *);
void gc_beam_to_resource(T_BEAM_TO_RESOURCE *);
void gc_beam_to_resource_get(T_BEAM_TO_RESOURCE *);

XL_SEXP * gv_is_insert_query(XLISP_ENV *,XL_SEXP *,XLISP_ENV *,XL_SYM_FIELD*);
XL_SEXP * gv_is_set_query(XLISP_ENV *,XL_SEXP *,XLISP_ENV *,XL_SYM_FIELD*);
XL_SEXP * gv_is_get_query(XLISP_ENV *,XL_SEXP *,XLISP_ENV *,XL_SYM_FIELD*);
XL_SEXP * gv_is_delete_query(XLISP_ENV *,XL_SEXP *,XLISP_ENV *,XL_SYM_FIELD*);
XL_SEXP * gv_zoom(XLISP_ENV *,XL_SEXP *,XLISP_ENV *,XL_SYM_FIELD*);
XL_SEXP * gv_radar_status(XLISP_ENV *,XL_SEXP *);
RADAR_CRD * _search_radar_crd(RADAR_CACHE*,L_CHAR *,L_CHAR*,int);
REAL1 get_win_rect(GBVIEW_FLAME * gf,GB_RECT * rp);
void radar_event_func(GBVIEW_FLAME * gf,int type,void * sys,void * usr);
void re_lock_base(RADAR_CACHE * rc_ptr);

int lock_pattern[] = {
	TMM_MIN|TMM_TRIG,
	TMM_WMAN|TMM_LOAD|TMM_INS,
	TMM_LOAD|TMM_WMAN|TMM_INS,
	TMM_TRIG|TMM_MIN,
	TMM_REMK,
	TMM_LOAD|TMM_WMAN|TMM_INS,
};

/*
void
_lock_radar_crd(RADAR_CRD * crd,int id)
{
RADAR_CRD_LOCK * lk;
	lk = d_alloc(sizeof(*lk));
	lk->next = crd->_lock;
	crd->_lock = lk;
}

void
_unlock_radar_crd(RADAR_CRD * crd,int id)
{
RADAR_CRD_LOCK ** lkp,* lk;
	for ( lkp = &crd->_lock ; *lkp ; lkp = (*lkp)->next ) {
		lk = *lkp;
		if ( lk->lock_id == id ) {
			*lkp = lk->next;
			d_f_ree(lk);
			return;
		}
	}
	er_panic("_unlock_radar_crd");
}
*/

/*
void
_check_matrix(RADAR_MATRIX * mx)
{
int x,y;
	if ( mx == 0 )
		return;
	if ( mx->resolution < 0 )
		er_panic("matrix(1)");
	if ( mx->loaded_reso < 0 )
		er_panic("check_matrix(1.1)");
	if ( check_fnan(mx->resolution) < 0 )
		er_panic("matrix(20)");
	if ( check_fnan(mx->loaded_reso) < 0 )
		er_panic("matrix(21)");


	if ( mx->rect[0][0].tl.x != mx->rect[0][1].tl.x )
		er_panic("check_matrix(2)");
	if ( mx->rect[0][0].br.x != mx->rect[0][1].br.x )
		er_panic("check_matrix(3)");
	if ( mx->rect[0][0].br.x != mx->rect[1][0].tl.x )
		er_panic("check_matrix(4)");
	if ( mx->rect[0][0].br.x != mx->rect[1][1].tl.x )
		er_panic("check_matrix(5)");
	if ( mx->rect[1][0].br.x != mx->rect[1][1].br.x )
		er_panic("check_matrix(6)");
	if ( mx->rect[0][0].tl.y != mx->rect[1][0].tl.y )
		er_panic("check_matrix(7)");
	if ( mx->rect[0][0].br.y != mx->rect[1][0].br.y )
		er_panic("check_matrix(8)");
	if ( mx->rect[0][0].br.y != mx->rect[0][1].tl.y )
		er_panic("check_matrix(9)");
	if ( mx->rect[0][0].br.y != mx->rect[1][1].tl.y )
		er_panic("check_matrix(10)");
	if ( mx->rect[0][1].br.y != mx->rect[1][1].br.y )
		er_panic("check_matrix(11)");

	for ( x = 0 ; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ ) {
			if ( check_fnan(mx->rect[x][y].tl.x) < 0 )
				er_panic("matrix(22)");
			if ( check_fnan(mx->rect[x][y].tl.y) < 0 )
				er_panic("matrix(23)");
			if ( check_fnan(mx->rect[x][y].br.x) < 0 )
				er_panic("matrix(24)");
			if ( check_fnan(mx->rect[x][y].br.y) < 0 )
				er_panic("matrix(25)");

			if ( mx->mx[x][y] == 0 )
				continue;
			if ( mx->mx[x][y]->parent != mx )
				er_panic("check_matrix(12)");
			_check_matrix(mx->mx[x][y]);
		}
}

void
_x_check_matrix()
{
	if ( rc_ptr->matrix == 0 )
		return;
	if ( rc_ptr->matrix->parent != 0 )
		er_panic("check_matrix(100)");
	_check_matrix(rc_ptr->matrix);
}

void
check_matrix()
{
	lock_task(radar_lock);
	_x_check_matrix();
	unlock_task(radar_lock,"check_matrix");
}



void
check_parent(RADAR_MATRIX * mx)
{
	for ( ; mx ; mx = mx->parent )
		_check_matrix(mx);
}
*/

int
_check_matrix_size(RADAR_MATRIX * mx)
{
int x,y;
int ret;
	if ( mx == 0 )
		return 0;
	ret = 1;
	for ( x = 0; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ )
			ret += _check_matrix_size(mx->mx[x][y]);
	return ret;
}

int
check_matrix_size(RADAR_CACHE * rc_ptr)
{
Q_THREAD_LIST * qt;
int ret;
	ret = 0;
	for ( qt = rc_ptr->q_thread_lst ; qt ; qt = qt->next )
		ret += _check_matrix_size(qt->matrix);
	return ret;
}

void
init_radar()
{
	radar_lock = new_lock(LL_RADAR);
	query_lock = new_lock(LL_RADAR_QUERY);
	lump_list = 0;
	memset(&lump_que_1,0,sizeof(SYS_QUEUE));
	lump_que_1.flags = QF_FIFO;
	lump_que_1.key_func = retrieve_lump_task_1;
	lump_que_1.pri = PRI_FETCH;
	setup_queue(&lump_que_1);

	memset(&lump_que_2,0,sizeof(SYS_QUEUE));
	lump_que_2.flags = QF_FIFO;
	lump_que_2.key_func = retrieve_lump_task_2;
	lump_que_2.pri = PRI_FETCH;
	setup_queue(&lump_que_2);

	radar_env = new_env(gblisp_top_env0);
	set_env(radar_env,l_string(std_cm,"gv-insert-query"),
		get_func_prim(gv_is_insert_query,FO_NORMAL,0,2,2));
	set_env(radar_env,l_string(std_cm,"gv-set-query"),
		get_func_prim(gv_is_set_query,FO_NORMAL,0,2,2));
	set_env(radar_env,l_string(std_cm,"gv-get-query"),
		get_func_prim(gv_is_get_query,FO_APPLICATIVE,0,1,1));
	set_env(radar_env,l_string(std_cm,"gv-delete-query"),
		get_func_prim(gv_is_delete_query,FO_APPLICATIVE,0,2,2));
	set_env(radar_env,l_string(std_cm,"gv-zoom"),
		get_func_prim(gv_zoom,FO_APPLICATIVE,0,2,4));
	set_env(radar_env,l_string(std_cm,"gv-status"),
		get_func_prim(gv_radar_status,FO_APPLICATIVE,0,1,1));

	set_gv_sp_resource(RID_RADAR,radar_env);
	set_env(gblisp_top_env0,l_string(std_cm,"radar"),
		get_env(radar_env));


}

RADAR_CACHE *
new_radar(GBVIEW_FLAME * gf)
{
int i;
RADAR_CACHE * rc_ptr;
int crd_len,ptr_len,res_len;
	lock_task(radar_lock);
	rc_ptr = d_alloc(sizeof(*rc_ptr));
	memset(rc_ptr,0,sizeof(*rc_ptr));
	rc_ptr->win_reso_window = WIN_RESO_WINDOW_MAX;
	rc_ptr->crd = d_alloc(crd_len=sizeof(RADAR_CRD)*RADAR_CACHE_SIZE);
	rc_ptr->ptr = d_alloc(ptr_len=
				sizeof(GB_POINT)*RADAR_CACHE_SIZE*RADAR_RESO_PTR_SIZE);
	rc_ptr->res = d_alloc(res_len=sizeof(REAL1)*RADAR_CACHE_SIZE*RADAR_RESO_PTR_SIZE);
	rc_ptr->free_list = 0;

	memset(rc_ptr->crd,0,crd_len);
	memset(rc_ptr->ptr,0,ptr_len);
	memset(rc_ptr->res,0,res_len);
	for ( i = 1 ; i < RADAR_CACHE_SIZE ; i ++ ) {
		rc_ptr->crd[i].bufid = i;
		rc_ptr->ptr[i].x = rc_ptr->ptr[i].y = 0;
		rc_ptr->res[i] = -1;
		rc_ptr->crd[i].next = rc_ptr->free_list;
		rc_ptr->free_list = &rc_ptr->crd[i];
	}
	rc_ptr->crd[0].bufid = 0;
	rc_ptr->ptr[0].x = rc_ptr->ptr[i].y = 0;
	rc_ptr->res[0] = -1;
	rc_ptr->crd[0].next = rc_ptr->crd[0].prev = &rc_ptr->crd[0];

	rc_ptr->mtx_h.next = rc_ptr->mtx_h.prev = &rc_ptr->mtx_h;

//	rc_ptr->matrix = 0;
	rc_ptr->matrix_count = 0;
	rc_ptr->q_thread_lst = 0;
//	rc_ptr->query = 0;
	rc_ptr->query_mode = 0;
	rc_ptr->load_mode = 0;

	memset(&rc_ptr->load_to_beam,0,sizeof(SYS_QUEUE));
	rc_ptr->load_to_beam.flags = QF_STACK;
	rc_ptr->load_to_beam.gc_func = gc_load_to_beam;
	rc_ptr->load_to_beam.gc_get = gc_load_to_beam_get;
	rc_ptr->load_to_beam.key_func = beam_task;
	rc_ptr->load_to_beam.pri = PRI_FETCH;
	rc_ptr->load_to_beam.work = rc_ptr;
	setup_queue(&rc_ptr->load_to_beam);

	memset(&rc_ptr->beam_to_resource,0,sizeof(SYS_QUEUE));
	rc_ptr->beam_to_resource.flags = QF_STACK;
	rc_ptr->beam_to_resource.key_func = beam_load_resource_task;
	rc_ptr->beam_to_resource.pri = PRI_FETCH;
	rc_ptr->beam_to_resource.gc_func = gc_beam_to_resource;
	rc_ptr->beam_to_resource.gc_get = gc_beam_to_resource_get;
	rc_ptr->beam_to_resource.work = rc_ptr;
	setup_queue(&rc_ptr->beam_to_resource);

	memset(&rc_ptr->resource_to_insert,0,sizeof(SYS_QUEUE));
	rc_ptr->resource_to_insert.flags = QF_STACK|QF_HIGH;
	rc_ptr->resource_to_insert.key_func = beam_insert_task;
	rc_ptr->resource_to_insert.pri = PRI_RADAR_FETCH;
	rc_ptr->resource_to_insert.work = rc_ptr;
	setup_queue(&rc_ptr->resource_to_insert);

	rc_ptr->status = GVFS_IDLE;
	rc_ptr->gf = gf;

	rc_ptr->next = radar_cache_list;
	radar_cache_list = rc_ptr;
	unlock_task(radar_lock,"new_radar");
	return rc_ptr;
}

void
_call_indicate_event(RADAR_CACHE * rc,int change)
{
void (*func)(RADAR_INDICATE *,void *);
void * work;
RADAR_INDICATE ri;

	if ( change == 0 )
		return;
	if ( rc->indicate_event == 0 )
		return;
	func = rc->indicate_event;
	work = rc->indicate_event_work;
	ri = rc->ri;
	unlock_task(radar_lock,"_call_indicate_event");

	(*func)(&ri,work);

	lock_task(radar_lock);
}

void
call_indicate_event(RADAR_CACHE * rc,int change)
{
	_call_indicate_event(rc,change);
	unlock_task(radar_lock,"call_indicate_event");
}

void
_rc_set_indicate_event(
	RADAR_CACHE * rc,
	void (*func)(RADAR_INDICATE*,void*),
	void*work)
{
	if ( rc->status & GVFM_ZONBIE )
		return;
	rc->indicate_event = func;
	rc->indicate_event_work = work;
}

void
rc_set_indicate_event(
	RADAR_CACHE * rc,
	void (*func)(RADAR_INDICATE*,void*),
	void*work)
{
	lock_task(radar_lock);
	_rc_set_indicate_event(rc,func,work);
	unlock_task(radar_lock,"set_indicate_event");
}

int
copy_ri(RADAR_INDICATE * ri1,RADAR_INDICATE * ri2)
{
int i;
int ret;
	ret = 0;
	for ( i = 1 ; i < R_IND_ARY_RES ; i ++ ) {
		if ( ri1->ary[i] != ri2->ary[i] )
			ret = 1;
		ri1->ary[i] = ri2->ary[i];
	}
	return ret;
}


void
_call_condition_event(RADAR_CACHE * rc,QUERY_THREAD * qq)
{
void (*func)(QUERY_THREAD*,void *);
void * work;
QUERY_THREAD * qt;
Q_THREAD_LIST * ql;

	if ( qq == 0 )
		return;
	if ( qq->id == 0 )
		return;
	if ( rc->condition_event == 0 )
		return;
	func = rc->condition_event;
	work = rc->condition_event_work;

	qt = d_alloc(sizeof(*qt));
	qt->next = 0;
	ql = _search_q_thread(rc,qq->id);
	if ( ql ) {
		if ( qq->mask ) {
			memset(qt,0,sizeof(*qt));
			qt->id = qq->id;
			qt->flags = qq->flags;
			qt->mask = qq->mask;
		}
		else	duplicate_q_thread(qt,ql->qth);
	}
	else {
		memset(qt,0,sizeof(*qt));
		qt->id = qq->id;
	}
	unlock_task(radar_lock,"_call_indicate_event");

	(*func)(qt,work);

	lock_task(radar_lock);
	free_query_thread(qt);
}

void
_rc_set_condition_event(
	RADAR_CACHE * rc,
	void (*func)(QUERY_THREAD*,void*),
	void*work)
{
	if ( rc->status & GVFM_ZONBIE )
		return;
	rc->condition_event = func;
	rc->condition_event_work = work;
}

void
rc_set_condition_event(
	RADAR_CACHE * rc,
	void (*func)(QUERY_THREAD*,void*),
	void*work)
{
	lock_task(radar_lock);
	_rc_set_condition_event(rc,func,work);
	unlock_task(radar_lock,"set_indicate_event");
}

void
radar_event_func(GBVIEW_FLAME * gf,int type,void * sys,void * usr)
{
RADAR_CACHE * rc_ptr;
	rc_ptr = (RADAR_CACHE*)usr;
	switch ( type ) {
	case ET_LOCK_BASE:
		re_lock_base(rc_ptr);
		break;
	default:
		er_panic("radar_event_func");
	}
}

void
attach_radar(GBVIEW_FLAME * gf)
{
RADAR_CACHE * rc_ptr;
	rc_ptr = new_radar(gf);
	gf->radar_ptr = rc_ptr;
	gf->radar_event = radar_event_func;
	gf->radar_event_user_arg = rc_ptr;
}


RADAR_CACHE **
_radar_zonbie_tick(RADAR_CACHE ** rp)
{
RADAR_CACHE * r;
int i;
	r = *rp;
	switch ( r->status ) {
	case GVFS_ZONBIE:
		r->indicate_event = 0;
		r->indicate_event_work = 0;
		_free_query_thread_list(r,r->q_thread_lst,0);
//		_free_radar_matrix(r,r->matrix);
		r->q_thread_lst = 0;
		for ( ; r->crd[0].next != &r->crd[0] ; )
			_free_radar_crd(r,r->crd[0].next);
		wakeup_task((int)r->win_manage_task_wp);
		wakeup_task((int)r->loading_task_wp);
		wakeup_task((int)r->min_route_task_wp);
		wakeup_task((int)r->retrieve_task_wp);
		r->status = GVFS_ZONBIE_2;
		break;
	case GVFS_ZONBIE_2:
		for ( i = 0 ; i < R_IND_ARY_LEN ; i ++ )
			if ( r->ri.ary[i] )
				break;
		if ( i < R_IND_ARY_LEN )
			break;
		if ( r->win_manage_task_req ||
				r->win_manage_task_active )
			break;
		if ( r->loading_task_req ||
				r->loading_task_active )
			break;
		if ( r->min_route_task_req ||
				r->min_route_task_active )
			break;


		if ( r->win_manage_task_wp )
			break;;
		if ( r->loading_task_wp )
			break;
		if ( r->min_route_task_wp )
			break;
		if ( r->retrieve_task_wp )
			break;
		if ( get_active_que_thread(&r->load_to_beam) )
			break;
		if ( get_active_que_thread(&r->beam_to_resource) )
			break;
		if ( get_active_que_thread(&r->resource_to_insert) )
			break;
		if ( release_queue(&r->load_to_beam) < 0 )
			break;
		if ( release_queue(&r->beam_to_resource) < 0 )
			break;
		if ( release_queue(&r->resource_to_insert) < 0 )
			break;
//		_free_radar_matrix(r,r->matrix);
		_free_query_thread_list(r,r->q_thread_lst,0);
		r->q_thread_lst = 0;
		for ( ; r->crd[0].next != &r->crd[0] ; )
			_free_radar_crd(r,r->crd[0].next);
		d_f_ree(r->crd);
		d_f_ree(r->ptr);
		d_f_ree(r->res);
		*rp = r->next;
		d_f_ree(r);
		radar_zonbie_count --;
		return rp;
	default:
		break;
	}
	return &r->next;
}

void
radar_zonbie_tick()
{
RADAR_CACHE ** rp;
	lock_task(radar_lock);
	if ( radar_zonbie_count == 0 ) {
		del_tick(radar_zonbie_tick);
		goto end;
	}
	for ( rp = &radar_cache_list ; *rp ; )
		rp = _radar_zonbie_tick(rp);
end:
	unlock_task(radar_lock,"radar_zonbie_tick");
}

void
detach_radar(RADAR_CACHE * rc_ptr)
{
	lock_task(radar_lock);
	if ( (rc_ptr->status & GVFM_ZONBIE) == 0 ) {
		rc_ptr->status = GVFS_ZONBIE;
		radar_zonbie_count ++;
		if ( radar_zonbie_count == 1 )
			new_tick(radar_zonbie_tick,1,0);
	}
	unlock_task(radar_lock,"detach_radar");
}

void
radar_status(RADAR_CACHE * r,int status)
{

	lock_task(radar_lock);
	r->status = status;
	_wakeup_win_manage(r);
	_wakeup_loading_task(r);
	unlock_task(radar_lock,"detach_radar");
}

void
gc_load_to_beam(T_LOAD_TO_BEAM * n)
{
	gc_gb_sexp(n->query);
}

void
gc_beam_to_resource(T_BEAM_TO_RESOURCE * n)
{
	gc_gb_sexp(n->urls);
}

void
gc_load_to_beam_get(T_LOAD_TO_BEAM * n)
{
	lock_mem();
	gc_set_nl(n->query,gc_gb_sexp);
	unlock_mem();
}

void
gc_beam_to_resource_get(T_BEAM_TO_RESOURCE * n)
{
	lock_mem();
	gc_set_nl(n->urls,gc_gb_sexp);
	unlock_mem();
}

void
insert_beam_to_resource(RADAR_CACHE * rc_ptr,XL_SEXP * urls,int qt_id)
{
T_BEAM_TO_RESOURCE * n;
	if ( rc_ptr->status & GVFM_ZONBIE )
		return;
	n = new_queue_node(sizeof(*n));
	n->h.key = nl_copy_str(std_cm,"beam_to_resource");
	n->h.ins = 0;
	n->urls = urls;
	n->qt_id = qt_id;
	rc_ptr->ri.d.beam ++;
	rc_ptr->ri.d.beam_to_resource ++;
	_call_indicate_event(rc_ptr,1);
	insert_queue(&rc_ptr->beam_to_resource,n,0);
}

void
free_load_to_beam(T_LOAD_TO_BEAM * n)
{
void _free_radar_lump();
	if ( n->h.key )
		d_f_ree(n->h.key);
	d_f_ree(n->base_url);
	if ( n->rl )
		_free_radar_lump(n->rl);
	d_f_ree(n);
}

void
free_resource_to_insert(T_RESOURCE_TO_INSERT * n)
{
	if ( n->h.key )
		d_f_ree(n->h.key);
	d_f_ree(n->crd_path);
	d_f_ree(n->obj_path);
	d_f_ree(n);
}

void
gc_radar_cache(RADAR_CACHE * rc_ptr)
{
//	gc_gb_sexp(rc_ptr->query);
}

void
gc_radar()
{
RADAR_CACHE * rc_ptr;
	for ( rc_ptr = radar_cache_list ; rc_ptr ; rc_ptr = rc_ptr->next ) {
		if ( !(rc_ptr->status & GVFS_ACTIVE) )
			continue;
		gc_radar_cache(rc_ptr);
	}
}


void
_wlock_base_url(RADAR_CACHE * rc_ptr,char * msg)
{
int tid;
	tid = get_tid();
	if ( rc_ptr->base_url_lock == 0 )
		goto ok;
	if ( rc_ptr->base_url_lock > 0 )
		goto retry_loop;
	if ( rc_ptr->base_url_lock_task == tid ) {
		rc_ptr->base_url_lock --;
		goto end;
	}
retry_loop:
	for ( ; rc_ptr->base_url_lock ; ) {
		sleep_task((int)&rc_ptr->base_url_lock,radar_lock);
		lock_task(radar_lock);
	}
ok:
	rc_ptr->base_url_lock = -1;
	rc_ptr->base_url_lock_task = tid;
end:	{}
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"BASE_URL W(%i) %s - %i\n",get_tid(),msg,rc_ptr->base_url_lock);
*/
}

void
_rlock_base_url(RADAR_CACHE * rc_ptr,char * msg)
{
	if ( rc_ptr->base_url_lock >= 0 )
		goto end;
	if ( rc_ptr->base_url_lock_task == get_tid() ) {
		_wlock_base_url(rc_ptr,msg);
		return;
	}
	for ( ; rc_ptr->base_url_lock < 0 ; ) {
		sleep_task((int)&rc_ptr->base_url_lock,radar_lock);
		lock_task(radar_lock);
	}
end:
	rc_ptr->base_url_lock ++;
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"BASE_URL R(%i) %s - %i\n",get_tid(),msg,rc_ptr->base_url_lock);
*/
}

void
_unlock_base_url(RADAR_CACHE * rc_ptr)
{

	if ( rc_ptr->base_url_lock > 0 ) {
		rc_ptr->base_url_lock --;
		goto end;
	}
	if ( rc_ptr->base_url_lock < 0 ) {
		if ( rc_ptr->base_url_lock_task != get_tid() )
			er_panic("_unlock_base_url");
		rc_ptr->base_url_lock ++;
		goto end;
	}
	er_panic("_unlock_Base_url(1)");
end:
	if ( rc_ptr->base_url_lock == 0 ) {
		rc_ptr->base_url_lock_task = 0;
		wakeup_task((int)&rc_ptr->base_url_lock);
	}
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"BASE_URL(%i) UNLOCK %i\n",get_tid(),rc_ptr->base_url_lock);
*/
}

void
wlock_base_url(RADAR_CACHE * rc_ptr,char * msg)
{
	lock_task(radar_lock);
	_wlock_base_url(rc_ptr,msg);
	unlock_task(radar_lock,"lock_base_url");
}

void
rlock_base_url(RADAR_CACHE * rc_ptr,char * msg)
{
	lock_task(radar_lock);
	_rlock_base_url(rc_ptr,msg);
	unlock_task(radar_lock,"lock_base_url");
}

void
unlock_base_url(RADAR_CACHE * rc_ptr)
{
	lock_task(radar_lock);
	_unlock_base_url(rc_ptr);
	unlock_task(radar_lock,"unlock_base_url");
}


void
_set_q_mode(RADAR_CACHE * rc_ptr)
{
	for ( ; rc_ptr->query_mode ; ) {
		/* alreay there is another query task */
		sleep_task((int)&rc_ptr->query_mode,query_lock);
		lock_task(query_lock);
	}
	rc_ptr->query_mode = 1;
	for ( ; rc_ptr->load_mode ; ) {
		wakeup_task((int)&rc_ptr->query_mode);
		wakeup_task((int)&rc_ptr->first_max);
		sleep_task((int)&rc_ptr->query_mode,query_lock);
		lock_task(query_lock);
	}
}

void
set_q_mode(RADAR_CACHE * rc_ptr)
{
	lock_task(query_lock);
	_set_q_mode(rc_ptr);
	unlock_task(query_lock,"set_q_mode");
}

void
reset_q_mode(RADAR_CACHE * rc_ptr)
{
	lock_task(query_lock);
	rc_ptr->query_mode = 0;
	wakeup_task((int)&rc_ptr->query_mode);
	unlock_task(query_lock,"reset_q_mode");
}


void
set_l_mode(RADAR_CACHE * rc_ptr)
{
	lock_task(query_lock);
	for ( ; rc_ptr->query_mode ; ) {
		sleep_task((int)&rc_ptr->query_mode,query_lock);
		lock_task(query_lock);
	}
	rc_ptr->load_mode = 1;
	unlock_task(query_lock,"set_l_mode");
}


void
reset_l_mode(RADAR_CACHE * rc_ptr)
{
	lock_task(query_lock);
	rc_ptr->load_mode = 0;
	wakeup_task((int)&rc_ptr->query_mode);
	unlock_task(query_lock,"reset_l_mode");
}

void
_set_opening_state(int state)
{
	if ( opening_state < state )
		opening_state = state;
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"set_opening_state %i %i\n",opening_state,state);
	wakeup_task((int)&opening_state);
}

void
set_opening_state(int state)
{
	lock_task(radar_lock);
	_set_opening_state(state);
	unlock_task(radar_lock,"sethome_opening_state");
}

/* sethomestatus
void
set_opening_state_query()
{
	lock_task(radar_lock);
	if ( main_tid != get_tid() ) {
		for ( ; opening_state < OS_SETHOME_COMPLETE ; ) {
			sleep_task((int)&opening_state,radar_lock);
			lock_task(radar_lock);
		}
		_set_opening_state(OS_RUN);
		wakeup_task((int)&opening_state);
	}
	unlock_task(radar_lock,"sethome_opening_state");
}
*/

void
_insert_radar_crd_ring(RADAR_CACHE * rc_ptr,RADAR_CRD * c)
{
	c->prev = &rc_ptr->crd[0];
	c->next = rc_ptr->crd[0].next;
	c->prev->next = c;
	c->next->prev = c;
}

int
_rc_task_lock_check(RADAR_CACHE * rc_ptr,int t)
{
int lp;


	lp = lock_pattern[t];
	if ( rc_ptr->task_mode&(~lp) )
		return -1;
	return 0;
}

int
rc_task_lock_check(RADAR_CACHE * rc_ptr,int t)
{
int ret;
	lock_task(radar_lock);
	ret = _rc_task_lock_check(rc_ptr,t);
	unlock_task(radar_lock,"rc_task_lock_check");
	return ret;
}

void
_rc_task_lock(RADAR_CACHE * rc_ptr,int t)
{
int lp;

	lp = lock_pattern[t];
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"lock_pattern %x %i\n",rc_ptr->task_mode,t);
*/
	for ( ; rc_ptr->task_mode&(~lp) ; ) {
		sleep_task((int)lock_pattern,radar_lock);
		lock_task(radar_lock);
	}
	rc_ptr->task_mode |= 1<<t;
}

void
rc_task_lock(RADAR_CACHE * rc_ptr,int t)
{
	lock_task(radar_lock);
	_rc_task_lock(rc_ptr,t);
	unlock_task(radar_lock,"rc_task_lock");
}

void
_rc_task_unlock(RADAR_CACHE * rc_ptr,int t)
{
	rc_ptr->task_mode &= ~(1<<t);
	wakeup_task((int)lock_pattern);
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"unlock_pattern %x %i\n",rc_ptr->task_mode,t);
*/
}

void
rc_task_unlock(RADAR_CACHE * rc_ptr,int t)
{
	lock_task(radar_lock);
	_rc_task_unlock(rc_ptr,t);
	unlock_task(radar_lock,"rc_task_unlock");
}



void
_delete_radar_crd_ring(RADAR_CRD * c)
{
	c->prev->next = c->next;
	c->next->prev = c->prev;
}

void
_insert_radar_mtx_ring(RADAR_CACHE * rc_ptr,RADAR_MATRIX * mx)
{
	mx->prev = &rc_ptr->mtx_h;
	mx->next = rc_ptr->mtx_h.next;
	mx->next->prev = mx;
	mx->prev->next = mx;
}

void
_delete_radar_mtx_ring(RADAR_MATRIX * mx)
{
	mx->prev->next = mx->next;
	mx->next->prev = mx->prev;
}

void
_free_query_thread_1(RADAR_CACHE * rc_ptr,QUERY_THREAD * qt)
{
	if ( qt->url )
		d_f_ree(qt->url);
	if ( qt->property )
		d_f_ree(qt->property);
	d_f_ree(qt);


}

void
_free_query_thread(RADAR_CACHE * rc_ptr,QUERY_THREAD * qt)
{
QUERY_THREAD* qt2;
	for ( ; qt ; ) {
		qt2 = qt->next;
		_free_query_thread_1(rc_ptr,qt);
		qt = qt2;
	}
}

void
free_query_thread(QUERY_THREAD * qt)
{
	_free_query_thread(0,qt);
}




void
_free_query_thread_list(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,int one)
{
Q_THREAD_LIST * qt2;
GB_RECT *lr;
	for ( ; qt ; ) {
		qt2 = qt->next;
		if ( rc_ptr )
			_free_radar_matrix(rc_ptr,qt->matrix);
		lr = &qt->large_crd;
		lr->tl.x = lr->tl.y = 0;
		lr->br.x = lr->br.y = -1;
		_free_query_thread(rc_ptr,qt->qth);
		qt = qt2;
		if ( one )
			break;
	}
}


void
free_query_thread_list(Q_THREAD_LIST * qt,int one)
{
	_free_query_thread_list(0,qt,one);
}

int 
q_thread_id_len(int * id_list)
{
int ret;
	for ( ret = 0 ; id_list[ret] ; ret ++ );
	return ret;
}

int *
insert_q_thread_id(int * id_list,int id)
{
int * ret;
int len;
int i;
	if ( id_list ) {
		for ( i = 0 ; id_list[i] ; i ++ )
			if ( id_list[i] == id )
				return id_list;
		len = i;
		ret = d_re_alloc(id_list,(len+2)*sizeof(int));
		ret[len] = id;
		ret[len+1] = 0;
	}
	else {
		ret = d_alloc(2*sizeof(int));
		ret[0] = id;
		ret[1] = 0;
	}
	return ret;
}

Q_THREAD_LIST **
insert_q_thread_list_ptr(Q_THREAD_LIST ** qtl,Q_THREAD_LIST * qt)
{
int i,len;
	if ( qtl ) {
		for ( i = 0 ; qtl[i] ; i ++ )
			if ( qtl[i] == qt )
				return qtl;
		len = i;
		qtl = d_re_alloc(qtl,(len+2)*sizeof(Q_THREAD_LIST*));
		qtl[len] = qt;
		qtl[len+1] = 0;
	}
	else {
		qtl = d_alloc(2*sizeof(Q_THREAD_LIST*));
		qtl[0] = qt;
		qtl[1] = 0;
	}
	return qtl;
}

int q_thread_id;

int
_get_new_id(RADAR_CACHE * rc_ptr)
{
int id;
Q_THREAD_LIST * q;

retry:
	id = q_thread_id + 1;
	if ( id <= 0 )
		id = 1;
	q_thread_id = id;
	for ( q = rc_ptr->q_thread_lst ; q ; q = q->next )
		if ( q->qth->id == id )
			goto retry;
	return id;
}


void
_copy_q_thread(
	QUERY_THREAD * q1,
	QUERY_THREAD * q2)
{


	q1->flags = q2->flags;
	if ( q2->title ) {
		if ( q1->title )
			d_f_ree(q1->title);
		q1->title = ll_copy_str(q2->title);
	}
	if ( q2->url ) {
		if ( q1->url )
			d_f_ree(q1->url);
		q1->url = ll_copy_str(q2->url);
	}
	if ( q2->property ) {
		if ( q1->property )
			d_f_ree(q1->property);
		q1->property = ll_copy_str(q2->property);
	}
	if ( valid_gb_time(&q2->content_period_from) == 0 )
		q1->content_period_from
			= q2->content_period_from;
	if ( valid_gb_time(&q2->content_period_to) == 0 )
		q1->content_period_to
			= q2->content_period_to;
}


QUERY_THREAD *
copy_q_thread(QUERY_THREAD * q)
{
QUERY_THREAD * ret, ** rp, * tmp;
	ret = 0;
	rp = &ret;
	for ( ; q ; q = q->next ) {
		tmp = d_alloc(sizeof(*tmp));
		memset(tmp,0,sizeof(*tmp));
		_copy_q_thread(tmp,q);
		*rp = tmp;
		tmp->next = 0;
		rp = &tmp->next;
	}
	return ret;
}


void
duplicate_q_thread(
	QUERY_THREAD * q1,
	QUERY_THREAD * q2)
{
	memcpy(&q1->id,&q2->id,sizeof(*q1)-sizeof(q1->next));
	if ( q2->title )
		q1->title = ll_copy_str(q2->title);
	if ( q2->url )
		q1->url = ll_copy_str(q2->url);
	if ( q2->property )
		q1->property = ll_copy_str(q2->property);
}

QUERY_THREAD *
_new_q_thread(RADAR_CACHE * rc_ptr,
	QUERY_THREAD * data)
{
Q_THREAD_LIST * q;
QUERY_THREAD * qt;
	for ( q = rc_ptr->q_thread_lst ; q ; q = q->next ) {
		if ( _cmp_q_thread(q->qth,data) == 0 )
			return q->qth;
	}
	q = d_alloc(sizeof(*q));
	memset(q,0,sizeof(*q));
	q->qth = qt = d_alloc(sizeof(*qt));
	memset(qt,0,sizeof(*qt));

	invalid_gb_time(&qt->content_period_from);
	invalid_gb_time(&qt->content_period_to);
	qt->flags = QTF_ACTIVE;

	_copy_q_thread(qt,data);

	qt->id = _get_new_id(rc_ptr);

	q->large_crd.tl.x = q->large_crd.tl.y = 0;
	q->large_crd.br.x = q->large_crd.br.y = -1;

	q->next = rc_ptr->q_thread_lst;
	rc_ptr->q_thread_lst = q;
	return q->qth;
}

int
_delete_q_thread(RADAR_CACHE * rc_ptr,int id)
{
Q_THREAD_LIST ** p,*q;
	for ( p = &rc_ptr->q_thread_lst ; *p ; p = &(*p)->next ) {
		q = *p;
		if ( q->qth->id == id ) {
			*p = q->next;
			q->next = 0;
			_free_query_thread_list(rc_ptr,q,1);
			return 0;
		}
	}
	return -1;
}

int
_cmp_q_thread_string(L_CHAR * a,L_CHAR * b)
{
	if ( a == 0 && b == 0 )
		return 0;
	if ( a == 0 && b )
		return -1;
	if ( a && b == 0 )
		return 1;
	return l_strcmp(a,b);
}

int 
_cmp_q_thread_gb_time(GB_TIME * a1,GB_TIME * a2)
{
int v1,v2;
	v1 = valid_gb_time(a1);
	v2 = valid_gb_time(a2);
	if ( v1 < 0 && v2 < 0 )
		return 0;
	if ( v1 < 0 && v2 == 0 )
		return -1;
	if ( v1 == 0 && v2 < 0 )
		return 1;
	return cmp_gb_time(a1,a2);
}

int
_cmp_q_thread(QUERY_THREAD * q1,QUERY_THREAD * q2)
{
int ret;
	ret = _cmp_q_thread_string(q1->title,q2->title);
	if ( ret )
		return ret;
	ret = _cmp_q_thread_string(q1->url,q2->url);
	if ( ret )
		return ret;
	ret = _cmp_q_thread_string(q1->property,q2->property);
	if ( ret )
		return ret;
	ret = _cmp_q_thread_gb_time(
			&q1->content_period_from,
			&q2->content_period_from);
	if ( ret )
		return ret;
	ret = _cmp_q_thread_gb_time(
			&q1->content_period_to,
			&q2->content_period_to);
	return ret;
}

Q_THREAD_LIST *
_search_q_thread_by_content(RADAR_CACHE * rc_ptr,QUERY_THREAD * q)
{
Q_THREAD_LIST * ret;
	for ( ret = rc_ptr->q_thread_lst ; ret ; ret = ret->next )
		if ( _cmp_q_thread(q,ret->qth) == 0 )
			return ret;
	return 0;
}

Q_THREAD_LIST *
_search_q_thread(RADAR_CACHE * rc_ptr,int id)
{
Q_THREAD_LIST * ret;
	for ( ret = rc_ptr->q_thread_lst ; ret ; ret = ret->next )
		if ( ret->qth->id == id )
			return ret;
	return 0;
}

Q_THREAD_LIST *
search_q_thread(RADAR_CACHE *rc_ptr,int id)
{
Q_THREAD_LIST * ret;
	lock_task(radar_lock);
	ret = _search_q_thread(rc_ptr,id);
	unlock_task(radar_lock,"search_q_thread");
	return ret;
}

int *
_get_valid_qt_id_list(RADAR_CACHE * rc_ptr)
{
int len;
int i;
Q_THREAD_LIST * qt;
int * ret;
	qt = rc_ptr->q_thread_lst;
	for ( len = 0; qt ; qt = qt->next )
		if ( qt->qth->flags & QTF_ACTIVE )
			len ++;
	if ( len ) {
		qt = rc_ptr->q_thread_lst;
		ret = d_alloc((len+1)*sizeof(int));
		for ( i = 0 ; qt ; qt = qt->next )
			if ( qt->qth->flags & QTF_ACTIVE )
				ret[i++] = qt->qth->id;
		ret[i] = 0;
		return ret;
	}
	else	return 0;
}


int *
get_valid_qt_id_list(RADAR_CACHE * rc_ptr)
{
int * ret;
	lock_task(radar_lock);
	ret = _get_valid_qt_id_list(rc_ptr);
	unlock_task(radar_lock,"get_qt_id_list");
	return ret;
}

XL_SEXP *
q_thread_to_sexp_1(QUERY_THREAD * qt,int mode)
{
XL_SEXP * ret;
int cnt;
XL_SEXP * sym;
char from[50];
char to[50];
char buf[100];
XL_SEXP * q;
char * qtype;
	if ( qt->url ) {
		ret = List(n_get_symbol("URL"),
			get_string(qt->url),
			-1);
		qtype = "URL";
	}
	else {
		qtype = "property";
		cnt = 0;
		ret = 0;
		if ( qt->property ) {
			sym = n_get_symbol("qualifier");
			set_attribute(sym,
				l_string(std_cm,"cond"),
				l_string(std_cm,"part"));
			ret = cons(
				List(sym,
					n_get_string(GB_NAMESPACE),
					get_integer(0,0),
					n_get_string("property"),
					0,
					get_string(qt->property),
					-1),
				ret);
		}
		if ( valid_gb_time(&qt->content_period_from) == 0 &&
				valid_gb_time(&qt->content_period_to) == 0 ) {
			gb_time_format(from,&qt->content_period_from);
			gb_time_format(to,&qt->content_period_to);
			sprintf(buf,"%s / %s",from,to);
			sym = n_get_symbol("qualifier");
			set_attribute(sym,
				l_string(std_cm,"cond"),
				l_string(std_cm,"boundary"));
			ret = cons(
				List(sym,
					n_get_string(GB_NAMESPACE),
					get_integer(0,0),
					n_get_string("content.period"),
					n_get_string("W3C-DTF"),
					n_get_string(buf),
					-1),
				ret);
		}
		else if ( valid_gb_time(&qt->content_period_from) == 0 ) {
			gb_time_format(from,&qt->content_period_from);
			sprintf(buf,"%s /",from);
			sym = n_get_symbol("qualifier");
			set_attribute(sym,
				l_string(std_cm,"cond"),
				l_string(std_cm,"boundary"));
			ret = cons(
				List(sym,
					n_get_string(GB_NAMESPACE),
					get_integer(0,0),
					n_get_string("content.period"),
					n_get_string("W3C-DTF"),
					n_get_string(buf),
					-1),
				ret);
		}
		else if ( valid_gb_time(&qt->content_period_to) == 0  ) {
			gb_time_format(to,&qt->content_period_from);
			sprintf(buf,"/ %s",to);
			sym = n_get_symbol("qualifier");
			set_attribute(sym,
				l_string(std_cm,"cond"),
				l_string(std_cm,"boundary"));
			ret = cons(
				List(sym,
					n_get_string(GB_NAMESPACE),
					get_integer(0,0),
					n_get_string("content.period"),
					n_get_string("W3C-DTF"),
					n_get_string(buf),
					-1),
				ret);
		}
		if ( get_type(cdr(ret)) == XLT_NULL )
			ret = car(ret);
		else	ret = cons(n_get_symbol("AND"),ret);
	}
	switch ( mode ) {
	case QTH_MINIMUM_INFO:
		return ret;
	case QTH_MAXIMUM_INFO:
	case QTH_NOID_INFO:
		sprintf(buf,"%i",qt->id);
		q = n_get_symbol("query");
		if ( qt->flags & QTF_ACTIVE )
			set_attribute(q,
				l_string(std_cm,"active"),
				l_string(std_cm,"on"));
		else	set_attribute(q,
				l_string(std_cm,"active"),
				l_string(std_cm,"off"));
		if ( mode != QTH_NOID_INFO )
			set_attribute(q,
				l_string(std_cm,"id"),
				l_string(std_cm,buf));
		if ( qt->title )
			set_attribute(q,
				l_string(std_cm,"title"),
				qt->title);
		set_attribute(q,
			l_string(std_cm,"qtype"),
			l_string(std_cm,qtype));
		return List(q,ret,-1);
	default:
		er_panic("q_thread_to_sexp_1");
		return 0;
	}
}

XL_SEXP *
q_thread_to_sexp(QUERY_THREAD * qt,int mode)
{
XL_SEXP * ret = 0;
	if ( qt == 0 )
		return 0; 
	if ( qt->next == 0 )
		return q_thread_to_sexp_1(qt,mode);
	for ( ; qt ; qt = qt->next ) {
		ret = cons(q_thread_to_sexp_1(qt,mode), ret);
		
	}
	return cons(n_get_symbol("OR"), reverse(ret));
}

RADAR_LUMP *
_search_radar_lump(L_CHAR * lumpcrd_path)
{
RADAR_LUMP * ret;
	for ( ret = lump_list ; ret ; ret = ret->next )
		if ( l_strcmp(ret->lumpcrd_path,lumpcrd_path) == 0 )
			return ret;
	return 0;
}

void
trigger_tick(int d);

void
trigger_tick(int d)
{
RADAR_CACHE * rc_ptr = (RADAR_CACHE*)d;
	query_trigger(rc_ptr,0);
}

void
_insert_radar_lump(RADAR_CACHE * rc_ptr,RADAR_CRD * c,RADAR_LUMP * rl)
{
LUMP_CRD_NODE * n;
	n = d_alloc(sizeof(*n));
	n->crd = c;
	n->lump = rl;
	n->crd_next = c->lump;
	c->lump = n;
	n->lump_next = rl->crd;
	rl->crd = n;

	new_tick(trigger_tick,0,(int)rc_ptr);
}

void
_delete_lump_crd_node_from_lump(RADAR_LUMP * l)
{
LUMP_CRD_NODE * n, ** np;
RADAR_CRD * c;
	for ( ; l->crd ; ) {
		n = l->crd;
		c = n->crd;
		np = &c->lump;
		for ( ; *np && *np != n ; np = &(*np)->crd_next );
		if ( *np == 0 )
			er_panic("_delete_lump_crd_node_form_lump(1)");
		*np = n->crd_next;
		l->crd = n->lump_next;
		d_f_ree(n);
	}
}

void
_free_radar_lump(RADAR_LUMP * l)
{
RADAR_LUMP ** lp;

	for ( lp = &lump_list ; *lp && *lp != l ; lp = &(*lp)->next );
	if ( *lp )
		*lp = l->next;
	d_f_ree(l->db_path);
	d_f_ree(l->lumpcrd_path);
	if ( l->unit )
		d_f_ree(l->unit);
	if ( l->reso_unit )
		d_f_ree(l->reso_unit);
	_delete_lump_crd_node_from_lump(l);
	d_f_ree(l);

}

RADAR_LUMP *
_copy_radar_lump_1(RADAR_LUMP * l)
{
RADAR_LUMP * ll;
	ll = d_alloc(sizeof(*ll));
	memset(ll,0,sizeof(*ll));
	*ll = *l;
	ll->crd = 0;
	ll->db_path = ll_copy_str(l->db_path);
	ll->lumpcrd_path = ll_copy_str(l->lumpcrd_path);
	if ( l->unit )
		ll->unit = ll_copy_str(l->unit);
	else	ll->unit = 0;
	if ( l->reso_unit )
		ll->reso_unit = ll_copy_str(l->reso_unit);
	ll->next = 0;
	return ll;
}

RADAR_LUMP *
_copy_radar_lump(RADAR_LUMP * l)
{
RADAR_LUMP * ret, * ll;
	ret = 0;
	for ( ; l ; l = l->next ) {
		ll = _copy_radar_lump_1(l);
		ll->next = ret;
		ret = ll;
	}
	return ret;
}


void
_delete_lump_crd_node_from_crd(RADAR_CRD * c)
{
LUMP_CRD_NODE * n, ** np;
RADAR_LUMP * l;
	for ( ; c->lump ; ) {


		n = c->lump;
		l = n->lump;
		np = &l->crd;
		for ( ; *np && *np != n ; np = &(*np)->lump_next );
		if ( *np == 0 )
			er_panic("_delete_lump_crd_node_from_crd(1)");

		*np = n->lump_next;
		c->lump = n->crd_next;
		d_f_ree(n);
		if ( l->crd == 0 )
			_free_radar_lump(l);

	}
}

RADAR_LUMP *
_new_radar_lump(L_CHAR * crd,L_CHAR * db)
{
RADAR_LUMP * l;

	l = d_alloc(sizeof(*l));
	l->lumpcrd_path = ll_copy_str(crd);
	l->db_path = ll_copy_str(db);
	l->next = 0;
	l->crd = 0;
	l->unit = 0;
	l->reso_unit = 0;
	return l;
}

int
_insert_radar_lump_list(RADAR_LUMP * l)
{
RADAR_LUMP * ll;
	ll = _search_radar_lump(l->lumpcrd_path);
	if ( ll )
		return -1;
	l->next = lump_list;
	lump_list = l;
	return 0;
}

L_CHAR *
_get_minrect_unit(XL_SEXP * d)
{
L_CHAR * ret;
	switch ( get_type(d) ) {
	case XLT_PAIR:
		for ( ; get_type(d) ; d = cdr(d) ) {
			ret = _get_minrect_unit(car(d));
			if ( ret )
				return ret;
		}
		return _get_minrect_unit(d);
	case XLT_INTEGER:
		return d->integer.unit;
	case XLT_FLOAT:
		return d->floating.unit;
	default:
		return 0;
	}
}

L_CHAR *
get_minrect_unit(XL_SEXP * d)
{
L_CHAR * ret;
	ret = _get_minrect_unit(d);
	if ( ret == 0 )
		return l_string(std_cm,"m");
	return ret;
}


RADAR_LUMP *
setup_radar_lump(int ses,L_CHAR * crd,L_CHAR * db)
{
XL_SEXP * xl_GetElement();
RADAR_LUMP * l;
L_CHAR * db_path;
int len;
XL_SEXP * ret, * sts;
URL u;
XL_SEXP * mr, * v;
int ret_mr;
GB_RECT r;
XL_SEXP * v_min,* v_max;
REAL1 reso_min,reso_max;
L_CHAR  * r_unit;

	l = 0;
	db_path = ll_copy_str(db);
	len = l_strlen(db_path);
	db_path = d_re_alloc(db_path,(len + 10)*sizeof(L_CHAR));
	l_strcpy(&db_path[len],l_string(std_cm,"db.pmd"));
	get_url2(&u,crd);
	if ( u.resource )
		d_f_ree(u.resource);
	u.resource = nl_copy_str(std_cm,"db.pmd");

	gc_push(0,0,"setup_radar_lump");
	sts = List(n_get_symbol("pmd-status"),get_string(db_path),-1);
	ret = remote_session(
		gblisp_top_env0,
		ses,
		&u,
		l_string(std_cm,"gbpmd.get"),
		l_string(std_cm,"user"),
		l_string(std_cm,"Get"),
		List(sts,-1),
		0,0,0,0);
	if ( get_type(ret) == XLT_ERROR )
		goto end;
	get_field(ret,
		l_string(std_cm,"mr"),"sexp",&mr,&ret_mr,
		0);
	if ( ret_mr ) {
		goto end;
	}
	get_minrect(0,&r,mr);
	v = get_el_by_symbol(ret,
			l_string(std_cm,"v"),
			0);
	v_min = get_el(v,1);
	switch ( get_type(v_min) ) {
	case XLT_INTEGER:
		reso_min = v_min->integer.data;
		r_unit = v_min->integer.unit;
		break;
	case XLT_FLOAT:
		reso_min = v_min->floating.data;
		r_unit = v_min->floating.unit;
		break;
	default:
		goto end;
	}
	v_max = get_el(v,2);
	switch ( get_type(v_max) ) {
	case XLT_INTEGER:
		reso_max = v_max->integer.data;
		if ( r_unit == 0 )
			r_unit = v_max->integer.unit;
		break;
	case XLT_FLOAT:
		reso_max = v_max->floating.data;
		if ( r_unit == 0 )
			r_unit = v_max->floating.unit;
		break;
	default:
		goto end;
	}
	l = _new_radar_lump(crd,db_path);
	l->sphere = r;
	l->reso_min = reso_min;
	l->reso_max = reso_max;
	if ( r_unit )
		l->reso_unit = ll_copy_str(r_unit);
	else	l->reso_unit = nl_copy_str(std_cm,"m");
	l->unit = ll_copy_str(get_minrect_unit(mr));
	call_gv_event(RID_RADAR,l_string(std_cm,"insert"));
end:
	gc_pop(0,0);

	free_url(&u);
	d_f_ree(db_path);
	return l;
}

RADAR_CRD * 
_search_crd_path(RADAR_CACHE * rc_ptr,L_CHAR * path)
{
RADAR_CRD * ret;
	for ( ret = rc_ptr->crd[0].next; ret != &rc_ptr->crd[0] ; ret = ret->next ) {
		if ( ret->lump == 0 )
			continue;
		if ( l_strcmp(ret->crd_path,path) == 0 )
			return ret;
	}
	return 0;
}

void
free_t_retrieve(T_RETRIEVE * r)
{
	d_f_ree(r->h.key);
	d_f_ree(r->crd);
	d_f_ree(r->obj);
	free_lr(r->lr);
}

void
_retrieve_lump(RADAR_CACHE * rc_ptr)
{
int nos;
int i;
RADAR_CRD * c, * c1;
URL u;
T_RETRIEVE * rn;
LUMP_CRD_NODE * n;

/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"RETRIEVE LUMP ---- %x\n",rc_ptr);
*/
	for ( nos = 0 ; ; nos ++ ) {
		lock_task(radar_lock);
		c = rc_ptr->crd[0].next;
		for ( i = 0 ; i < nos && c != &rc_ptr->crd[0] ; i ++ )
			c = c->next;
		if ( c == &rc_ptr->crd[0] ) {
			unlock_task(radar_lock,"retrieve_lump");
			break;
		}
		if ( c->lump_handling ) {
			unlock_task(radar_lock,"retrieve_lump");
			continue;
		}
		if ( c->resolution <= 0 ) {
			unlock_task(radar_lock,"retrieve_lump");
			continue;
		}
		if ( c->lump ) {
			unlock_task(radar_lock,"retrieve_lump");
			continue;
		}
		c1 = _search_crd_path(rc_ptr,c->crd_path);
		if ( c1 ) {
			for ( n = c1->lump ; n ; n = n->crd_next )
				_insert_radar_lump(rc_ptr,c,n->lump);
			unlock_task(radar_lock,"retrieve_lump");
			continue;
		}
		c->lump_handling ++;
		rn = d_alloc(sizeof(*rn));
		memset(rn,0,sizeof(*rn));
		rn->crd = ll_copy_str(c->crd_path);
		rn->obj = ll_copy_str(c->obj_path);
		rn->rc_ptr = rc_ptr;

		get_url2(&u,rn->crd);
		rn->h.key = get_server_key(&u,0);
		free_url(&u);

		rc_ptr->ri.d.retrieve1 ++;
		unlock_task(radar_lock,"retrieve_lump");
		insert_queue(&lump_que_1,rn,0);
	}
}


void
retrieve_lump_task_1(TKEY d)
{
int ses;
L_CHAR * key;
SYS_QUEUE * que;
XL_INTERPRETER * xli;
T_RETRIEVE * rn, * rn_1;
XL_SEXP * lmp;
LUMP_ROUTE * lr;
RADAR_CRD * cc;
RADAR_CACHE * rc_ptr;

	que = (SYS_QUEUE*)GET_TKEY(d);
	key = touch_qkey(que);
	if ( key == 0 )
		return;

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

	ses = open_session(SEST_OPTIMIZE);

	rc_ptr = 0;
	for ( ; ; ) {
		gc_push(0,0,"retrieve_lump_task_1");

		lock_task(radar_lock);
		if ( rc_ptr )
			rc_ptr->retrieve_task1_active --;
		unlock_task(radar_lock,"retrieve_lump_task_1");

		rn = delete_queue(que,sq_key_cond,key,0);
		if ( rn == 0 ) {
			gc_pop(0,0);
			break;
		}
		lock_task(radar_lock);
		rc_ptr = rn->rc_ptr;
		rc_ptr->ri.d.retrieve1 --;
		rc_ptr->retrieve_task1_active ++;
		unlock_task(radar_lock,"retrieve_lump_task_1");

		lmp = load_meta(ses,"lump",rn->crd);
		if ( get_type(lmp) == XLT_ERROR ) {
			lock_task(radar_lock);
			cc = _search_radar_crd(rn->rc_ptr,rn->crd,rn->obj,1);
			if ( cc == 0 ) {
				unlock_task(radar_lock,"retrieve");
				goto end0;
			}
			cc->lump_handling --;
			unlock_task(radar_lock,"retrieve");
			goto end0;
		}

		lr = get_lr(0,lmp,0);

	retry:
		lock_task(radar_lock);
		cc = _search_radar_crd(rn->rc_ptr,rn->crd,rn->obj,1);
		if ( cc == 0 ) {
			unlock_task(radar_lock,"retrieve");
			sleep_sec(1);
			goto retry;
		}
		cc->lump_handling --;
		for ( ; lr ; ) {
			rn_1 = d_alloc(sizeof(*rn_1));
			memset(rn_1,0,sizeof(*rn_1));
			rn_1->crd = ll_copy_str(rn->crd);
			rn_1->obj = ll_copy_str(rn->obj);
			rn_1->lr = lr;
			rn_1->rc_ptr = rn->rc_ptr;
			
			lr = lr->next;
			rn_1->lr->next = 0;
			rn_1->h.key = ll_copy_str(rn_1->lr->lump_crd);
			cc->lump_handling ++;

			rn_1->rc_ptr->ri.d.retrieve2 ++;
			insert_queue(&lump_que_2,rn_1,0);
		}
		_flush_radar_crd(cc);
		unlock_task(radar_lock,"retrive1");
	end0:
		free_t_retrieve(rn);
		gc_pop(0,0);
	}
	
	close_session(ses);
	close_self_interpreter();
	release_qkey(que,key);
	d_f_ree(key);
}


void
retrieve_lump_task_2(TKEY d)
{
int ses;
L_CHAR * key;
SYS_QUEUE * que;
XL_INTERPRETER * xli;
int ret_f;
T_RETRIEVE * rn;
XL_SEXP * lmp;
LUMP_ROUTE * lr1, * lr2;
LUMP_OPT opt;
RADAR_LUMP * l;
RADAR_CRD * c;
RADAR_CACHE * rc_ptr;

	que = (SYS_QUEUE*)GET_TKEY(d);
	key = touch_qkey(que);
	if ( key == 0 )
		return;

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

	ses = open_session(SEST_OPTIMIZE);


	rc_ptr = 0;
	for ( ; ; ) {

		gc_push(0,0,"retrieve_lump_task_2");

		lock_task(radar_lock);
		if ( rc_ptr )
			rc_ptr->retrieve_task2_active --;
		unlock_task(radar_lock,"retrieve2");


		rn = delete_queue(que,sq_key_cond,key,0);
		if ( rn == 0 ) {
			gc_pop(0,0);
			break;
		}
		rc_ptr = rn->rc_ptr;

		lr1 = rn->lr;

		ret_f = 0;
		init_lump_opt(&opt);

		lock_task(radar_lock);
		rc_ptr->ri.d.retrieve2 --;
		rc_ptr->retrieve_task2_active ++;

		c = _search_radar_crd(rc_ptr,rn->crd,rn->obj,1);
		l = _search_radar_lump(lr1->lump_crd);
		if ( l ) {
			if ( c == 0 ) {
/*
				free_lump_opt(&opt);
				_free_radar_lump(l);
				unlock_task(radar_lock,"retrieve_lump");
				call_gv_event(RID_RADAR,
					l_string(std_cm,"delete"));
*/
				goto next4;
			}
			goto next1;
		}
		else {
			_flush_radar_crd(c);
			c = 0;
		}
		unlock_task(radar_lock,"retrieve_lump");

		lmp = load_meta(ses,"lump",lr1->lump_crd);
		if ( get_type(lmp) == XLT_ERROR )
			goto next3;
		lr2 = get_lr(&opt,lmp,0);
		free_lr(lr2);
		if ( opt.lump == 0 )
			goto next2;
		l = setup_radar_lump(ses,lr1->lump_crd,opt.lump);
		if ( l == 0 )
			goto next2;
		lock_task(radar_lock);
		c = _search_radar_crd(rc_ptr,rn->crd,rn->obj,1);
		if ( c == 0 ) {
			free_lump_opt(&opt);
			_free_radar_lump(l);
			unlock_task(radar_lock,"retrieve_lump");
			call_gv_event(RID_RADAR,
				l_string(std_cm,"delete"));
			goto next3;
		}
		if ( _insert_radar_lump_list(l) < 0 ) {
			free_lump_opt(&opt);
			_free_radar_lump(l);
			if ( c )
				_flush_radar_crd(c);
			unlock_task(radar_lock,"retrieve_lump");
			call_gv_event(RID_RADAR,
				l_string(std_cm,"delete"));
			goto next3;
		}
		ret_f = 1;
	next1:
		_insert_radar_lump(rc_ptr,c,l);
		_flush_radar_crd(c);
		c = 0;
		unlock_task(radar_lock,"retrieve_lump");
	next2:
		free_lump_opt(&opt);

		if ( ret_f ) {
			_query_trigger(rc_ptr,0);

			lock_task(radar_lock);
			rc_ptr->win_force = 1;
			_wakeup_loading_task(rc_ptr);
			unlock_task(radar_lock,
				"retrieve_lump_task");
		}
	next3:

		lock_task(radar_lock);
	next4:
		c = _search_radar_crd(rc_ptr,rn->crd,rn->obj,1);
		if ( c ) {
			c->lump_handling --;
			_flush_radar_crd(c);
			c = 0;
		}
		unlock_task(radar_lock,
			"retrieve_lump_task");
		free_t_retrieve(rn);
		gc_pop(0,0);
	}
	
	close_session(ses);
	close_self_interpreter();
	release_qkey(que,key);
	d_f_ree(key);
}

void
retrieve_lump(RADAR_CACHE * rc_ptr)
{

	gc_push(0,0,"retrieve");
	_retrieve_lump(rc_ptr);
	gc_pop(0,0);
}

void
retrieve_lump_task(TKEY d)
{
XL_INTERPRETER * xli;
RADAR_CACHE * rc_ptr;

	rc_ptr = (RADAR_CACHE*)GET_TKEY(d);
	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);

	for ( ; ; ) {
		lock_task(radar_lock);
		if ( rc_ptr->retrieve_flag == 0 ) {
			new_timeout((int)&rc_ptr->retrieve_flag,5);
			sleep_task((int)&rc_ptr->retrieve_flag,radar_lock);
			del_timeout((int)&rc_ptr->retrieve_flag);
			lock_task(radar_lock);
			if ( rc_ptr->retrieve_flag == 0 ) {
				rc_ptr->retrieve_task_wp --;
				unlock_task(radar_lock,"retrieve_lump_task");
				break;
			}
		}
		rc_ptr->retrieve_flag = 0;
		unlock_task(radar_lock,"retrieve_lump_task");

		retrieve_lump(rc_ptr);
/*
		if ( retrieve_lump(ses) ) {
			_query_trigger(0);

			lock_task(radar_lock);
			rc_ptr->win_force = 1;
			_wakeup_loading_task();
			unlock_task(radar_lock,"retrieve_lump_task");
		}
*/
	}

	close_self_interpreter();
}

void
_wakeup_retrieve_lump_task(RADAR_CACHE* rc_ptr)
{

	if ( rc_ptr->retrieve_task_wp == 0 ) {
		create_task(retrieve_lump_task,(int)rc_ptr,PRI_FETCH);
		rc_ptr->retrieve_task_wp ++;
	}
	rc_ptr->retrieve_flag = 1;
	wakeup_task((int)&rc_ptr->retrieve_flag);
}


void
wakeup_retrieve_lump_task(RADAR_CACHE* rc_ptr)
{
	lock_task(radar_lock);
	_wakeup_retrieve_lump_task(rc_ptr);
	unlock_task(radar_lock,"wakeup_retrieve_lump_task");
}

void
_delete_turning_loaded_reso(RADAR_MATRIX * mx,REAL1 lr)
{
int x,y;
	if ( mx->loaded_reso < lr )
		mx->loaded_reso = lr;
	for ( x = 0 ; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ ) {
			if ( mx->mx[x][y] == 0 )
				continue;
			_delete_turning_loaded_reso(
				mx->mx[x][y],lr);
		}
}

void
_delete_node_from_crd(RADAR_CRD * c)
{
RADAR_NODE ** np;
RADAR_NODE * n;
	for ( ; c->list ; ) {
		n = c->list;
		c->list = n->crd_next;
		n->matrix->loaded_reso = n->matrix->resolution*2;
		_delete_turning_loaded_reso(n->matrix,
			n->matrix->loaded_reso);
		for ( np = &n->matrix->list ; *np ;
				np = &(*np)->matrix_next )
			if ( *np == n )
				break;
		if ( *np == 0 )
			er_panic("_delete_node_from_crd");
		*np = n->matrix_next;
		d_f_ree(n);
	}
}


void
dump_radar_crd_list(RADAR_CACHE * rc_ptr)
{
RADAR_CRD * c;
	for ( c = rc_ptr->crd[0].next ; c != &rc_ptr->crd[0] ; c = c->next ) {
		if ( c->crd_path )
			log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
				"(%ls) %i\n",
				c->crd_path,
				c->lock);
		else	log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
				"(NONE) %i\n",
				c->lock);
	}
}


RADAR_CRD *
new_radar_crd(RADAR_CACHE* rc_ptr)
{
RADAR_CRD * c1;
int i,p;
	lock_task(radar_lock);
	if ( rc_ptr->free_list == 0 ) {
		c1 = rc_ptr->crd[0].prev;
		for ( ; c1 != &rc_ptr->crd[0] ; c1 = c1->prev ) {
			if ( c1->lock == 0 )
				break;
		}
		if ( c1 == &rc_ptr->crd[0] ) {
			dump_radar_crd_list(rc_ptr);
			sleep_sec(5);
			er_panic("_new_radar_crd");
		}
		_delete_node_from_crd(c1);
		d_f_ree(c1->crd_path);
		d_f_ree(c1->obj_path);
		for ( i = RADAR_RESO_PTR_SIZE , 
				p = RADAR_RESO_PTR_SIZE*c1->bufid ; 
				i > 0 ; i -- , p ++ )
			rc_ptr->res[p] = -1;
		_delete_radar_crd_ring(c1);
		_insert_radar_crd_ring(rc_ptr,c1);
	}
	else {
		c1 = rc_ptr->free_list;
		rc_ptr->free_list = c1->next;
		_insert_radar_crd_ring(rc_ptr,c1);
	}
	c1->crd_path = 0;
	c1->obj_path = 0;
	c1->lock = -1;
	c1->list = 0;
	c1->base_url = 0;
	c1->lump = 0;
	c1->crd_bib = c1->obj_bib = 0;
	c1->crd_r = c1->obj_r = 0;
	c1->lump_handling = 0;
	c1->q_thread_id = 0;
	unlock_task(radar_lock,"new_radar_crd");
	return c1;
}

void
_free_radar_crd(RADAR_CACHE* rc_ptr,RADAR_CRD * c)
{
int i,p;


	if ( c->list )
		er_panic("_free_radar_crd");

	for ( i = RADAR_RESO_PTR_SIZE , 
			p = RADAR_RESO_PTR_SIZE*c->bufid ; 
			i > 0 ; i -- , p ++ )
		rc_ptr->res[p] = -1;

	if ( c->q_thread_id )
		d_f_ree(c->q_thread_id);
	c->q_thread_id = 0;

	c->lock = 0;
	wakeup_task((int)c);
	d_f_ree(c->crd_path);
	d_f_ree(c->obj_path);
	c->crd_path = c->obj_path = 0;

	free_bib_list(c->crd_bib);
	free_bib_list(c->obj_bib);
	c->crd_r = c->obj_r = 0;

	if ( c->base_url )
		d_f_ree(c->base_url);

	c->base_url = 0;

	_delete_lump_crd_node_from_crd(c);

	_delete_radar_crd_ring(c);

	c->next = rc_ptr->free_list;
	rc_ptr->free_list = c;

}

void
_flush_radar_crd(RADAR_CRD * c)
{
	if ( c->lock < 0 ) {
		c->lock = 0;
		wakeup_task((int)c);
	}
	else if ( c->lock > 0 ) {
		c->lock --;
		if ( c->lock == 0 )
			wakeup_task((int)c);
	}
}

void
flush_radar_crd(RADAR_CRD * c)
{
	lock_task(radar_lock);
	_flush_radar_crd(c);
	unlock_task(radar_lock,"flush_radar_crd");
}

int w_cnt;

void
_wait_radar_crd(RADAR_CRD * c)
{
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"WAIT %i %x\n",w_cnt,c);
w_cnt ++;
	for ( ; c->lock < 0 ; ) {
		sleep_task((int)c,radar_lock);
		lock_task(radar_lock);
	}
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"OK %i\n",w_cnt);
w_cnt --;
}


RADAR_CRD *
_search_radar_crd(RADAR_CACHE* rc_ptr,L_CHAR * crd,L_CHAR * obj,int wait_flag)
{
RADAR_CRD * c;
RADAR_CRD * wc;

retry:
	wc = 0;
	if ( obj ) {
		for ( c = rc_ptr->crd[0].next ; c != &rc_ptr->crd[0] ; c = c->next ) {
			if ( c->lock < 0 ) {
				wc = c;
				continue;
			}
			if ( l_strcmp(c->crd_path,crd) == 0 &&
				l_strcmp(c->obj_path,obj) == 0 ) {
				c->lock ++;
				return c;
			}
		}
	}
	else {
		for ( c = rc_ptr->crd[0].next ; c != &rc_ptr->crd[0] ; c = c->next ) {
			if ( c->lock < 0 ) {
				wc = c;
				continue;
			}
			if ( l_strcmp(c->crd_path,crd) == 0  ) {
				c->lock ++;
				return c;
			}
		}
	}
	if ( wait_flag && wc ) {
		_wait_radar_crd(wc);
		goto retry;
	}
	return 0;
}

RADAR_CRD *
search_radar_crd(RADAR_CACHE * rc_ptr,L_CHAR * crd,L_CHAR * obj,int wait_flag)
{
RADAR_CRD * c;
	lock_task(radar_lock);
	c = _search_radar_crd(rc_ptr,crd,obj,wait_flag);
	unlock_task(radar_lock,"search_radar_crd");
	return c;
}

RADAR_MATRIX *
_new_radar_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt)
{
int x,y;
RADAR_MATRIX * ret;

	ret = d_alloc(sizeof(*ret));
	for ( x = 0 ; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ )
			ret->mx[x][y] = 0;
	ret->list = 0;
	ret->parent = 0;
	ret->root_qt = qt;
	_insert_radar_mtx_ring(rc_ptr,ret);
	rc_ptr->matrix_count ++;

	return ret;
}

void
_init_radar_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,GB_RECT * r)
{
RADAR_MATRIX * mx;
int x,y;
REAL1 w,h,radius;
GB_POINT org;

	mx = _new_radar_matrix(rc_ptr,qt);
	w = r->br.x - r->tl.x;
	h = r->br.y - r->tl.y;

	mx->resolution = ((RADAR_DOTS/w + RADAR_DOTS/h)/2)*0.70710678118;
/*
if ( check_fnan(mx->resolution) < 0 )
er_panic("1");
*/
	mx->loaded_reso = mx->resolution*2;

	radius = 2*RADAR_DOTS_RATE*w*h/(w+h);
	org = p_avg(r->tl,r->br);
	org.x -= radius/2;
	org.y -= radius/2;
	for ( x = 0 ; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ ) {
			mx->rect[x][y].tl.x = radius*x + org.x;
			mx->rect[x][y].tl.y = radius*y + org.y;
			mx->rect[x][y].br.x = radius*(x+1) + org.x;
			mx->rect[x][y].br.y = radius*(y+1) + org.y;
			mx->mx[x][y] = 0;
		}
	mx->list = 0;
	qt->matrix = mx;
	mx->parent = 0;
}

void
_check_mx_rect(int x,int y,RADAR_MATRIX *mx)
{
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"MX RECT (%f %f)-(%f %f)\n",
mx->rect[x][y].tl.x,
mx->rect[x][y].tl.y,
mx->rect[x][y].br.x,
mx->rect[x][y].br.y);
if ( check_fnan(mx->rect[x][y].tl.x) < 0 )
er_panic("_init_radar_matrix 1");
if ( check_fnan(mx->rect[x][y].tl.y) < 0 )
er_panic("_init_radar_matrix 2");
if ( mx->rect[x][y].tl.x > mx->rect[x][y].br.x )
er_panic("3");
if ( mx->rect[x][y].tl.y > mx->rect[x][y].br.y )
er_panic("4");
}

void
check_mx_rect(RADAR_MATRIX * mx)
{
	_check_mx_rect(0,0,mx);
	_check_mx_rect(0,1,mx);
	_check_mx_rect(1,0,mx);
	_check_mx_rect(1,1,mx);
}

void
set_mx_rect(RADAR_MATRIX * mx,GB_POINT tl,GB_POINT c,GB_POINT br)
{
GB_RECT * r;
	r = &mx->rect[0][0];
	r->tl = tl;
	r->br = c;
	r = &mx->rect[1][0];
	r->tl.x = c.x;
	r->tl.y = tl.y;
	r->br.x = br.x;
	r->br.y = c.y;
	r = &mx->rect[0][1];
	r->tl.x = tl.x;
	r->tl.y = c.y;
	r->br.x = c.x;
	r->br.y = br.y;
	r = &mx->rect[1][1];
	r->tl = c;
	r->br = br;


}

RADAR_MATRIX *
_new_radar_matrix2(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,REAL1 reso,GB_RECT * r)
{
RADAR_MATRIX * mx;
GB_POINT c;

	c.x = (r->tl.x + r->br.x)/2;
	c.y = (r->tl.y + r->br.y)/2;
	mx = _new_radar_matrix(rc_ptr,qt);
	mx->resolution = 2*reso;
/*
if ( check_fnan(mx->resolution) < 0 )
er_panic("2");
*/
	mx->loaded_reso = mx->resolution*2;


	set_mx_rect(mx,r->tl,c,r->br);
	mx->list = 0;
	return mx;
}

RADAR_MATRIX_LIST *
_new_radar_matrix_list(RADAR_MATRIX * mx)
{
RADAR_MATRIX_LIST * ret;

	ret = d_alloc(sizeof(*ret));
	ret->mx = mx;
	ret->next = 0;
	return ret;
}

void
_free_radar_matrix_list(RADAR_MATRIX_LIST * lst)
{
RADAR_MATRIX_LIST * lst2;
	for ( ; lst ; ) {
		lst2 = lst->next;
		d_f_ree(lst);
		lst = lst2;
	}
}

RADAR_MATRIX_LIST *
append_rml(RADAR_MATRIX_LIST * lst1,RADAR_MATRIX_LIST * lst2)
{
RADAR_MATRIX_LIST * ret;
	if ( lst1 == 0 )
		return lst2;
	ret = lst1;
	for ( ; lst1->next ; lst1 = lst1->next );
	lst1->next = lst2;
	return ret;
}

RADAR_MATRIX_LIST *
__get_radar_matrix(RADAR_CACHE * rc_ptr,
	Q_THREAD_LIST * qtl,
	REAL1 reso,GB_RECT * r,RADAR_MATRIX * mx,
	int insert_flag)
{
int x,y;
RADAR_MATRIX_LIST * lst1, * lst2;
GB_RECT * rr;

#ifdef LOG_GET_RADAR_MATRIX_3
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
"_get_radar_matrix(2)-1 (%f %f)-(%f %f) %f\n",
r->tl.x,
r->tl.y,
r->br.x,
r->br.y,
reso);
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
"_get_radar_matrix(2)-2 (%f %f)-(%f %f) %f\n",
mx->rect[0][0].tl.x,
mx->rect[0][0].tl.y,
mx->rect[1][1].br.x,
mx->rect[1][1].br.y,
mx->resolution);
#endif
	if ( mx == 0 )
		er_panic("__get_radar_matrix(2)"); 
	if ( 2*mx->resolution >= reso )
		return _new_radar_matrix_list(mx);
	lst1 = 0;
	for ( x = 0 ; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ ) {
			rr = &mx->rect[x][y];
			if ( cross_rect_rect(r,rr) == 0 )
				continue;
			if ( mx->mx[x][y] == 0 ) {
				if ( insert_flag == 0 )
					continue;
				mx->mx[x][y] = _new_radar_matrix2(
					rc_ptr,
					qtl,
					mx->resolution,rr);
				mx->mx[x][y]->parent = mx;
			}
			lst2 = __get_radar_matrix(rc_ptr,qtl,reso,r,mx->mx[x][y],insert_flag);
			lst1 = append_rml(lst2,lst1);
		}
	return lst1;
}

void
stepup_radar_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,int xx,int yy)
{
RADAR_MATRIX * mx;
GB_POINT tl,c,br;
GB_POINT rtl,rbr;

	mx = _new_radar_matrix(rc_ptr,qt);
	mx->resolution = qt->matrix->resolution/2;
/*
if ( check_fnan(mx->resolution) < 0 )
er_panic("3");
*/
	mx->loaded_reso = mx->resolution*2;


	rtl = qt->matrix->rect[0][0].tl;
	rbr = qt->matrix->rect[1][1].br;
	if ( xx == 0 && yy == 0 ) {
		tl = rtl;
		c = rbr;
		br.x = 2*c.x - tl.x;
		br.y = 2*c.y - tl.y;
	}
	else if ( xx == 1 && yy == 0 ) {
		tl.x = 2*rtl.x - rbr.x;
		tl.y = rtl.y;
		c.x = rtl.x;
		c.y = rbr.y;
		br.x = rbr.x;
		br.y = 2*rbr.y - rtl.y;
	}
	else if ( xx == 0 && yy == 1 ) {
		tl.x = rtl.x;
		tl.y = 2*rtl.y - rbr.y;
		c.x = rbr.x;
		c.y = rtl.y;
		br.x = 2*rbr.x - rtl.x;
		br.y = rbr.y;
	}
	else {
		tl.x = 2*rtl.x - rbr.x;
		tl.y = 2*rtl.y - rbr.y;
		c = rtl;
		br = rbr;
	}
	set_mx_rect(mx,tl,c,br);
	mx->list = 0;
	mx->mx[xx][yy] = qt->matrix;
	qt->matrix->parent = mx;
	qt->matrix = mx;


	mx->parent = 0;
}

void
including_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,GB_RECT * r)
{
GB_POINT p;
int x,y;


	for ( ; ; ) {
		if ( qt->matrix->rect[0][0].tl.x <= r->tl.x &&
				qt->matrix->rect[0][0].tl.y <= r->tl.y &&
				qt->matrix->rect[1][1].br.x >= r->br.x &&
				qt->matrix->rect[1][1].br.y >= r->br.y )
			break;
		p = qt->matrix->rect[0][0].tl;
		if ( p.x <= r->tl.x )
			x = 0;
		else	x = 1;
		if ( p.y <= r->tl.y )
			y = 0;
		else	y = 1;
		if ( x || y ) {
			stepup_radar_matrix(rc_ptr,qt,x,y);
			continue;
		}
		p = qt->matrix->rect[1][1].br;
		if ( p.x < r->br.x ) {
			stepup_radar_matrix(rc_ptr,qt,0,0);
			continue;
		}
		if ( p.y < r->br.y ) {
			stepup_radar_matrix(rc_ptr,qt,0,0);
			continue;
		}
//		break;
	}
}

RADAR_MATRIX_LIST *
_get_radar_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,REAL1 reso,GB_RECT * r,int insert_flag)
{
RADAR_MATRIX * mx;

#ifdef LOG_GET_RADAR_MATRIX
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
"_get_radar_matrix(%f %f)-(%f %f) %f\n",
r->tl.x,
r->tl.y,
r->br.x,
r->br.y,
reso);
#endif

	if ( reso <= 0 )
		er_panic("_get_radar_matrix(1)");

	if ( qt->matrix == 0 ) {
		_init_radar_matrix(rc_ptr,qt,r);
	}

	including_matrix(rc_ptr,qt,r);
	mx = qt->matrix;

	if ( mx->resolution > reso ) {
		for ( ; qt->matrix->resolution > reso ; )
			stepup_radar_matrix(rc_ptr,qt,0,0);
		return _new_radar_matrix_list(qt->matrix);
	}
	else if ( 2*mx->resolution <= reso ) {
		return __get_radar_matrix(rc_ptr,qt,reso,r,mx,insert_flag);
	}
	else {
		return _new_radar_matrix_list(mx);
	}
}

RADAR_MATRIX_LIST *
_get_radar_matrix_all(RADAR_CACHE * rc_ptr,REAL1 reso,GB_RECT * r,int insert_flag)
{
RADAR_MATRIX_LIST * ret,* l_1;
Q_THREAD_LIST * qt;
	ret = 0;
	for ( qt = rc_ptr->q_thread_lst ; qt ; qt = qt->next ) {
		if ( !( qt->qth->flags & QTF_ACTIVE ) )
			continue;
		l_1 = _get_radar_matrix(rc_ptr,qt,reso,r,insert_flag);
		ret = append_rml(ret,l_1);
	}
	return ret;
}

void
_insert_radar_matrix(RADAR_CACHE * rc_ptr,RADAR_MATRIX * mx,RADAR_CRD * c)
{
RADAR_NODE * n;

	_delete_radar_mtx_ring(mx);
	_insert_radar_mtx_ring(rc_ptr,mx);

	for ( n = mx->list ; n ; n = n->matrix_next )
		if ( n->crd == c )
			return;
	n = d_alloc(sizeof(*n));
	n->matrix = mx;
	n->crd = c;
	n->matrix_next = mx->list;
	mx->list = n;
	n->crd_next = c->list;
	c->list = n;
}

void
get_fitting_line(
		int * fitting_p,
		REAL1 * tl,REAL1 * br,
		REAL1 target_tl,
		REAL1 target_br,
		REAL1 reso,
		REAL1 window_tl,
		REAL1 window_br,
		REAL1 rate)
{
REAL1 len,max;
REAL1 center;
REAL1 ret_tl,ret_br;
	len = target_br - target_tl;
	max = rate * RADAR_RECT_RATE;
	if ( reso * len <= max ) {
		*tl = target_tl;
		*br = target_br;
		return;
	}
	max = max/reso;
	*fitting_p = 1;
	if ( target_br > window_tl && target_tl < window_br ) {
		center = (window_tl + window_br)/2;
		ret_tl = center - max/2;
		ret_br = center + max/2;
		if ( target_tl <= ret_tl &&
				ret_br <= target_br ) {
			*tl = ret_tl;
			*br = ret_br;
			return;
		}
		else if ( target_tl > ret_tl ) {
			*tl = target_tl;
			*br = target_tl + max;
		}
		else {
			*br = target_br;
			*tl = target_br - max;
		}
		return;
	}
	else {
		center = (target_br + target_tl)/2;
		*tl = center - max/2;
		*br = center + max/2;
	}
}

GB_RECT
get_fitting_rect(int * fitting_p,GB_RECT * target,REAL1 reso,RADAR_CACHE * rc_ptr,
			Q_THREAD_LIST * qt)
{
REAL1 wh,wv;
GB_RECT wr;
GB_RECT ret;
REAL1 w_reso;
REAL1 rate;
GB_POINT p1,p2;
REAL1 len;
	*fitting_p = 0;
	if ( qt->matrix ) {
		wr = rc_ptr->win_rect;

		w_reso = get_win_rect(rc_ptr->gf,&wr);

		p2 = p_add(wr.tl,wr.br);

		w_reso = qt->matrix->resolution;
		wr.tl = qt->matrix->rect[0][0].tl;
		wr.br = qt->matrix->rect[1][1].br;

		p1 = p_add(wr.tl,wr.br);
		p1 = p_sub(p2,p1);
		p1.x /= 2;
		p1.y /= 2;

		wr.tl = p_add(wr.tl,p1);
		wr.br = p_add(wr.br,p1);
	}
	else {
		w_reso = get_win_rect(rc_ptr->gf,&wr);
		p1 = p_add(wr.tl,wr.br);
		p1.x /= 2;
		p1.y /= 2;
		len = (wr.br.x - wr.tl.x)*RADAR_DOTS_RATE;
		wr.tl.x = p1.x - len/2;
		wr.br.x = p1.x + len/2;
		len = (wr.br.y - wr.tl.y)*RADAR_DOTS_RATE;
		wr.tl.y = p1.y - len/2;
		wr.br.y = p1.y + len/2;
	}

	wh = wr.br.x - wr.tl.x;
	wv = wr.br.y - wr.tl.y;
	rate = w_reso*(wh+wv)/2;

	get_fitting_line(fitting_p,&ret.tl.x,&ret.br.x,
			target->tl.x,target->br.x,
			reso,
			wr.tl.x,wr.br.x,
			rate);
	get_fitting_line(fitting_p,&ret.tl.y,&ret.br.y,
			target->tl.y,target->br.y,
			reso,
			wr.tl.y,wr.br.y,
			rate);

if ( cross_rect_rect(target,&ret) == 0 )
er_panic("FITTING!!\n");
	return ret;
}

void
insert_radar_matrix(RADAR_CACHE * rc_ptr,int qt_id,RADAR_CRD * c,int lock_flag)
{
int p;
int i;
RADAR_MATRIX_LIST * lst, * lst2;
Q_THREAD_LIST * qt;
GB_RECT ins_r;
int fitting;

	if ( c->resolution <= 0 )
		return; 
	c->minrect.tl.x = c->minrect.tl.y = 0;
	c->minrect.br.x = c->minrect.br.y = -1;
	for ( i = RADAR_RESO_PTR_SIZE, 
			p = RADAR_RESO_PTR_SIZE*c->bufid ; 
			i > 0 ; i -- , p ++ ){
		insert_rect(&c->minrect,rc_ptr->ptr[p]);
	}
/*
	if(_isnan(c->minrect.tl.x) || 
		_isnan(c->minrect.tl.y) ||
		_isnan(c->minrect.br.x) ||
		_isnan(c->minrect.br.y)){
		int debug=1;
		debug++;
	}

	printf("rader AAA %f %f %f %f\n", c->minrect.tl.x,
c->minrect.tl.y,
c->minrect.br.x,
c->minrect.br.y);

log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"irm1 %f (%f %f)-(%f %f)\n",c->resolution,
c->minrect.tl.x,
c->minrect.tl.y,
c->minrect.br.x,
c->minrect.br.y);
*/
	if ( lock_flag )
		lock_task(radar_lock);


	qt = _search_q_thread(rc_ptr,qt_id);
	if ( qt == 0 )
		goto end;
	ins_r = get_fitting_rect(&fitting,&c->minrect,c->resolution,rc_ptr,qt);
	if ( fitting ) {
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"FITTING\n");
		c->flags |= RCF_LARGE_CRD;
		insert_rect(&qt->large_crd,ins_r.tl);
		insert_rect(&qt->large_crd,ins_r.br);
	}
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"irm2 %f (%f %f)-(%f %f) x=%f y=%f rate=(%f %f)\n",
c->resolution,
ins_r.tl.x,
ins_r.tl.y,
ins_r.br.x,
ins_r.br.y,
ins_r.br.x - ins_r.tl.x,
ins_r.br.y - ins_r.tl.y,
c->resolution*(ins_r.br.x - ins_r.tl.x),
c->resolution*(ins_r.br.y - ins_r.tl.y));
if ( rc_ptr->matrix )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"irm2-1 %f (%f %f)-(%f %f) x=%f y=%f rate=(%f %f)\n",
rc_ptr->matrix->resolution,
rc_ptr->matrix->rect[0][0].tl.x,
rc_ptr->matrix->rect[0][0].tl.y,
rc_ptr->matrix->rect[1][1].br.x,
rc_ptr->matrix->rect[1][1].br.y,
rc_ptr->matrix->rect[1][1].br.x - rc_ptr->matrix->rect[0][0].tl.x,
rc_ptr->matrix->rect[1][1].br.y - rc_ptr->matrix->rect[0][0].tl.y,
rc_ptr->matrix->resolution*
	(rc_ptr->matrix->rect[1][1].br.x - rc_ptr->matrix->rect[0][0].tl.x),
rc_ptr->matrix->resolution*
	(rc_ptr->matrix->rect[1][1].br.y - rc_ptr->matrix->rect[0][0].tl.y));
*/

	lst = _get_radar_matrix(rc_ptr,qt,c->resolution,&ins_r,1);

	if ( lst ) {
		for ( lst2 = lst ; lst2 ; lst2 = lst2->next )
			_insert_radar_matrix(rc_ptr,lst2->mx,c);
		_free_radar_matrix_list(lst);
	}
	else {
		sleep_sec(5);
		er_panic("insert_radar_matrix(1)");
		/***/
	}
end:
	if ( lock_flag )
		unlock_task(radar_lock,"insert_radar_matirx");
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"irm3 end\n");
*/
}


void
_free_node_from_matrix(RADAR_MATRIX * mx)
{
RADAR_NODE * n,** np;


	for ( ; mx->list ; ) {
		n = mx->list;
		mx->list = n->matrix_next;
		for ( np = &n->crd->list; *np ; np = &(*np)->crd_next )
			if ( *np == n )
				break;
		if ( *np == 0 )
			er_panic("_free_node_from_matrix");
		*np = n->crd_next;
		d_f_ree(n);
	}
}


void
_free_node_from_matrix2(RADAR_MATRIX * mx)
{
RADAR_NODE * n,** np;

	for ( ; mx->list ; ) {
		n = mx->list;
		mx->list = n->matrix_next;
		for ( np = &n->crd->list; *np ; np = &(*np)->crd_next )
			if ( *np == n )
				break;
		if ( *np == 0 )
			er_panic("_free_node_from_matrix");
		*np = n->crd_next;
		d_f_ree(n);
	}
}
void
_free_radar_matrix(RADAR_CACHE * rc_ptr,RADAR_MATRIX * mx)
{
int x,y;
RADAR_MATRIX * p;
	if ( mx == 0 )
		return;
	for ( x = 0; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ )
			_free_radar_matrix(rc_ptr,mx->mx[x][y]);
	_free_node_from_matrix(mx);
	_delete_radar_mtx_ring(mx);
	rc_ptr->matrix_count --;
	p = mx->parent;
	if ( p ) {
		for ( x = 0 ; x < 2 ; x ++ )
			for ( y = 0 ; y < 2 ; y ++ )
				if ( p->mx[x][y] == mx )
					p->mx[x][y] = 0;
	}
	d_f_ree(mx);
}


void
free_radar_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt)
{
GB_RECT * r;
	lock_task(radar_lock);
	_free_radar_matrix(rc_ptr,qt->matrix);
	qt->matrix = 0;
	r = &qt->large_crd;
	r->tl.x = r->tl.y = 0;
	r->br.x = r->br.y = -1;
	unlock_task(radar_lock,"free_radar_matrix");
}

void
_free_radar_matrix_all(RADAR_CACHE * rc_ptr)
{
Q_THREAD_LIST * qt;
GB_RECT * lr;
	for ( qt = rc_ptr->q_thread_lst ; qt ; qt = qt->next ) {
		_free_radar_matrix(rc_ptr,qt->matrix);
		qt->matrix = 0;
		lr = &qt->large_crd;
		lr->tl.x = lr->tl.y = 0;
		lr->br.x = lr->br.y = -1;
	}
}


void
free_radar_matrix_all(RADAR_CACHE * rc_ptr)
{
	lock_task(radar_lock);
	_free_radar_matrix_all(rc_ptr);
	unlock_task(radar_lock,"free_radar_matrix");
}



void
_clean_top_of_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt)
{
RADAR_MATRIX * mx;
int x,y;
	for ( ; ; ) {
		if ( qt->matrix == 0 )
			return;
		if ( qt->matrix->resolution*2 >= 
				rc_ptr->win_reso_max / rc_ptr->win_reso_window / 2 )
			return;
		mx = 0;
		for ( x = 0 ; x < 2 ; x ++ )
			for ( y = 0 ; y < 2 ; y ++ ) {
				if ( qt->matrix->mx[x][y] ) {
					if ( mx )
						return;
					mx = qt->matrix->mx[x][y];
				}
			}
		_free_node_from_matrix(qt->matrix);
		_delete_radar_mtx_ring(qt->matrix);
		rc_ptr->matrix_count --;
		d_f_ree(qt->matrix);
		qt->matrix = mx;
		mx->parent = 0;
	}
}

int
__clean_radar_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,RADAR_MATRIX * mx)
{
int x,y;
int f;
GB_RECT * r;
	if ( mx == 0 )
		return 0;
	f = 0;
	for ( x = 0 ; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ ) {
			if ( __clean_radar_matrix(rc_ptr,qt,mx->mx[x][y]) == 0 ) {
				mx->mx[x][y] = 0;
			}
			else {
				f = 1;
			}
		}
	if ( f )
		return 1;
	_free_radar_matrix(rc_ptr,mx);
	r = &qt->large_crd;
	r->tl.x = r->tl.y = 0;
	r->br.x = r->br.y = -1;
	return 0;
}

void
_clean_radar_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt)
{
	if ( __clean_radar_matrix(rc_ptr,qt,qt->matrix) == 0 )
		qt->matrix = 0;
	_clean_top_of_matrix(rc_ptr,qt);
}

void
_clean_force_matrix(RADAR_CACHE * rc_ptr,int clear_count)
{
RADAR_MATRIX * mx;
int x,y;
int f;

int loop;

loop = 0;

	for ( mx = rc_ptr->mtx_h.prev ; mx != &rc_ptr->mtx_h && clear_count > 0 ;
				mx = mx->prev , loop ++ ) {
		f = 0;

		for ( x = 0 ; x < 2 ; x ++ )
			for ( y = 0 ; y < 2 ; y ++ )
				if ( mx->mx[x][y] ) {
					f = 1;
					break;
				}
		if ( f )
			continue;
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"clean force %x %f %f %i\n",mx->list,mx->resolution,mx->loaded_reso,loop);
*/
		mx->loaded_reso = mx->resolution*2;

		_free_node_from_matrix(mx);

		clear_count --;

		return;
	}
}

void
clean_radar_matrix(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt)
{
	if ( rc_ptr->matrix_count < 2*RADAR_MATRIX_CACHE_SIZE )
		goto end;
retry:
	_clean_radar_matrix(rc_ptr,qt);
	if ( rc_ptr->matrix_count <= RADAR_MATRIX_CACHE_SIZE )
		goto end;
	_clean_force_matrix(rc_ptr,rc_ptr->matrix_count-RADAR_MATRIX_CACHE_SIZE);
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"retry %i\n",rc_ptr->matrix_count);
if ( rc_ptr->matrix_count > 100 )
er_panic("a\n");
*/
	goto retry;
end:
	{}
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"retry end %i\n",rc_ptr->matrix_count);
*/
}


int
set_ptr_list(RADAR_CACHE * rc_ptr,int ses,RADAR_CRD * c)
{
L_CHAR * url;
MP_ROUTE * mpr;
MAP_HISTORY * mh;
RESOURCE * r, * map_r;
GB_POINT ptr[RADAR_RESO_PTR_SIZE];
REAL1	reso[RADAR_RESO_PTR_SIZE];
int i;
GB_RECT mr;
URL u,u2;
int ret;
int len;
int er;
LOAD_RESOURCE_WORK * w;


	w = 0;
	url = c->crd_path;
	get_url2(&u,url);
	get_url2(&u2,rc_ptr->base_url);
	if ( url_cmp_str(&u,&u2) == 0 ) {

		free_url(&u);
		free_url(&u2);
		mh = 0;
		mpr = 0;
		if ( c->base_url )
			d_f_ree(c->base_url);
		c->base_url = ll_copy_str(rc_ptr->base_url);
		goto same;
	}
	free_url(&u);
	free_url(&u2);
	if ( c->base_url )
		d_f_ree(c->base_url);
	c->base_url = ll_copy_str(rc_ptr->base_url);
	{
	L_CHAR * tmp;
		tmp = ll_copy_str(rc_ptr->base_url);
		mpr = resolve_route(tmp,url,RR_WM_INDIRECT);
		d_f_ree(tmp);
	}
	if ( mpr == 0 || mpr == MP_NO_ROUTE ) {
		ret = -1;
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"NO ROUTE(not found mappath) OR SAME TO BASE CRD\n");
		goto end;
	}
	get_url2(&u,rc_ptr->base_url);
	mh = get_mh_from_route(ses,&u,mpr);
	free_url(&u);
	if ( mh == MP_MH_NO_ROUTE ) {
		ret = -2;
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"NO ROUTE (map resource error)\n");
		goto mp_flush_end;
	}
same:

	len = l_strlen(c->obj_path);
	if ( l_strcmp(&c->obj_path[len-4],l_string(std_cm,".crd")) ) {
		map_r = get_map_between(ses,c->obj_path,c->crd_path);
		if ( map_r == 0 ) {
			ret = -3;
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"OBJECT not belong to base crd.\n");
			goto mp_flush_end;
		}
	}
	else {
		map_r = 0;
	}
	get_url2(&u,c->obj_path);
	w = new_lrw(0);
	get_url2(&w->url,c->crd_path);
	w = new_lrw(w);
	get_url2(&w->url,c->obj_path);
	load_resource_list(w,Q_PRI_RADAR,1);
	r = get_lrw(w,&u);
	if ( r == 0 )
		er_panic("radar");
	free_url(&u);
	if ( r == 0 ) {
		ret = -4;
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"NOT FOUND OBJECT resource\n");
		goto mp_flush_end;
	}
	mr = r->h.minrect;
	if ( r->h.visible_resolution == 0 ||
		mr.br.x - mr.tl.x < 1/r->h.visible_resolution ||
		mr.br.y - mr.tl.y < 1/r->h.visible_resolution ) {

		ret = -5;
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"INCONSISTENT VISIBLE RESOLUTION ERROR %lf\n",
r->h.visible_resolution);
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"(%f %f)-(%f %f)\n",
mr.tl.x,mr.tl.y,
mr.br.x,mr.br.y);
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"%lf %lf - %f\n",
mr.br.x - mr.tl.x,
mr.br.y - mr.tl.y,
1/r->h.visible_resolution);

		goto mp_flush_end;
	}

	ptr[0] = mr.tl;
	ptr[1] = mr.br;
	ptr[2].x = mr.tl.x;
	ptr[2].y = mr.br.y;
	ptr[3].x = mr.br.x;
	ptr[3].y = mr.tl.y;
	ptr[4] = p_add(ptr[0],ptr[2]);
	ptr[4].x = ptr[4].x/2;
	ptr[4].y = ptr[4].y/2;
	ptr[5] = p_add(ptr[0],ptr[3]);
	ptr[5].x = ptr[5].x/2;
	ptr[5].y = ptr[5].y/2;
	ptr[6] = p_add(ptr[1],ptr[2]);
	ptr[6].x = ptr[6].x/2;
	ptr[6].y = ptr[6].y/2;
	ptr[7] = p_add(ptr[1],ptr[3]);
	ptr[7].x = ptr[7].x/2;
	ptr[7].y = ptr[7].y/2;
	for ( i = 0 ; i < RADAR_RESO_PTR_SIZE ; i ++ )
		reso[i] = 1;
	if ( map_r )
		map_conv_forward(map_r,ptr,reso,RADAR_RESO_PTR_SIZE);

	get_url2(&u,c->crd_path);
	r = get_lrw(w,&u);
	if ( r == 0 )
		er_panic("radar");
	free_url(&u);
	if ( r == 0 ) {
		ret = -6;
		goto mp_flush_end;
	}
	for ( i = 0 ; i < RADAR_RESO_PTR_SIZE ; i ++ )
		reso[i] = r->h.visible_resolution;
	{
	L_CHAR * tmp;
		tmp = nl_copy_str(std_cm,"rad^-1");
		reso[RADAR_RESO_PTR_SIZE-1] = conv_unit(&er,
				r->h.cu.uenv,GLOBE_RESO_LIMIT,
				tmp,reso_c_unit(&r->h.cu));
		d_f_ree(tmp);
	}
	if ( mh )
		map_from_resource(mh,ptr,reso,RADAR_RESO_PTR_SIZE);
	for ( i = 0 ; i < RADAR_RESO_PTR_SIZE ; i ++ ) {
		rc_ptr->ptr[c->bufid*RADAR_RESO_PTR_SIZE + i] = ptr[i];
		rc_ptr->res[c->bufid*RADAR_RESO_PTR_SIZE + i] = reso[i];
	}

	free_mh(mh);

log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"RESOLUTION %f\n",reso[0]);
	c->resolution = reso[0];
	c->globe_resolution_limit = reso[RADAR_RESO_PTR_SIZE-1];

	if ( c->resolution == 0 ) {
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"R ERR\n");
		ret = -7;
log_printf(LOG_WARNING,LOG_LAYER_GB,0,"MAPATH RESOLUTION CONVERTION ERROR\n");
		goto mp_flush_end;
	}

	mr.tl.x = mr.tl.y = 0;
	mr.br.x = mr.br.y = -1;
	for ( i = 0 ; i < RADAR_RESO_PTR_SIZE ; i ++ )
		insert_rect(&mr,rc_ptr->ptr[c->bufid*RADAR_RESO_PTR_SIZE+i]);
	c->minrect = mr;
	ret = 0;


mp_flush_end:

	flush_route(mpr);
end:
	free_lrw_req_next(w);

	return ret;
}

int
_insert_radar_url(RADAR_CACHE * rc_ptr,int qt_id,int ses,L_CHAR * crd,L_CHAR * obj)
{
RADAR_CRD * c;
int ret;
RESOURCE * r, * r2;
URL u;
LOAD_RESOURCE_WORK * w;

	w = 0;

	ret = 0;
/*
if ( l_strcmp(crd,obj) == 0 )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"ins_url %s\n",n_string(std_cm,crd));
*/
	rlock_base_url(rc_ptr,"_insert_radar_url");
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"R1\n");
*/
	if ( rc_ptr->base_url == 0 ) {
		ret = -1;
		goto end;
	}
	c = search_radar_crd(rc_ptr,crd,obj,1);

	if ( c ) {
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"reso2 %f (%f %f)-(%f %f)\n",c->resolution,
c->minrect.tl.x,
c->minrect.tl.y,
c->minrect.br.x,
c->minrect.br.y);
*/
		if ( c->resolution <= 0 ) {
			ret = -2;
			goto flush_end;
		}
		insert_radar_matrix(rc_ptr,qt_id,c,1);
		ret = 1;
		goto flush_end;
	}
	c = search_radar_crd(rc_ptr,crd,crd,1);
	if ( c ) {
		if ( c->resolution <= 0 ) {
			ret = -3;
			goto flush_end;
		}
		insert_radar_matrix(rc_ptr,qt_id,c,1);
		ret = 2;
		goto flush_end;
	}
	w = new_lrw(0);
	get_url2(&w->url,crd);
	w = new_lrw(w);
	get_url2(&w->url,obj);
	load_resource_list(w,Q_PRI_RADAR,1);

	get_url2(&u,crd);
	r = get_lrw(w,&u);
	free_url(&u);
	if ( r == 0 ) {
		ret = -4;
		goto flush_end;
	}
	
	get_url2(&u,obj);
	r2 = get_lrw(w,&u);
	free_url(&u);
	if ( r2 == 0 ){
		ret = -5;
		goto flush_end;
	}

	c = new_radar_crd(rc_ptr);
	c->crd_path = ll_copy_str(crd);
	c->obj_path = ll_copy_str(obj);
	c->base_url = ll_copy_str(rc_ptr->base_url);

	c->crd_bib = copy_bib_list(r->h.bib);
	c->obj_bib = copy_bib_list(r2->h.bib);
	c->crd_r = r;
	c->obj_r = r2;
	ret = set_ptr_list(rc_ptr,ses,c);

/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"reso1 %f (%f %f)-(%f %f)\n",c->resolution,
c->minrect.tl.x,
c->minrect.tl.y,
c->minrect.br.x,
c->minrect.br.y);

log_printf(LOG_DEBUG,LOG_LAYER_GB,0,">> %i\n",ret);
*/

	if ( ret >= 0 )
		insert_radar_matrix(rc_ptr,qt_id,c,1);
	else {
		ret = -6;
		c->resolution = 0;
	}

flush_end:


	if ( c )
	  flush_radar_crd(c);
end:


	free_lrw_req_next(w);

	if ( ret >= 0 ) {
		rc_ptr->win_load = 1;
		wakeup_win_manage(rc_ptr);
	}
	unlock_base_url(rc_ptr);
	return ret;
}




int
remake_cache(RADAR_CACHE * rc_ptr,int ses,int type,WF_ID current,WF_ID next)
#define RCT_CHANGE	1
#define RCT_DELETE	2
{
MAP_HISTORY * mh;
MP_ROUTE * mpr;
RADAR_CRD * c;
RADAR_NODE * rn;
URL u;
L_CHAR * new;
RESOURCE *draw;
int i,j;
WF_ID wfid;

#ifdef GET_RADAR_MATRIX
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"REMAKE CACHE NEXT %i\n",next);
#endif

	wfid = wf_get_current(rc_ptr->gf);
	if ( next == 0 ) {
		if ( current ) {
			wf_set_current_now(rc_ptr->gf,current);
			rc_ptr->base_change_flag = 1;
		}
	}
	else {
		wf_set_current_target(rc_ptr->gf,next);
		rc_ptr->base_change_flag = 1;
	}

	switch ( type ) {
	case RCT_CHANGE:
		if ( next && wfid == next )
			return 0;
		break;
	case RCT_DELETE:
		if ( rc_ptr->win_delete_lock == 0 &&
				wf_check_last(rc_ptr->gf,current) == 0 )
			free_win_flame(rc_ptr->gf,current);
		else return 0;
		wf_wait_stable(rc_ptr->gf);
		break;
	default:
		er_panic("remake_cache");
	}
	wfid = wf_get_current(rc_ptr->gf);
	draw = wf_get_resource(rc_ptr->gf,wfid);


	wlock_base_url(rc_ptr,"remake_cache");

	if ( draw == 0 ) {
		lock_task(radar_lock);
		if ( rc_ptr->base_url )
			d_f_ree(rc_ptr->base_url);
		rc_ptr->base_url = 0;
		_free_radar_matrix_all(rc_ptr);
		for ( ; rc_ptr->crd[0].next != &rc_ptr->crd[0] ; ) {
			c = rc_ptr->crd[0].next;
			_free_radar_crd(rc_ptr,c);
		}

		unlock_task(radar_lock,"remake");

		goto last;
	}
	new = ll_copy_str(get_url_str2(&draw->h.entry));


	if ( rc_ptr->base_url == 0 ) {

		free_radar_matrix_all(rc_ptr);
		rc_ptr->base_url = ll_copy_str(new);
		goto end;
	}
	if ( l_strcmp(rc_ptr->base_url,new) == 0 ) {
		goto end;
	}

	{
	L_CHAR * tmp;
		tmp = ll_copy_str(rc_ptr->base_url);
		mpr = resolve_route(tmp,new,RR_WM_INDIRECT);
		d_f_ree(tmp);
	}
	if ( mpr == 0 || mpr == MP_NO_ROUTE )
		goto end;
	get_url2(&u,rc_ptr->base_url);

	mh = get_mh_from_route(ses,&u,mpr);


	free_url(&u);
	if ( mh == MP_MH_NO_ROUTE )
		goto end_flush;
	for ( i = 0; i < RADAR_CACHE_SIZE ; i ++ ) {
		c = &rc_ptr->crd[i];
		if ( c->q_thread_id )
			d_f_ree(c->q_thread_id);
		c->q_thread_id = 0;
	}
	for ( c = rc_ptr->crd[0].next ; c != &rc_ptr->crd[0] ; c = c->next ) {
		for ( rn = c->list ; rn ; rn = rn->crd_next )
			c->q_thread_id = insert_q_thread_id(c->q_thread_id,
						rn->matrix->root_qt->qth->id);
		if ( c->list == 0 )
			continue;
		if ( c->globe_resolution_limit )
			rc_ptr->res[c->bufid*RADAR_RESO_PTR_SIZE+(RADAR_RESO_PTR_SIZE-1)]
				= c->globe_resolution_limit;
	}




	free_radar_matrix_all(rc_ptr);

	map_from_flame(mh,rc_ptr->ptr,rc_ptr->res,RADAR_CACHE_SIZE*RADAR_RESO_PTR_SIZE);


	for ( c = rc_ptr->crd[0].next ; c != &rc_ptr->crd[0] ; c = c->next ) {
		c->resolution = rc_ptr->res[c->bufid*RADAR_RESO_PTR_SIZE];

		c->minrect.tl.x = c->minrect.tl.y = 0;
		c->minrect.br.x = c->minrect.br.y = -1;
		for ( j = 0 ; j < RADAR_RESO_PTR_SIZE ; j ++ )
			insert_rect(&c->minrect,rc_ptr->ptr[c->bufid*RADAR_RESO_PTR_SIZE+j]);
		if ( c->globe_resolution_limit )
			c->globe_resolution_limit = rc_ptr->res[c->bufid*RADAR_RESO_PTR_SIZE+
							(RADAR_RESO_PTR_SIZE-1)];
/*
		c->lock = 0;
*/
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"RMAKE LOCK COUNT = %i\n",c->lock);
*/

		if ( c->base_url )
			d_f_ree(c->base_url);
		c->base_url = 0;
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"ins %s\n",n_string(std_cm,c->obj_path));
*/
		if ( c->q_thread_id )
			for ( i = 0 ; c->q_thread_id[i] ; i ++ )
				insert_radar_matrix(rc_ptr,c->q_thread_id[i],c,1);
	}

/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"REMAKE %ls --> ",rc_ptr->base_url);
*/
	d_f_ree(rc_ptr->base_url);
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"%ls\n",new);
*/
	rc_ptr->base_url = ll_copy_str(new);

end_flush:
	flush_route(mpr);
end:
	d_f_ree(new);
last:
	unlock_base_url(rc_ptr);
	{}


	return 1;
}


int
cmp_wf_crd(CRD_LIST * c1,CRD_LIST * c2)
{
L_CHAR * fp1, * fp2;
RESOURCE * draw;
	if ( c1->crd )
		fp1 = c1->crd->crd_path;
	else {
		draw = wf_get_resource(c1->rc_ptr->gf,c1->wfid);
		if ( draw )
			fp1 = get_url_str2(&draw->h.entry);
		else	fp1 = l_string(std_cm,"");
	}
	if ( c2->crd )
		fp2 = c2->crd->crd_path;
	else {
		draw = wf_get_resource(c2->rc_ptr->gf,c2->wfid);
		if ( draw )
		 	fp2 = get_url_str2(&draw->h.entry);
		else	fp2 = l_string(std_cm,"");
	}
	return l_strcmp(fp1,fp2);
}

AVT_NODE *
get_wf_tree(RADAR_CACHE * rc_ptr)
{
AVT_NODE * ret;
AVT_NODE * a;
CRD_LIST * cl;
unsigned int t;
GBVIEW_STATUS gb_sts;
GBVIEW_LAYER_STATUS * ls;
	wf_status(rc_ptr->gf,&gb_sts);
	ret = 0;
	t = get_xltime();
	for ( ls = gb_sts.layers ; ls ; ls = ls->next ) {
		cl = d_alloc(sizeof(*cl));
		a = d_alloc(sizeof(*a));
		cl->rc_ptr = rc_ptr;
		cl->wfid = ls->id;
		cl->crd = 0;
		if ( ls->flags & WFF_BASE_LOCK )
			cl->base_lock = 1;
		else	cl->base_lock = 0;
		if ( t - wf_insert_time(rc_ptr->gf,ls->id) > 10 )
			cl->sts = CLS_REMOVE;
		else	cl->sts = CLS_KEEP;
		a->data = cl;
		avt_insert(&ret,a,cmp_wf_crd);
	}
	return ret;
}

typedef struct keep_work {
	REAL1		sum_surf;
} KEEP_WORK;

int keep_check(AVT_NODE * a,KEEP_WORK * w);
int _cmp_cache_wf(
	RADAR_CACHE * rc_ptr,
	AVT_NODE ** tree,RADAR_MATRIX_LIST * lst,REAL1 reso,
	GB_RECT * r,KEEP_WORK * kw);
void free_reso_tree(AVT_NODE * a);

int
keep_check(AVT_NODE * a,KEEP_WORK * w)
{
CRD_LIST * cl;
RESOURCE * res;
	cl = a->data;
#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"KEEP %ls %f %i\n",cl->crd->crd_path,w->sum_surf,cl->sts);
#endif
	if ( cl->crd == 0 )
		return 0;
	if ( w->sum_surf > WIN_SURF_RATE_MIN ) {
		switch ( cl->sts ) {
		case CLS_KEEP:
			cl->sts = CLS_REMOVE;
			break;
		case CLS_REMOVE:
			break;
		case CLS_INSERT:
			cl->sts = CLS_NONE;
			break;
		}
#ifdef LOG_RADAR_STREAM
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"KEEP SET %i\n",cl->sts);
#endif
	}
	else {
		res = cl->crd->crd_r;
#ifdef LOG_RADAR_STREAM
if ( res && res->h.type == RT_COORDINATE )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"WEIGHT %ls %f\n",get_url_str2(&res->h.entry),res->c.weight);
#endif
		if ( res == 0 )
			w->sum_surf += 1;
		else if ( res->h.type == RT_COORDINATE )
			w->sum_surf += res->c.weight;
		else	w->sum_surf += 1;
	}
	return 0;
}

int
cmp_reso_sort(CRD_LIST * c1,CRD_LIST * c2)
{
	if ( c1->crd->resolution < c2->crd->resolution )
		return -1;
	if ( c1->crd->resolution > c2->crd->resolution )
		return 1;
	return l_strcmp(c1->crd->crd_path,c2->crd->crd_path);
}

int
reso_sort(AVT_NODE * a,AVT_NODE ** tree)
{
AVT_NODE * a1;
CRD_LIST * cl;
	cl = a->data;
	if ( cl->crd == 0 )
		return 0;
	a1 = d_alloc(sizeof(*a1));
	a1->data = cl;
	avt_insert(tree,a1,cmp_reso_sort);
	return 0;
}

void
free_reso_tree(AVT_NODE * a)
{
	if ( a == 0 )
		return;
	free_reso_tree(a->small);
	free_reso_tree(a->large);
	d_f_ree(a);
}

int
_cmp_cache_wf(
	RADAR_CACHE * rc_ptr,
	AVT_NODE ** tree,RADAR_MATRIX_LIST * lst,REAL1 reso,
	GB_RECT * r,KEEP_WORK * kw)
{
RADAR_NODE * n;
RADAR_CRD * c;
AVT_NODE * a;
CRD_LIST cl,* clp;
AVT_NODE * reso_tree;

	for ( ; lst ; lst = lst->next ) {
		_delete_radar_mtx_ring(lst->mx);
		_insert_radar_mtx_ring(rc_ptr,lst->mx);
		for ( n = lst->mx->list ; n ; n = n->matrix_next ) {
#ifdef LOG_RADAR_STREAM_2
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"MX (%f %f)-(%f %f)\n",
lst->mx->rect[0][0].tl.x,
lst->mx->rect[0][0].tl.y,
lst->mx->rect[1][1].br.x,
lst->mx->rect[1][1].br.y
);
#endif
			c = n->crd;
			if ( c->lock < 0 )
				continue;
#ifdef LOG_RADAR_STREAM_2
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"CMP BEFOR %ls %lf\n",c->crd_path,(double)c->resolution);
#endif

			if ( cross_rect_rect(&c->minrect,r) == 0 )
				continue;

			if ( c->resolution > reso )
				continue;
			if ( c->crd_r && (c->crd_r->h.flags & RF_INDICATE) == RF_I_OFF )
				continue;
			c->lock ++;

#ifdef LOG_RADAR_STREAM_2
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"CMP CACHE %ls %lf\n",c->crd_path,(double)c->resolution);

log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"MINRECT (%f %f) = (%f %f)\n",
c->minrect.tl.x,
c->minrect.tl.y,
c->minrect.br.x,
c->minrect.br.y);
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"RECT (%f %f) = (%f %f)\n",
r->tl.x,
r->tl.y,
r->br.x,
r->br.y);
#endif

			cl.rc_ptr = rc_ptr;
			cl.wfid = 0;
			cl.crd = c;
			cl.sts = 0;
			a = avt_search(*tree,&cl,cmp_wf_crd);
			if ( a ) {
				clp = a->data;
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"EXIST %i\n",clp->sts);
*/
				if ( clp->crd == 0 ) {
					clp = a->data;
					clp->crd = c;
					clp->sts = CLS_KEEP;
				}
				else _flush_radar_crd(c);
			}
			else {
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"NOT EXIST\n");
*/
				clp = d_alloc(sizeof(*clp));
				memset(clp,0,sizeof(*clp));
				clp->rc_ptr = rc_ptr;
				clp->wfid = 0;
				clp->crd = c;
				clp->sts = CLS_INSERT;
				a = d_alloc(sizeof(*a));
				a->data = clp;
				avt_insert(tree,a,cmp_wf_crd);
			}
		}
	}
	kw->sum_surf = 0;
	reso_tree = 0;
	avt_trace_from_small(*tree,reso_sort,&reso_tree);
	avt_trace_from_large(reso_tree,keep_check,kw);
	free_reso_tree(reso_tree);
	if ( kw->sum_surf > WIN_SURF_RATE_MIN )
		return -1;
	return 0;
}

RADAR_MATRIX_LIST * 
get_parent(RADAR_MATRIX_LIST * lst)
{
RADAR_MATRIX_LIST * ret, * lst1;
RADAR_MATRIX * mx;
	ret = 0;

	for ( ; lst ; lst = lst->next ) {
		mx = lst->mx->parent;
		if ( mx == 0 )
			continue;
		for ( lst1 = ret ; lst1 ; lst1 = lst1->next ) {
			if ( lst1->mx == mx )
				break;
		}
		if ( lst1 == 0 ) {
			lst1 = _new_radar_matrix_list(mx);
			lst1->next = ret;
			ret = lst1;
		}
	}
	return ret;
}

void
_free_wf_tree(AVT_NODE * tree)
{
CRD_LIST * c;
	if ( tree == 0 )
		return;
	_free_wf_tree(tree->small);
	_free_wf_tree(tree->large);
	c = tree->data;
	if ( c->crd )
		_flush_radar_crd(c->crd);
	d_f_ree(tree->data);
	d_f_ree(tree);
}


typedef struct win_insert_work {
	int		ses;
	REAL1		reso;
	URL		u;
	WF_ID	 	wfid;
	int		ret;
	REAL1		reso_min;
	RADAR_CACHE * 	rc_ptr;
} WIN_INSERT_WORK;

int win_insert_func(AVT_NODE * a,WIN_INSERT_WORK * w);
int win_delete_func(AVT_NODE * a,WIN_INSERT_WORK * w);

int
win_insert_func(AVT_NODE * a,WIN_INSERT_WORK * w)
{
CRD_LIST * cl;
WF_ID wfid;
URL u;
RESOURCE * r;
GB_POINT center;
MAP_HISTORY * mh;
MP_ROUTE * mpr;

	cl = a->data;
#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"WIF ok %ls - %i\n",cl->crd->crd_path,cl->sts);
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"WIF *  %x\n",cl);
#endif

	switch ( cl->sts ) {
	case CLS_INSERT:
		if ( cl->crd )
			if ( w->reso_min == -1 || 
					w->reso_min > cl->crd->resolution )
				w->reso_min = cl->crd->resolution; 
		break;
	case CLS_KEEP:
		if ( cl->crd )
			if ( w->reso_min == -1 || 
					w->reso_min > cl->crd->resolution )
				w->reso_min = cl->crd->resolution;
		return 0;
	default:
		return 0;
	}


	get_url2(&u,cl->crd->crd_path);

	r = load_resource(w->ses,&u,Q_PRI_RADAR);
	free_url(&u);
	{
	L_CHAR * tmp;
		tmp = ll_copy_str(w->rc_ptr->base_url);
		mpr = resolve_route(tmp,cl->crd->crd_path,RR_WM_INDIRECT);
		d_f_ree(tmp);
	}
	if ( mpr == MP_NO_ROUTE )
		goto end_flush2;
	if ( mpr == 0 )
		goto end_flush;
	mh = get_mh_from_route(w->ses,&w->u,mpr);
	if ( mh == MP_MH_NO_ROUTE )
		goto end_flush;
	center.x = center.y = 0;
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"+++++++++++++++++++ insert %ls\n",cl->crd->crd_path);
	new_win_flame(
		&wfid,
		w->rc_ptr->gf,
		cl->crd->resolution,
		r,
		mh,
		center,
		0,
		w->reso);
	lock_task(radar_lock);
	w->rc_ptr->delete_insert_flag = 1;
	unlock_task(radar_lock,"insert");
	free_mh(mh);
	w->rc_ptr->win_delete_lock = 0;
end_flush:
	flush_route(mpr);
end_flush2:

	return 0;
}

int
win_delete_func(AVT_NODE * a,WIN_INSERT_WORK * w)
{
CRD_LIST * cl;
	cl = a->data;
#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"DEL ok %ls - %i\n",cl->crd->crd_path,cl->sts);
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"DEL *  %x - %i\n",cl,w->rc_ptr->win_delete_lock);
#endif
	if ( cl->sts != CLS_REMOVE )
		return 0;
	if ( cl->wfid == w->wfid ) {
		w->ret = 1;
		return 0;
	}
	if ( w->rc_ptr->win_delete_lock )
		return 0;
	if ( wf_check_last(w->rc_ptr->gf,cl->wfid) == 0 ) {
#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"DEL-EXE ok %ls - %i\n",cl->crd->crd_path,cl->sts);
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"DEL-EXE *  %x\n",cl);
#endif
		free_win_flame(w->rc_ptr->gf,cl->wfid);
		lock_task(radar_lock);
		w->rc_ptr->delete_insert_flag = 1;
		unlock_task(radar_lock,"win_delete_func");
	}
	return 0;
}


int
free_crd_lock(AVT_NODE * a)
{
CRD_LIST * cl;
	cl = a->data;
	if ( cl->crd == 0 )
		return 0;
	_flush_radar_crd(cl->crd);
	return 0;
}


typedef struct h_same_meta_work {
	CRD_LIST *	target;
	AVT_NODE *	wf_tree;
} H_SAME_META_WORK;

int h_same_meta_func2(AVT_NODE * a,H_SAME_META_WORK * w);
int h_same_meta_func(AVT_NODE * a,H_SAME_META_WORK * w);
void h_search_same_meta(AVT_NODE * wf_tree);

int
h_same_meta_func2(AVT_NODE * a,H_SAME_META_WORK * w)
{
CRD_LIST * cl;
	cl = a->data;

#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"SAME META %ls - %i\n",cl->crd->crd_path,cl->sts);
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"SAME META  %x\n",cl);
#endif


	if ( cl == w->target )
		return 1;
	if ( cl->sts == CLS_NONE ||
			cl->sts == CLS_REMOVE )
		return 0;
	if ( cl->crd == 0 )
		return 0;
	if ( cmp_bib_list(cl->crd->crd_bib,w->target->crd->crd_bib) )
		goto ok;
	if ( cmp_bib_list(cl->crd->obj_bib,w->target->crd->obj_bib) )
		goto ok;

	if ( cl->wfid && w->target->wfid ) {
		cl->sts = CLS_REMOVE;
		cl->crd = 0;
	}
	else if ( cl->wfid ) {
		w->target->sts = CLS_NONE;
		w->target->crd = 0;
		return 1;
	}
	else if ( w->target->wfid ) {
		cl->sts = CLS_NONE;
		cl->crd = 0;
	}
	else {
		cl->sts = CLS_NONE;
		cl->crd = 0;
	}
ok:
	return 0;
}

int
h_same_meta_func(AVT_NODE * a,H_SAME_META_WORK * w)
{
	w->target = a->data;
	if ( w->target->sts == CLS_NONE ||
			w->target->sts == CLS_REMOVE )
		return 0;
	if ( w->target->crd == 0 )
		return 0;
	if ( w->target->crd->crd_bib == 0 &&
		w->target->crd->obj_bib == 0 ) {
		if ( w->target->wfid ) {
			w->target->sts = CLS_REMOVE;
			w->target->crd = 0;
		}
		else {
			w->target->sts = CLS_NONE;
			w->target->crd = 0;
		}
		return 0;
	}
/*
	avt_trace_from_large(w->wf_tree,h_same_meta_func2,w);
*/
	return 0;
}

void
h_search_same_meta(AVT_NODE * wf_tree)
{
H_SAME_META_WORK w;
	w.wf_tree = wf_tree;
	avt_trace_from_small(wf_tree,h_same_meta_func,&w);
}

typedef struct h_relation_work {
	CRD_LIST *	target;
	AVT_NODE *	wf_tree;
	L_CHAR *	ms;
} H_RELATION_WORK;

int h_relation_master(AVT_NODE * a,H_RELATION_WORK * w);
int h_relation_slave(AVT_NODE * a,H_RELATION_WORK * w);
int h_relation_func(AVT_NODE * a,H_RELATION_WORK * w);
void h_search_relation(AVT_NODE * wf_tree);



int
h_relation_master(AVT_NODE * a,H_RELATION_WORK * w)
{
CRD_LIST * cl;
	cl = a->data;
#ifdef LOG_RADAR_STREAM
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"REL %x %x\n",cl,cl->crd);
#endif

	if ( cl == w->target )
		return 0;
	if ( cl->sts == CLS_NONE ||
			cl->sts == CLS_REMOVE )
		return 0;
	if ( cl->crd == 0 )
		return 0;

	if ( l_strcmp(cl->crd->crd_path,w->ms) )
		return 0;

	if ( w->target->wfid ) {
		w->target->sts = CLS_REMOVE;
		return 1;
	}
	w->target->sts = CLS_NONE;
	return 1;
}


int
h_relation_slave(AVT_NODE * a,H_RELATION_WORK * w)
{
CRD_LIST * cl;
	cl = a->data;
	if ( cl == w->target )
		return 0;
	if ( cl->sts == CLS_NONE ||
			cl->sts == CLS_REMOVE )
		return 0;
	if ( cl->crd == 0 )
		return 0;

	if ( l_strcmp(cl->crd->crd_path,w->ms) )
		return 0;

	if ( cl->wfid ) {
		cl->sts = CLS_REMOVE;
		return 1;
	}
	cl->sts = CLS_NONE;
	return 1;
}


int
h_relation_func(AVT_NODE * a,H_RELATION_WORK * w)
{
	w->target = a->data;
	if ( w->target->sts == CLS_NONE ||
			w->target->sts == CLS_REMOVE )
		return 0;
	if ( w->target->crd == 0 )
		return 0;
	if ( w->target->crd->crd_r->c.relation_master ) {
		w->ms = w->target->crd->crd_r->c.relation_master;
		avt_trace_from_large(w->wf_tree,h_relation_master,w);
		return 0;
	}
	if ( w->target->crd->crd_r->c.relation_slave ) {
		w->ms = w->target->crd->crd_r->c.relation_slave;
		avt_trace_from_large(w->wf_tree,h_relation_slave,w);
		return 0;
	}
	return 0;
}

void
h_search_relation(AVT_NODE * wf_tree)
{
H_RELATION_WORK w;
	w.wf_tree = wf_tree;
	avt_trace_from_small(wf_tree,h_relation_func,&w);
}


int
h_limit_reso_func(AVT_NODE * a,HEURISTICS_PARAM * w)
{
CRD_LIST * cl;
RESOURCE * r;
REAL1 reso,r_width;
REAL1 lrr;

	cl = a->data;

#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"LIM %ls - %i\n",cl->crd->crd_path,cl->sts);
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"LIM  %x\n",cl);
#endif


	if ( cl->sts == CLS_NONE ||
			cl->sts == CLS_REMOVE )
		return 0;
	if ( cl->crd == 0 )
		return 0;
	r = cl->crd->crd_r;
#ifdef LOG_RADAR_STREAM
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"= %f %f\n",r->h.limit_resolution,r->h.visible_resolution);
#endif

	if ( r->h.limit_resolution == 0 )
		return 0;
	if ( r->c.flags & CF_FIX_LIMIT_RESO )
		lrr = 1;
	else	lrr = LIMIT_RESOLUTION_RATE;
	if ( r->h.visible_resolution*lrr > 
			r->h.limit_resolution )
		reso = r->h.visible_resolution*lrr;
	else 	reso = r->h.limit_resolution;
	r_width = r->h.visible_resolution
			/r->h.limit_resolution
			*lrr;
	if ( resolution_width < r_width )
		resolution_width = r_width;

	reso = cl->crd->resolution * reso / r->h.visible_resolution;
/*
ss_printf("CRD 2 %ls - %f\n",cl->crd->crd_path,reso);
*/

	if ( reso*lrr >= w->base_resolution )
		return 0;

#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"REL %ls - %i - %i %f %f\n",cl->crd->crd_path,cl->sts,cl->wfid,reso*lrr,w->base_resolution);
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"REL  %x\n",cl);
#endif
	if ( cl->wfid == 0 )
		cl->sts = CLS_NONE;
	else	
		cl->sts = CLS_REMOVE;
/*
ss_printf("CRD 1 %ls - %i\n",cl->crd->crd_path,cl->sts);
*/
	return 0;
}

void
h_search_limit_resolution(AVT_NODE * wf_tree,
	HEURISTICS_PARAM * p)
{
	avt_trace_from_small(wf_tree,h_limit_reso_func,p);
}

void
heuristics_search(AVT_NODE * wf_tree,HEURISTICS_PARAM * p)
{

	h_search_limit_resolution(wf_tree,p);
	h_search_same_meta(wf_tree);
	h_search_relation(wf_tree);
}


typedef struct base_pri_work {
	GB_RECT 	r;
	CRD_LIST * 	cl;
	REAL1		resolution;
	double		bpri;
	double		max_reso;
	double		min_reso;
	int		change_on;
	WF_ID		wfid;
	int		globe_flag;
} BASE_PRI_WORK;

int win_base_reso_cal(AVT_NODE * a,BASE_PRI_WORK * w);
int win_base_pri(AVT_NODE * a,BASE_PRI_WORK * w);

int
win_base_reso_cal(AVT_NODE * a,BASE_PRI_WORK * w)
{
CRD_LIST * cl;
double v_rate,h_rate,bpri,d,reso;
double v,h;
GB_RECT * mr;

	cl = a->data;
#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"BCAL ok %ls - %i\n",cl->crd->crd_path,cl->sts);
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"BCAL *  %x\n",cl);
#endif
	switch ( cl->sts ) {
	case CLS_NONE:
	case CLS_REMOVE:
		return 0;
	case CLS_KEEP:
	case CLS_INSERT:
		break;
	}
	if ( cl->crd == 0 )
		return 0;
/*
		er_panic("win_base_pri");
*/
	if ( cl->crd->crd_r ) {
		if ( (cl->crd->crd_r->c.geometory_type & GT_T_MASK) == GT_T_GLOBE_SUR && 
				cl->crd->globe_resolution_limit > w->resolution ) {
			w->globe_flag = 1;
		}
	}
	mr = &cl->crd->minrect;
	d = v_rate = h_rate = reso = h = v = 0;
	if ( cross_rect_rect(mr,&w->r) == 0 ) {
		bpri = 0x7fffffff;
		goto end;
	}
	h_rate = (mr->br.x - mr->tl.x) / (h = w->r.br.x - w->r.tl.x);
	v_rate = (mr->br.y - mr->tl.y) / (v = w->r.br.y - w->r.tl.y);

	if ( h_rate < 1 || v_rate < 1 ) {
		bpri = 0x7fffffff;
		goto end;
	}

	if ( w->max_reso == 0 || w->max_reso < cl->crd->resolution )
		w->max_reso = cl->crd->resolution;
	if ( w->min_reso == 0 || w->min_reso > cl->crd->resolution )
		w->min_reso = cl->crd->resolution;

end:
	return 0;
}

int
win_base_pri(AVT_NODE * a,BASE_PRI_WORK * w)
{
CRD_LIST * cl;
double v_rate,h_rate,bpri,d,reso;
double v,h;
GB_RECT * mr;
GB_POINT c;
int adj;

#define ADJ_W 100
#define RESO_W	200

	cl = a->data;
#ifdef LOG_RADAR_STREAM
if ( cl->crd )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"BPRI ok %ls - %i\n",cl->crd->crd_path,cl->sts);
else
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"BPRI *  %x\n",cl);
#endif
	switch ( cl->sts ) {
	case CLS_NONE:
		return 0;
	case CLS_REMOVE:
		if ( cl->wfid == w->wfid )
			w->change_on = 1;
		return 0;
	case CLS_KEEP:
	case CLS_INSERT:
		break;
	}
	if ( cl->crd == 0 )
		return 0;
/*
		er_panic("win_base_pri");
*/
	if ( w->globe_flag &&
			(cl->crd->crd_r->c.geometory_type & GT_T_MASK) != GT_T_GLOBE_SUR ) {
		bpri = 0x7fffffff;
		if ( cl->wfid == w->wfid )
			w->change_on = 2;
		goto end;
	}
	mr = &cl->crd->minrect;
	d = v_rate = h_rate = reso = h = v = 0;
	if ( cross_rect_rect(mr,&w->r) == 0 ) {
		bpri = RESO_W;
		if ( cl->wfid == w->wfid )
			w->change_on = 2;
		goto end;
	}
	h_rate = (mr->br.x - mr->tl.x) / (h = w->r.br.x - w->r.tl.x);
	v_rate = (mr->br.y - mr->tl.y) / (v = w->r.br.y - w->r.tl.y);

	if ( h_rate < 1 || v_rate < 1 ) {
		bpri = RESO_W;
		if ( cl->wfid == w->wfid )
			w->change_on = 3;
		goto end;
	}


	c = p_sub(p_add(mr->br,mr->tl),p_add(w->r.br,w->r.tl));

#ifdef LOG_RADAR_STREAM
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"B+ %lf %lf\n",c.x,c.y);
#endif
	if ( c.x < 0 )
		c.x = - c.x;
	if ( c.y < 0 )
		c.y = - c.y;

	d = (c.x/h + c.y/v)/2;
	if ( w->max_reso == w->min_reso )
		reso = 0;
	else	reso = RESO_W*(w->max_reso - cl->crd->resolution)
				/(w->max_reso - w->min_reso);
	bpri = reso + d;

	if ( cl->wfid ) {
		bpri += ADJ_W*(adj = get_wf_priadj(
					cl->rc_ptr->gf,cl->wfid));
#ifdef LOG_RADAR_STREAM
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"BBB %i %i - %i\n",cl->wfid,w->wfid,adj);
#endif
		if ( adj && cl->wfid == w->wfid )
			w->change_on = 4;
	}
end:
#ifdef LOG_RADAR_STREAM
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"B %ls %lf - %lf %lf %lf %lf %i\n",
cl->crd->crd_path,bpri,
reso,d,h,v,adj);


log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"                     B %ls\n",
cl->crd->crd_path,bpri,
reso,d,h,v,adj);
#endif
	if ( cl->wfid && w->bpri > bpri ) {
		w->cl = cl;
		w->bpri = bpri;
	}
	return 0;
}

int
win_detect_base_lock(AVT_NODE * a,BASE_PRI_WORK * w);

int
win_detect_base_lock(AVT_NODE * a,BASE_PRI_WORK * w)
{
CRD_LIST * cl;
	cl = a->data;
	if ( cl->base_lock == 0 )
		return 0;
	if ( cl->sts == CLS_KEEP || cl->sts == CLS_INSERT )
		w->cl = cl;
	return -1;
}

void
_dump_the_matrix(RADAR_MATRIX * mx,int level,GB_RECT * r)
{
int i,j;
RADAR_NODE * n;
RADAR_CRD * c;
GB_RECT mx_r;
	if ( mx == 0 )
		return;
	mx_r.tl = mx->rect[0][0].tl;
	mx_r.br = mx->rect[1][1].br;
	log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
		"  %i reso(%f)loaded_reso(%f),(%f %f)(%f %f)-%i\n",
			level,
			mx->resolution,
			mx->loaded_reso,
			mx->rect[0][0].tl.x,
			mx->rect[0][0].tl.y,
			mx->rect[1][1].br.x,
			mx->rect[1][1].br.y,
			cross_rect_rect(&mx_r,r));
	for ( n = mx->list ; n ; n = n->matrix_next ) {
		c = n->crd;
		log_printf(LOG_DEBUG,LOG_LAYER_GB,0,
			"    %ls(%f)--(%f %f)(%f %f)-%i\n",
			c->crd_path,
			c->resolution,
			c->minrect.tl.x,
			c->minrect.tl.y,
			c->minrect.br.x,
			c->minrect.br.y,
			cross_rect_rect(&c->minrect,r));
	}
	for ( i = 0 ; i < 2 ; i ++ )
		for ( j = 0 ; j < 2 ; j ++ )
			_dump_the_matrix(mx->mx[i][j],level+1,r);
}

void
dump_the_matrix_qt(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,GB_RECT * r)
{
	log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"  QT qt_id = %i\n",qt->qth->id);
	_dump_the_matrix(qt->matrix,0,r);
	log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"  QT END\n");
}


void
dump_the_matrix(RADAR_CACHE * rc_ptr,GB_RECT * r)
{
Q_THREAD_LIST * qtl;
	log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"DUMP THE MATRIX\n");
	for ( qtl = rc_ptr->q_thread_lst ; qtl ; qtl = qtl->next )
		dump_the_matrix_qt(rc_ptr,qtl,r);
	log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"DUMP THE MATRIX END\n");
}


void
_fitting_check(RADAR_CACHE * rc_ptr,Q_THREAD_LIST * qt,GB_RECT * r)
{
GB_RECT * large_crd;
RADAR_CRD * crd;

/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"Ftting_check--------------\n");
*/
	large_crd = &qt->large_crd;
	if ( large_crd->tl.x > large_crd->br.x )
		return;
	if ( large_crd->tl.x <= r->tl.x &&
		large_crd->br.x >= r->tl.x &&
		large_crd->tl.x <= r->br.x &&
		large_crd->br.x >= r->br.x &&
		large_crd->tl.y <= r->tl.y &&
		large_crd->br.y >= r->tl.y &&
		large_crd->tl.y <= r->br.y &&
		large_crd->br.y >= r->br.y ) {

		return;
	}
	else {
		large_crd->tl.x = large_crd->tl.y = 0;
		large_crd->br.x = large_crd->br.y = -1;
		crd = rc_ptr->crd[0].next;
		for ( ; crd != &rc_ptr->crd[0] ; crd = crd->next )
			if ( (crd->flags & RCF_LARGE_CRD) &&
					crd->list ) {
				insert_radar_matrix(rc_ptr,qt->qth->id,crd,0);
			}
	}
}

void
_fitting_check_all(RADAR_CACHE * rc_ptr,GB_RECT * r)
{
Q_THREAD_LIST * qt;
	for (qt = rc_ptr->q_thread_lst ; qt ; qt = qt->next ) {
		_fitting_check(rc_ptr,qt,r);
	}
}


REAL1
_get_qt_min_reso(RADAR_CACHE * rc_ptr)
{
Q_THREAD_LIST * qt;
REAL1 ret;
	ret = 0;
	for ( qt = rc_ptr->q_thread_lst ; qt ; qt = qt->next ) {
		if ( qt->matrix == 0 )
			continue;
		if ( ret == 0 ) {
			ret = qt->matrix->resolution;
			continue;
		}
		if ( qt->matrix->resolution < ret )
			ret = qt->matrix->resolution;
	}
	return ret;
}

/***/
WF_ID
win_manage(RADAR_CACHE * rc_ptr,WF_ID * next,int ses,REAL1 reso,GB_RECT * r)
{
RADAR_MATRIX_LIST * lst1;
AVT_NODE * wf_tree;
WIN_INSERT_WORK w;
KEEP_WORK kw;
HEURISTICS_PARAM hw;
BASE_PRI_WORK bw;
REAL1 _reso;
REAL1 min_reso;


	if ( rc_ptr == 0 )
		return 0;
	lock_task(radar_lock);


#ifdef LOG_RADAR_STREAM_2

log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"\n");
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"WIN_MANAGE (%f %f)(%f %f) %f - %ls (%i)\n",
r->tl.x,
r->tl.y,
r->br.x,
r->br.y,
reso,
rc_ptr->base_url,
rc_ptr->matrix_count
);
dump_the_matrix(rc_ptr,r);

#endif

	_rlock_base_url(rc_ptr,"win_manage");

retry:
	if ( rc_ptr->base_url == 0 ) {
		_unlock_base_url(rc_ptr);
		unlock_task(radar_lock,"win_manage(1)");
		return 0;
	}
	
	wf_tree = get_wf_tree(rc_ptr);
	_fitting_check_all(rc_ptr,r);
	_reso = reso;
	for ( ; ; ) {
		lst1 = _get_radar_matrix_all(rc_ptr,_reso,r,0);
		if ( _cmp_cache_wf(rc_ptr,&wf_tree,lst1,reso,r,&kw) < 0 ) {
			_free_radar_matrix_list(lst1);
			break;
		}
		_free_radar_matrix_list(lst1);
		_reso *= 0.5;
		min_reso = _get_qt_min_reso(rc_ptr);
		if ( min_reso <= 0 )
			break;
		if ( min_reso > _reso )
			break;
	}
	
#ifdef LOG_RADAR_STREAM_2
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"========================= %f\n",_reso);
#endif
	if ( rc_ptr->win_reso_window < resolution_width &&
			kw.sum_surf < WIN_SURF_RATE_MIN ) {
		avt_trace_from_small(wf_tree,free_crd_lock,0);
		_free_wf_tree(wf_tree);
		rc_ptr->win_reso_window *= 4;
		rc_ptr->win_reso_max = reso;
		rc_ptr->win_rect = *r;
		rc_ptr->win_force = 1;
		goto retry;
	}
	else if ( rc_ptr->win_reso_window > WIN_RESO_WINDOW_MIN &&
			kw.sum_surf > WIN_SURF_RATE_MAX )
		rc_ptr->win_reso_window /= 2;


	unlock_task(radar_lock,"win_manage(1)");

	hw.ses = ses;
	hw.base_resolution = reso;
	heuristics_search(wf_tree,&hw);
	w.rc_ptr = rc_ptr;
	w.ses = ses;
	w.reso = reso;
	w.wfid = wf_get_current(rc_ptr->gf);
	w.ret = 0;
	w.reso_min = -1;
	get_url2(&w.u,rc_ptr->base_url);

	avt_trace_from_small(wf_tree,win_insert_func,&w);
	avt_trace_from_small(wf_tree,win_delete_func,&w);

	free_url(&w.u);

	bw.cl = 0;
	avt_trace_from_small(wf_tree,win_detect_base_lock,&bw);
	if ( bw.cl == 0 ) {
		bw.r = *r;
		bw.resolution = reso;
		bw.globe_flag = 0;
		bw.bpri = 0x7fffffff;
		bw.cl = 0;
		bw.max_reso = bw.min_reso = 0;
		bw.change_on = 0;
		bw.wfid = w.wfid;
#ifdef LOG_RADAR_STREAM
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"BB %f %f - %f %f\n",
bw.r.tl.x,
bw.r.tl.y,
bw.r.br.x,
bw.r.br.y
);
#endif
		avt_trace_from_small(wf_tree,win_base_reso_cal,&bw);
		avt_trace_from_small(wf_tree,win_base_pri,&bw);
#ifdef LOG_RADAR_STREAM
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"BB - %x %i\n",bw.cl,bw.change_on);
#endif
	}
	if ( bw.cl == 0 )
		*next = 0;
	else if ( bw.cl->wfid == w.wfid )
		*next = 0;
	else	*next = bw.cl->wfid;
#ifdef LOG_RADAR_STREAM
if ( bw.cl )
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"NEXT %ls\n",bw.cl->crd->crd_path);
#endif

	lock_task(radar_lock);
	avt_trace_from_small(wf_tree,free_crd_lock,0);


	_free_wf_tree(wf_tree);
	unlock_task(radar_lock,"win_manage(3)");

	lock_task(radar_lock);

	_unlock_base_url(rc_ptr);
#ifdef LOG_RADRA_STREAM
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"WIN_MANAGE END\n");
#endif
	rc_ptr->win_reso_max = reso;
	rc_ptr->win_rect = *r;
	unlock_task(radar_lock,"win_manage");
	if ( w.ret )
		return w.wfid;
	else	return 0;
}

int
in_condition(RADAR_CACHE * rc_ptr,GB_RECT * r,REAL1 window,REAL1 max)
{
	if ( r->tl.x != rc_ptr->win_rect.tl.x )
		return -1;
	if ( r->tl.y != rc_ptr->win_rect.tl.y )
		return -1;
	if ( r->br.x != rc_ptr->win_rect.br.x )
		return -1;
	if ( r->br.y != rc_ptr->win_rect.br.y )
		return -1;
	if ( window != rc_ptr->win_reso_window )
		return -1;
	if ( max != rc_ptr->win_reso_max )
		return -1;
	return 0;
}



void
_empty_radar_matrix(RADAR_MATRIX * mx,int fn_flag)
{
int x,y;


	if ( mx == 0 )
		return;
	if ( fn_flag )
		_free_node_from_matrix(mx);
	mx->loaded_reso = mx->resolution*2;


	for ( x = 0 ; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ )
			_empty_radar_matrix(mx->mx[x][y],fn_flag);
}

void
_empty_radar_matrix_in_query(RADAR_CACHE * rc_ptr,int fn_flag)
{
Q_THREAD_LIST * qt;
	for ( qt = rc_ptr->q_thread_lst ; qt ; qt = qt->next )
		_empty_radar_matrix(qt->matrix,fn_flag);
}


XL_SEXP *
gv_radar_status(XLISP_ENV * env,XL_SEXP * s)
{
XL_SEXP * ret;
RADAR_LUMP * rl;

	ret = 0;
	lock_task(radar_lock);
	for ( rl = lump_list ; rl ; rl = rl->next ) {
		ret = cons(
			List(n_get_symbol("lump"),
				get_string(rl->lumpcrd_path),
				List(n_get_symbol("pmd"),
					get_string(rl->db_path),
					List(
					List(get_floating(rl->sphere.tl.x,
							rl->unit),
						get_floating(rl->sphere.tl.y,
							rl->unit),
						-1),
					List(get_floating(rl->sphere.br.x,
							rl->unit),
						get_floating(rl->sphere.br.y,
							rl->unit),
						-1),
					-1),
					get_floating(rl->reso_min,
						rl->reso_unit),
					get_floating(rl->reso_max,
						rl->reso_unit),
					-1),
				-1),
			ret);
	}
	unlock_task(radar_lock,"gv_status");
	return cons(n_get_symbol("status"),ret);
}

void
_query_trigger(RADAR_CACHE * rc_ptr,int fn_flag)
{

	lock_task(radar_lock);

	_empty_radar_matrix_in_query(rc_ptr,fn_flag);
	rc_ptr->win_force = 1;
	rc_ptr->win_delete_lock = 1;
	_wakeup_loading_task(rc_ptr);

	unlock_task(radar_lock,"query_trigger");
}

void
query_trigger(RADAR_CACHE * rc_ptr,int fn_flag)
{

	rc_task_lock(rc_ptr,TM_TRIG);
	_query_trigger(rc_ptr,fn_flag);
	rc_task_unlock(rc_ptr,TM_TRIG);
}

void
_query_trigger2(RADAR_CACHE * rc_ptr)
{

	lock_task(radar_lock);

	rc_ptr->win_force = 1;
	rc_ptr->win_delete_lock = 1;
	_wakeup_loading_task(rc_ptr);

	unlock_task(radar_lock,"query_trigger");
}

void
query_trigger2(RADAR_CACHE * rc_ptr)
{

	rc_task_lock(rc_ptr,TM_TRIG);
	_query_trigger2(rc_ptr);
	rc_task_unlock(rc_ptr,TM_TRIG);
}

int
__include_query_check(XL_SEXP * rc_q,XL_SEXP * q)
{
int ret;
	ret = gbb_equ(rc_q,q);
	if ( ret )
		return 0;
	return -1;
}

int
_include_query_check(XL_SEXP * rc_q,XL_SEXP * q)
{
XL_SEXP * cmd;
	if ( get_type(rc_q) != XLT_PAIR )
		return __include_query_check(rc_q,q);
	cmd = car(rc_q);
	if ( get_type(cmd) != XLT_SYMBOL )
		return __include_query_check(rc_q,q);
	if ( l_strcmp(cmd->symbol.data,l_string(std_cm,"OR")) )
		return __include_query_check(rc_q,q);
	rc_q = cdr(rc_q);
	for ( ; get_type(rc_q) == XLT_PAIR ; rc_q = cdr(rc_q) ) {
		if ( __include_query_check(car(rc_q),q) == 0 )
			return 0;
	}
	return -1;
}

XL_SEXP *
include_query_check(XL_SEXP * rc_query,XL_SEXP * query)
{
XL_SEXP * cmd;
int ret;
XL_SEXP * _ret;
int len;
	if ( get_type(query) != XLT_PAIR ) {
		ret = _include_query_check(rc_query,query);
		if ( ret )
			return query;
		return 0;
	}
	cmd = car(query);
	if ( get_type(cmd) != XLT_SYMBOL ) {
		ret = _include_query_check(rc_query,query);
		if ( ret )
			return query;
		return 0;
	}
	if ( l_strcmp(cmd->symbol.data,l_string(std_cm,"OR")) ) {
		ret = _include_query_check(rc_query,query);
		if ( ret )
			return query;
		return 0;
	}
	query = cdr(query);
	_ret = 0;
	len = 0;
	for ( ; get_type(query) == XLT_PAIR ; query = cdr(query) ) {
		ret = _include_query_check(rc_query,car(query));
		if ( ret ) {
			_ret = cons(car(query),_ret);
			len ++;
		}
	}
	switch ( len ) {
	case 0:
		return 0;
	case 1:
		return car(_ret);
	default:
		return cons(n_get_symbol("OR"),_ret);
	}
}

RADAR_CACHE *
get_sf_rc_ptr(XL_SYM_FIELD * sf)
{
GBVIEW_FLAME * gf;
L_CHAR * _gf;
	_gf = get_sf_attribute(sf,
		l_string(std_cm,"flame-id"));
	if ( _gf ) {
		gf = wf_get_gf_from_id(atoi(n_string(std_cm,_gf)));
	}
	else 	gf = 0;
	if ( gf == 0 )
		gf = wf_next_gf(0,GVFM_LIVE);
	return gf->radar_ptr;
}


int
_rc_insert_q_thread(
	RADAR_CACHE * rc_ptr,
	QUERY_THREAD * q_list)
{
QUERY_THREAD * q,* q2,*q3;
Q_THREAD_LIST *ql;
int ret;
	ret = 0;
	q2 = 0;
	for ( ; q_list ; q_list = q_list->next ) {
		ql = _search_q_thread_by_content(rc_ptr,q_list);
		q = ql ? ql->qth : 0;
		if ( q == 0 ) {
			q = _new_q_thread(rc_ptr,q_list);
			q3 = d_alloc(sizeof(*q3));
			memset(q3,0,sizeof(*q3));
			q3->id = q->id;
			q3->next = q2;
			q2 = q3;
		}
		q_list->id = q->id;
		ret ++;
	}

	if ( ret ) {
		rc_ptr->win_force = 1;
		rc_ptr->win_delete_lock = 1;
		_wakeup_loading_task(rc_ptr);

		for ( q3 = q2 ; q3 ; q3 = q3->next )
			_call_condition_event(rc_ptr,q3);
		free_query_thread(q2);
	}

	return ret;
}

int
rc_insert_q_thread(
	RADAR_CACHE * rc_ptr,
	QUERY_THREAD * q_list)
{
int ret;
	lock_task(radar_lock);
	ret = _rc_insert_q_thread(rc_ptr,q_list);
	unlock_task(radar_lock,"rc_insert_q_thread");
	return ret;
}

int
rc_delete_q_thread(
	RADAR_CACHE * rc_ptr,
	int id)
{
int ret;
QUERY_THREAD dummy;
	lock_task(radar_lock);
	if ( id < 0 ) {
		ret = 0;
		for ( ; rc_ptr->q_thread_lst ; ) {
			ret ++;
			_delete_q_thread(rc_ptr,rc_ptr->q_thread_lst->qth->id);
		}
	}
	else {
		ret = _delete_q_thread(rc_ptr,id);
		if ( ret >= 0 )
			ret = 1;
	}

	if ( ret > 0 ) {
		rc_ptr->win_force = 1;
		rc_ptr->win_delete_lock = 1;
		_wakeup_loading_task(rc_ptr);

		memset(&dummy,0,sizeof(dummy));
		dummy.id = id;
		_call_condition_event(rc_ptr,&dummy);
	}

	unlock_task(radar_lock,"rc_delete_q_thread");
	return ret;
}


int
sexp_to_q_thread_1(QUERY_THREAD * q,XL_SEXP * s)
{
XL_SEXP * sym;
L_CHAR * _id,* _title,* _active;
XL_SEXP * d;
/****/
XL_SEXP * dd;
XL_SEXP * dd_data;
char * time_data,* p, * ptr;
char ch;
	sym = car(s);
	if ( get_type(sym) != XLT_SYMBOL )
		return -1;
	if ( l_strcmp(sym->symbol.data,
			l_string(std_cm,"query")) == 0 ) {
		_id = get_sf_attribute(sym->symbol.field,
			l_string(std_cm,"id"));
		if ( _id ) {
			q->id = atoi(n_string(std_cm,_id));
		}
		else	q->id = 0;
		_title = get_sf_attribute(sym->symbol.field,
			l_string(std_cm,"title"));
		if ( _title ) {
			if ( _title[0] )
				q->title = ll_copy_str(_title);
			else	q->title = 0;
		}
		else	q->title = 0;
		_active = get_sf_attribute(sym->symbol.field,
			l_string(std_cm,"active"));
		if ( _active ) {
			if ( l_strcmp(_active,l_string(std_cm,"on")) == 0 )
				q->flags |= QTF_ACTIVE;
			else	q->flags &= ~QTF_ACTIVE;
			q->mask |= QTF_ACTIVE;
		}
		else	q->flags |= QTF_ACTIVE;
		return sexp_to_q_thread_1(q,get_el(s,1));
	}
	else if ( l_strcmp(sym->symbol.data,
			l_string(std_cm,"AND")) == 0 ) {
		s = cdr(s);
		for ( ; get_type(s) == XLT_PAIR ; s = cdr(s) )
			if ( sexp_to_q_thread_1(q,car(s)) < 0 )
				return -1;
		return 0;
	}
	else if ( l_strcmp(sym->symbol.data,
			l_string(std_cm,"URL")) == 0 ) {
		d = get_el(s,1);
		if ( get_type(d) != XLT_STRING )
			return -1;
		q->url = ll_copy_str(d->string.data);
		return 0;	
	}
	else if ( l_strcmp(sym->symbol.data,
			l_string(std_cm,"qualifier")) == 0 ) {
			dd = get_el(s,1);
			if ( get_type(dd) != XLT_STRING )
				return -1;
			if ( l_strcmp(dd->string.data,
					l_string(std_cm,GB_NAMESPACE)) )
				return -1;
			dd = get_el(s,2);
			switch ( get_type(dd) ) {
			case XLT_INTEGER:
				if ( dd->integer.data != 0 )
					return -1;
				break;
			case XLT_NULL:
				break;
			default:
				return -1;
			}
			dd = get_el(s,3);
			if ( get_type(dd) != XLT_STRING )
				return -1;
			dd_data = get_el(s,5);
			if ( l_strcmp(dd->string.data,
					l_string(std_cm,"property")) == 0 ) {
				if ( get_type(dd_data) != XLT_STRING )
					return -1;
				if ( q->property )
					d_f_ree(q->property);
				q->property = ll_copy_str(dd_data->string.data);
			}
			else if ( l_strcmp(dd->string.data,
					l_string(std_cm,"content.period")) == 0 ) {
				if ( get_type(dd_data) != XLT_STRING )
					return -1;
				time_data = ln_copy_str(std_cm,
						dd_data->string.data);
				for ( p = time_data ;
						*p && (
						*p == ' ' ||
						*p == '\t' ||
						*p == '\n' ||
						*p == '\r') ; 
						p ++ );
				if ( *p == '/' ) {
					invalid_gb_time(&q->content_period_from);
					p ++;
				}
				else {
					for ( ; *p && 
						*p != '/' ; p ++ );
					ch = *p;
					*p = 0;
					w3c_dtf_to_gb_time(&q->content_period_from,
						time_data);
					*p++ = ch;
				}
				ptr = p;
				for ( ;
						*p && (
						*p == ' ' ||
						*p == '\t' ||
						*p == '\n' ||
						*p == '\r') ; 
						p ++ );
				if ( *p == 0 ) {
					invalid_gb_time(&q->content_period_to);
				}
				else {
					w3c_dtf_to_gb_time(
						&q->content_period_to,
						ptr);
				}
			}
			else	return -1;
			return 0;
	}
	else	return -1;
}


QUERY_THREAD *
sexp_to_q_thread(XL_SEXP * s)
{
QUERY_THREAD * ret, * q, ** rp;
XL_SEXP * sym;
	sym = car(s);
	if ( get_type(sym) == XLT_SYMBOL &&
		l_strcmp(sym->symbol.data,
				l_string(std_cm,"OR")) == 0 ) {
		ret = 0;
		rp = &ret;
		for ( s = cdr(s) ; get_type(s) == XLT_PAIR ; s = cdr(s) ) {
			q = d_alloc(sizeof(*q));
			memset(q,0,sizeof(*q));
			q->flags |= QTF_ACTIVE;
			invalid_gb_time(&q->content_period_from);
			invalid_gb_time(&q->content_period_to);
			if ( sexp_to_q_thread_1(q,car(s)) < 0 ) {
				_free_query_thread_1(0,q);
				continue;
			}
			*rp = q;
			rp = &q->next;
		}
	}
	else {
		ret = d_alloc(sizeof(*ret));
		memset(ret,0,sizeof(*q));
		ret->flags |= QTF_ACTIVE;
		invalid_gb_time(&ret->content_period_from);
		invalid_gb_time(&ret->content_period_to);
		if ( sexp_to_q_thread_1(ret,s) < 0 ) {
			_free_query_thread_1(0,ret);
			return 0;
		}
	}
	return ret;
}

QUERY_THREAD *
_get_q_thread(
	RADAR_CACHE * rc_ptr)
{
QUERY_THREAD * ret, ** rp,* q2;
Q_THREAD_LIST * q1;
	ret = 0;
	rp = &ret;
	q1 = rc_ptr->q_thread_lst;
	for ( ; q1 ; q1 = q1->next , rp = &(*rp)->next ) {
		q2 = d_alloc(sizeof(*q2));
		memset(q2,0,sizeof(*q2));
		invalid_gb_time(&q2->content_period_from);
		invalid_gb_time(&q2->content_period_to);
		duplicate_q_thread(q2,q1->qth);
		q2->id = q1->qth->id;
		*rp = q2;
	}
	return ret;
}

QUERY_THREAD *
rc_get_q_thread(
	RADAR_CACHE * rc_ptr)
{
QUERY_THREAD * ret;
	lock_task(radar_lock);
	ret = _get_q_thread(rc_ptr);
	unlock_task(radar_lock,"_get_q_thread");
	return ret;
}

int
rc_set_q_thread(
	RADAR_CACHE * rc_ptr,
	QUERY_THREAD * q)
{
Q_THREAD_LIST * q2;
int ret;
QUERY_THREAD * q_head, * q3;
int win_f;

	lock_task(radar_lock);
	ret = 0;
	q_head = 0;
	win_f = 0;
	for ( ; q ; q = q->next ) {
		q2 = _search_q_thread(rc_ptr,q->id);
		if ( q2 == 0 )
			continue;
		if ( q->mask ) {
			if ( (q->mask & q2->qth->flags) != (q->mask & q->flags) ) {
				q2->qth->flags &= ~q->mask;
				q2->qth->flags |= q->flags & q->mask;

				q3 = d_alloc(sizeof(*q3));
				memset(q3,0,sizeof(*q3));
				q3->id = q->id;
				q3->flags = q2->qth->flags;
				q3->mask = q->mask;
				q3->next = q_head;
				q_head = q3;
				win_f = 1;
				ret ++;
			}
		}
		else if ( _cmp_q_thread(q2->qth,q) ) {
			duplicate_q_thread(q2->qth,q);
			_empty_radar_matrix(q2->matrix,1);
			q2->matrix = 0;

			q3 = d_alloc(sizeof(*q3));
			memset(q3,0,sizeof(*q3));
			q3->id = q->id;
			q3->next = q_head;
			q_head = q3;
			ret ++;
		}
	}

	if ( ret ) {
		rc_ptr->win_force = 1;
		rc_ptr->win_delete_lock = 1;
		_wakeup_loading_task(rc_ptr);
		if ( win_f ) {
			rc_ptr->win_load = 1;
			rc_ptr->base_change_flag = 0;
			_wakeup_win_manage(rc_ptr);
		}
		for ( q3 = q_head ; q3 ; q3 = q3->next )
			_call_condition_event(rc_ptr,q3);
		free_query_thread(q_head);
	}
	unlock_task(radar_lock,"rc_set_q_thread");
	return ret;
}

int
rc_replace_q_thread(
	RADAR_CACHE * rc_ptr,
	QUERY_THREAD * q)
{
int ret,_ret;

	lock_task(radar_lock);
	ret = 0;
	for ( ; rc_ptr->q_thread_lst ; ) {
		_delete_q_thread(rc_ptr,rc_ptr->q_thread_lst->qth->id);
		ret = 1;
	}
	_ret = _rc_insert_q_thread(rc_ptr,q);

	if ( ret || _ret ) {
		rc_ptr->win_force = 1;
		rc_ptr->win_delete_lock = 1;
		_wakeup_loading_task(rc_ptr);
	}
	unlock_task(radar_lock,"rc_set_q_thread");
	return _ret ? _ret : ret;
}


XL_SEXP *
gv_is_insert_query(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
XL_SEXP * query;
XL_SEXP * cmd;
RADAR_CACHE * rc_ptr;
int ret;

	rc_ptr = get_sf_rc_ptr(sf);

	query = gb_quote_trace(env,get_el(s,1),
		get_sf_attribute(sf,l_string(std_cm,"type")));
	if ( get_type(query) == XLT_ERROR )
		return query;
	if ( get_type(query) != XLT_PAIR )
		goto type_missmatch;
	cmd = car(query);
	if ( get_type(cmd) != XLT_SYMBOL )
		goto type_missmatch;

	ret = rc_insert_q_thread(rc_ptr,sexp_to_q_thread(query));
	return get_integer(ret,0);

type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"gv-insert-query"),
		List(n_get_string("type missmatch"),
			query,
			-1));
}


XL_SEXP *
gv_is_delete_query(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
XL_SEXP * no;
int _no;
RADAR_CACHE * rc_ptr;
int ret;

	rc_ptr = get_sf_rc_ptr(sf);
	
	no = get_el(s,1);
	if ( get_type(no) != XLT_INTEGER )
		goto type_missmatch;
	_no = no->integer.data;


	ret = rc_delete_q_thread(rc_ptr,_no);
	if ( ret == 0 ) 
		return 0;
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_OBJECT,
		l_string(std_cm,"gv-delete-query"),
		List(n_get_string("no object id = "),
			no,
			-1));

type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"gv-delete-query"),
		List(n_get_string("type missmatch"),
			-1));
}



XL_SEXP *
gv_is_set_query(XLISP_ENV * env,XL_SEXP * s,XLISP_ENV * a,XL_SYM_FIELD * sf)
{
XL_SEXP * query;
XL_SEXP * cmd;
RADAR_CACHE * rc_ptr;
int ret;

	rc_ptr = get_sf_rc_ptr(sf);
	query = gb_quote_trace(env,get_el(s,1),
		get_sf_attribute(sf,l_string(std_cm,"type")));
	if ( get_type(query) == XLT_ERROR )
		return query;
	if ( get_type(query) != XLT_PAIR )
		goto type_missmatch;
	cmd = car(query);
	if ( get_type(cmd) != XLT_SYMBOL )
		goto type_missmatch;

	ret = rc_set_q_thread(rc_ptr,sexp_to_q_thread(query));
	return get_integer(ret,0);
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"gv-set-query"),
		List(n_get_string("type missmatch"),
			-1));
}


XL_SEXP *
gv_is_get_query(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
RADAR_CACHE * rc_ptr;
QUERY_THREAD * q, * _q;
XL_SEXP * ret;
XL_SEXP * sym;
char buf[100];
	rc_ptr = get_sf_rc_ptr(sf);
	_q = q = rc_get_q_thread(rc_ptr);
	ret = 0;
	for ( ; q ; q = q->next ) {
		sym = n_get_symbol("query");
		sprintf(buf,"%i",q->id);
		set_attribute(sym,
			l_string(std_cm,"id"),
			l_string(std_cm,buf));
		ret = cons(
			List(sym,
				q_thread_to_sexp_1(q,QTH_MAXIMUM_INFO),
				-1),
			ret);
	}
	return reverse(ret);
}



int
beam_convert(int ses,L_CHAR * burl,RADAR_LUMP * rl,
		GB_RECT * r,REAL1 * min,REAL1 * max,
		L_CHAR ** unit_p,L_CHAR ** r_unit_p)
{
GB_POINT ptr[8];
REAL1 reso[8];
int i;
MAP_HISTORY * mh;
	if ( l_strcmp(burl,rl->lumpcrd_path) == 0 )
		mh = 0;
	else {

		mh = resolve_mappath(ses,burl,rl->lumpcrd_path,RR_WM_INDIRECT);
		if ( mh == MP_MH_NO_ROUTE )
			return -1;
		for ( i = 0 ; i < 8 ; i += 2 ) {
			reso[i] = *min;
			reso[i+1] = *max;
		}
		ptr[0] = r->tl;
		ptr[2].x = r->tl.x;
		ptr[2].y = r->br.y;
		ptr[4] = r->br;
		ptr[6].x = r->br.x;
		ptr[6].y = r->tl.y;

		ptr[1] = p_avg(ptr[0],ptr[2]);
		ptr[3] = p_avg(ptr[2],ptr[4]);
		ptr[5] = p_avg(ptr[4],ptr[6]);
		ptr[7] = p_avg(ptr[6],ptr[0]);

		map_from_flame(mh,ptr,reso,8);

		r->tl.x = r->tl.y = 0;
		r->br.x = r->br.y = -1;
		*min = *max = 0;
		for ( i = 0 ; i < 8 ; i ++ ) {
			insert_rect(r,ptr[i]);
			if ( *min == 0 || *min > reso[i] )
				*min = reso[i];
			if ( *max == 0 || *max < reso[i] )
				*max = reso[i];
		}
	}
	*unit_p = rl->unit;
	*r_unit_p = rl->reso_unit;
	return 0;
}

void
test_lock(int f)
{
static int lock_data;
	lock_task(radar_lock);
	if ( f ) {
		for ( ; lock_data ; ) {
			sleep_task((int)&lock_data,radar_lock);
			lock_task(radar_lock);
		}
		lock_data = 1;
	}
	else {
		lock_data = 0;
		wakeup_task((int)&lock_data);
	}
	unlock_task(radar_lock,"test_lock");
}


void
beam_task(TKEY d)
{
RADAR_LUMP * rl, * rl2, * rl3;
XL_SEXP * ret,* result;
XL_SEXP * qq, * qqq;
URL u;
URL target;
GB_RECT conv_r;
REAL1 conv_min,conv_max;
GB_RECT _conv_r;
REAL1 _conv_min,_conv_max;
L_CHAR * base_url;
XL_SEXP * q;
int ses;
XL_INTERPRETER * xli;
SYS_QUEUE * que;
L_CHAR * key;

T_LOAD_TO_BEAM * n;
RADAR_CACHE * rc_ptr;
L_CHAR * unit,* reso_unit;

	que = (SYS_QUEUE *)GET_TKEY(d);
	key = touch_qkey(que);
	if ( key == 0 )
		return;

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

	ses = open_session(SEST_OPTIMIZE);
	rc_ptr = que->work;

	for ( ; ; ) {
		gc_push(0,0,"beam");

		n = delete_queue(que,sq_key_cond,key,0);
		if ( n == 0 ) {
			gc_pop(0,0);
			break;
		}
		lock_task(radar_lock);
		rc_ptr->ri.d.beam --;
		rc_ptr->ri.d.load_to_beam --;
		_call_indicate_event(rc_ptr,1);
		if ( l_strcmp(rc_ptr->base_url,n->base_url) != 0 ) {
			unlock_task(radar_lock,"beam_task");
			free_load_to_beam(n);
			gc_pop(0,0);
			continue;
		}
		unlock_task(radar_lock,"beam_task");
		if ( rc_ptr->status & GVFM_ZONBIE ) {
			free_load_to_beam(n);
			gc_pop(0,0);
			continue;
		}

		rl = n->rl;
		q = n->query;
		_conv_min = n->min;
		_conv_max = n->max;
		_conv_r = n->r;
		base_url = n->base_url;

		get_url2(&target,rl->lumpcrd_path);
		if ( target.resource )
			d_f_ree(target.resource);
		target.resource = ll_copy_str(rl->db_path);
		qqq = 0;
		for ( rl2 = rl ; rl2 ; ) {
			get_url2(&u,rl2->lumpcrd_path);
			conv_min = _conv_min;
			conv_max = _conv_max;
			conv_r = _conv_r;
			if ( beam_convert(ses,base_url,rl2,
					&conv_r,&conv_min,&conv_max,
					&unit,
					&reso_unit) < 0 )
{log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"BEAM CONVERT ERR\n");
				goto del;
}
			if ( cross_rect_rect(&rl2->sphere,&conv_r) == 0 )
{log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"CROSS_RECT_RECT ERR\n");
				goto del;
}
			if ( rl2->reso_min > conv_max ||
					rl2->reso_max < conv_min )
{log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"RESO BORDER ERR %ls %f %f - %f %f - %f %f\n",
rl2->lumpcrd_path,
rl2->reso_min,
rl2->reso_max,
conv_max,
conv_min,
_conv_max,
_conv_min);
				goto del;
}
			if ( rl2->db_path == 0 )
{log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"DB PATH ERR\n");
				goto del;
}
			if ( u.resource )
				d_f_ree(u.resource);

			u.resource = ll_copy_str(rl2->db_path);
			qq = List(n_get_symbol("pmd-query"),
				get_string(rl2->db_path),
				List(n_get_symbol("quote"),
					List(	List(	
						get_floating(conv_r.tl.x,
							unit),
						get_floating(conv_r.tl.y,
							unit),
						-1),
						List(	
						get_floating(conv_r.br.x,
							unit),
						get_floating(conv_r.br.y,
							unit),
						-1),
						-1),
					-1),
				get_floating(conv_min,
					reso_unit),
				get_floating(conv_max,
					reso_unit),
				n_get_symbol("qr"),
				-1);
			qqq = cons(qq,qqq);

		del:
			free_url(&u);
			rl3 = rl2->next;
			_free_radar_lump(rl2);
			rl2 = rl3;
		}
		if ( get_type(qqq) == XLT_NULL )
			goto no_process;
		qqq = cons(n_get_symbol("List"),qqq);
		qqq = List(n_get_symbol("Sequence"),
			0,
			List(n_get_symbol("Define"),
				n_get_symbol("qr"),
				List(n_get_symbol("quote"),q,-1),
				-1),
			qqq,
			-1);
/*
fflush(stdout);
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"===================================================\n");
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"beam6=> %ls ",target.server);
log_print_sexp(LOG_MESSAGE,LOG_LAYER_GB,0,"beam6",qqq,0);
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"\n");

ss_printf("===================================================\n");
ss_printf("beam6=> %ls ",target.server);
print_sexp(s_stdout,qqq,0);
ss_printf("\n");
*/
		ret = remote_session(
			gblisp_top_env0,
			ses,
			&target,
			l_string(std_cm,"gbpmd.get"),
			l_string(std_cm,"user"),
			l_string(std_cm,"Get"),
			List(qqq,-1),
			0,0,0,0);

		if ( get_type(ret) == XLT_ERROR ) {
			log_print_sexp(LOG_WARNING,LOG_LAYER_GB,0,
				"access to lump",ret,0);
			result = ret;
		}
		else {
			result = 0;
			for ( ; get_type(ret) == XLT_PAIR ; ret = cdr(ret) )
				result = append(car(ret),result);
		}

		if ( result ) {
/*
ss_printf("===================================================\n");
ss_printf("beam res=> %ls ",target.server);
print_sexp(s_stdout,result,0);
ss_printf("\n");
*/
			lock_task(radar_lock);
			insert_beam_to_resource(rc_ptr,result,n->qt_id);	
			unlock_task(radar_lock,"beam_task");
		}
	no_process:

		gc_pop(0,0);
		free_url(&target);

		n->rl = 0;
		free_load_to_beam(n);
	}

	release_qkey(que,key);
	d_f_ree(key);

	close_session(ses);
	close_self_interpreter();

}


RADAR_LUMP *
merge_radar_lump(RADAR_LUMP * rl,RADAR_LUMP * rl2)
{
RADAR_LUMP * rl_1;
	for ( rl_1 = rl ; rl_1 ; rl_1 = rl_1->next ) {
		if ( l_strcmp(rl_1->lumpcrd_path,
				rl2->lumpcrd_path) == 0 )
			return rl;
	}
	rl_1 = _copy_radar_lump_1(rl2);
	rl_1->next = rl;
	return rl_1;
}

void
beam_to_remote(RADAR_CACHE * rc_ptr,
	int ses,GB_RECT * r,REAL1 min,REAL1 max,XL_SEXP * q,int qt_id)
{
RADAR_LUMP * rl, * rl2, ** rlp, * rl3;
XL_SEXP * result;
URL u;
URL target;
L_CHAR * base_url;
RADAR_CRD * c;
LUMP_CRD_NODE * lcn;

T_LOAD_TO_BEAM * n;

GBVIEW_STATUS sts;
GBVIEW_LAYER_STATUS * ls;

	if ( rc_ptr->status & GVFM_ZONBIE )
		return;
	_rlock_base_url(rc_ptr,"base_to_remote");

	wf_status(rc_ptr->gf,&sts);
	rl = 0;
	for ( ls = sts.layers ; ls ; ls = ls->next ) {
		c = _search_radar_crd(rc_ptr,ls->entry_url,0,0);
//ss_printf("beam_to_remote %x\n",c);
		if ( c == 0 )
			continue;
		for ( lcn = c->lump ; lcn ; lcn = lcn->crd_next )
			rl = merge_radar_lump(rl,lcn->lump);
		_flush_radar_crd(c);
	}
	wf_free_status(&sts);
	
	base_url = ll_copy_str(rc_ptr->base_url);

	_unlock_base_url(rc_ptr);

	result = 0;
	gc_push(0,0,"beam_to_remote");


	for ( ; rl ; ) {
		get_url2(&target,rl->lumpcrd_path);
		rl2 = 0;
		for ( rlp = &rl ; *rlp ; ) {
			rl3 = *rlp;
			get_url2(&u,rl3->lumpcrd_path);
			if ( l_strcmp(target.server,u.server) == 0 &&
					target.port == u.port ) {
				*rlp = rl3->next;
				rl3->next = rl2;
				rl2 = rl3;
			}
			else {
				rlp = &rl3->next;
			}
			free_url(&u);
		}
		n = new_queue_node(sizeof(*n));
		n->h.key = ll_copy_str(target.server);
		n->query = q;
		n->r = *r;
		n->min = min;
		n->max = max;
		n->base_url = ll_copy_str(base_url);
		n->rl = rl2;
		n->qt_id = qt_id;

		rc_ptr->ri.d.beam ++;
		rc_ptr->ri.d.load_to_beam ++;
		_call_indicate_event(rc_ptr,1);

		insert_queue(&rc_ptr->load_to_beam,n,0);
		free_url(&target);
	}
	d_f_ree(base_url);

	gc_pop(0,0);
}


int
insert_check(SYS_QUEUE * q,T_RESOURCE_TO_INSERT * n,L_CHAR * obj_url)
{
	if ( l_strcmp(n->obj_path,obj_url) == 0 )
		return 0;
	return -1;
}

void
beam_load(RADAR_CACHE * rc_ptr,XL_SEXP * lst,int qt_id)
{
LOAD_RESOURCE_WORK * w;
XL_SEXP * p, * urls, * u, * v, * ret, * q, * r, * s ,* t;
int f;
T_RESOURCE_TO_INSERT * n;
L_CHAR * bu;

	if ( rc_ptr->status & GVFM_ZONBIE )
		return;
	ret = 0;
	for ( urls = lst ; get_type(urls) == XLT_PAIR ;
				urls = cdr(urls) ) {
		p = car(urls);
		if ( get_type(p) != XLT_PAIR )
			continue;
		if ( list_length(p) != 2 )
			continue;
		u = get_el(p,0);
		if ( get_type(u) != XLT_STRING )
			continue;
		v = get_el(p,1);
		if ( get_type(v) != XLT_STRING )
			continue;
		f = 0;
		for ( q = cdr(urls) ; get_type(q) ; q = cdr(q) ) {
			r = car(q);
			if ( get_type(r) != XLT_PAIR )
				continue;
			if ( list_length(r) != 2 )
				continue;
			s = get_el(r,0);
			if ( get_type(s) != XLT_STRING )
				continue;
			t = get_el(r,1);
			if ( get_type(t) != XLT_STRING )
				continue;
			if ( l_strcmp(u->string.data,s->string.data) )
				continue;
			if ( l_strcmp(v->string.data,t->string.data) )
				continue;
			f = 1;
			break;
		}
		if ( f == 1 )
			continue;
		ret = cons(p,ret);
	}

	lst = ret;
	w = 0;

	rlock_base_url(rc_ptr,"beam_load");
	if ( rc_ptr->base_url )
		bu = ll_copy_str(rc_ptr->base_url);
	else	bu = 0;
	unlock_base_url(rc_ptr);

	for ( urls = lst ; get_type(urls) == XLT_PAIR ;
				urls = cdr(urls) ) {

		p = car(urls);
		u = get_el(p,0);
		v = get_el(p,1);

		if ( check_queue(
				&rc_ptr->resource_to_insert,
				insert_check,
				v->string.data) > 0 ) {
			continue;
		}

		n = new_queue_node(sizeof(*n));
		n->h.key = nl_copy_str(std_cm,"resource_to_insert");
		n->mappath_loading = 0;

		n->lr_crd = w = new_lrw(w);
		get_url2(&w->url,u->string.data);
		if ( l_strcmp(v->string.data,u->string.data) ) {
			n->lr_obj = w = new_lrw(w);
			get_url2(&w->url,v->string.data);
		}
		else	n->lr_obj = 0;

		n->crd_path = ll_copy_str(u->string.data);
		n->obj_path = ll_copy_str(v->string.data);
		n->qt_id = qt_id;
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"LOAD %ls\n",n->crd_path);
*/

		if ( bu )
			flush_route(
				resolve_route(bu,n->crd_path,RR_WM_NO_WAIT));

		insert_queue(&rc_ptr->resource_to_insert,n,0);
	}
	if ( bu )
		d_f_ree(bu);
	load_resource_list(w,Q_PRI_RADAR,0);
	dispose_lrw(w,LRWE_COMPLETE);
}

void
beam_load_resource_task(TKEY d)
{
XL_INTERPRETER * xli;
T_BEAM_TO_RESOURCE * n;
L_CHAR * key;
SYS_QUEUE * que;
RADAR_CACHE * rc_ptr;

	que = (SYS_QUEUE *)GET_TKEY(d);
	key = touch_qkey(que);
	if ( key == 0 )
		return;

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);
	rc_ptr = que->work;

	for ( ; ; ) {
		gc_push(0,0,"beam_load_resource_task");
		n = delete_queue(&rc_ptr->beam_to_resource,sq_key_cond,key,0);
		if ( n == 0 ) {
			gc_pop(0,0);
			break;
		}
		lock_task(radar_lock);
		rc_ptr->ri.d.beam --;
		rc_ptr->ri.d.beam_to_resource --;
		_call_indicate_event(rc_ptr,1);
		unlock_task(radar_lock,"beam_load_resource_task");
		if ( rc_ptr->status & GVFM_ZONBIE ) {
			d_f_ree(n->h.key);
			d_f_ree(n);
			gc_pop(0,0);
			continue;
		}
		beam_load(rc_ptr,n->urls,n->qt_id);
		d_f_ree(n->h.key);
		d_f_ree(n);
		gc_pop(0,0);
/*
		lock_task(radar_lock);
		rc_ptr->ri.d.beam --;
		if ( rc_ptr->ri.d.beam < 0 )
			rc_ptr->ri.d.beam = 0;
		call_indicate_event(rc_ptr,1);
*/
	}

	release_qkey(que,key);
	d_f_ree(key);

	close_self_interpreter();

}

XL_SEXP *
beam_to_lump(RADAR_CACHE * rc_ptr,int ses,GB_RECT * r,REAL1 min,REAL1 max,int id)
{
XL_SEXP * q;
XL_SEXP * ret;
Q_THREAD_LIST * qt;

log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"beam (%f %f)-(%f %f) %f %f\n",
r->tl.x,
r->tl.y,
r->br.x,
r->br.y,
min,max);


	if ( rc_ptr->query_mode ) {
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"beam aboat\n");
		return get_integer(-1,0);
	}
//	q = List(n_get_symbol("quote"),rc_ptr->query,-1);
//	q = eval(gblisp_top_env0,q);
	qt = _search_q_thread(rc_ptr,id);
	if ( qt == 0 )
		return get_integer(-1,0);
//	q = List(n_get_symbol("quote"),
//			q_thread_to_sexp_1(qt),
//			-1);
	q = q_thread_to_sexp_1(qt->qth,QTH_MINIMUM_INFO);
	q = radar_query_regulation(q);
	if ( get_type(q) == XLT_ERROR )
		{log_print_sexp(LOG_WARNING,LOG_LAYER_GB,0,
			"beam_to_lump query error",q,0);} 

ss_printf("BEAM ID %i (%f %f)",id,min,max);
print_sexp(s_stdout,q,0);
ss_printf("\n");

	if ( lump_list && min != 0 && max != 0 )
		beam_to_remote(rc_ptr,ses,r,min,max,q,id);
	else {
		ret = virtual_lump(r,min,max,q);
		if ( ret )
			insert_beam_to_resource(rc_ptr,ret,id);
		_wakeup_retrieve_lump_task(rc_ptr);
	}
	return 0;
}

void
get_center_reso(GBVIEW_FLAME * gf,GB_POINT * p,REAL1 * reso,GB_RECT * r)
{
REAL1 ww,hh;
REAL1 reso_h,reso_w;
	p->x = (r->tl.x + r->br.x)/2;
	p->y = (r->tl.y + r->br.y)/2;
	ww = r->br.x - r->tl.x;
	hh = r->br.y - r->tl.y;
	reso_h = gf->win_height/hh;
	reso_w = gf->win_width/ww;
	if ( reso_h < reso_w )
		*reso = reso_h;
	else	*reso = reso_w;
}


int
goto_zoom(RADAR_CACHE * rc_ptr,int ses,GBVIEW_FLAME * gf,L_CHAR * target)
{
URL u;
RESOURCE * c;
REAL1 reso;
GB_POINT p;

	get_url2(&u,target);

	c = load_resource(ses,&u,Q_PRI_RADAR);


	free_url(&u);
	if ( c == 0 )
		return -1;
	get_center_reso(gf,&p,&reso,&c->h.minrect);
	if ( c->h.visible_resolution > reso )
		reso = c->h.visible_resolution*1.1;


	wf_goto_point(rc_ptr->gf,target,p,0,reso);

	wlock_base_url(rc_ptr,"goto_zoom");

	if ( rc_ptr->base_url )
		d_f_ree(rc_ptr->base_url);

	rc_ptr->base_url = ll_copy_str(target);

	unlock_base_url(rc_ptr);

	return 0;
}

void
adjust_rect_by_reso(
	RADAR_CACHE * rc_ptr,
	GB_RECT * r,
	REAL1 v_reso_min,
	REAL1 v_reso_max)
{
GBVIEW_FLAME * gf;
int w,h;
REAL1 h_reso,w_reso;
GB_POINT center;
GB_POINT ofs;
	gf = rc_ptr->gf;
	if ( gf == 0 )
		return;
	w = gf->win_width;
	h = gf->win_height;
	if ( r->br.y == r->tl.y || r->br.x == r->tl.y )
		goto adjust;
	h_reso = h/(r->br.y - r->tl.y);
	w_reso = w/(r->br.x - r->tl.x);
	if ( h_reso < v_reso_min && w_reso < v_reso_min ) {
		ofs.x = w/(v_reso_min*1.1)/2;
		ofs.y = h/(v_reso_min*1.1)/2;
		center = p_add(r->tl,r->br);
		center.x /= 2;
		center.y /= 2;
		r->tl = p_sub(center,ofs);
		r->br = p_add(center,ofs);
	}
	if ( v_reso_max == 0 )
		v_reso_max = v_reso_min * WIN_RESO_WINDOW_MAX;
	if ( h_reso > v_reso_max || w_reso > v_reso_max ) {
	adjust:
		ofs.x = w/(v_reso_max*0.9)/2;
		ofs.y = h/(v_reso_max*0.9)/2;
		center = p_add(r->tl,r->br);
		center.x /= 2;
		center.y /= 2;
		r->tl = p_sub(center,ofs);
		r->br = p_add(center,ofs);
	}
}

int
rc_zoom(int _ses,
	RADAR_CACHE * rc_ptr,
	RESOURCE * c,
	GB_RECT _r,
	REAL1 _rot)
{
L_CHAR * _crd;
GB_POINT p;
REAL1 reso;
GB_POINT ptr[4];
int i;
REAL1 reso_list[4];
MP_ROUTE * mpr;
URL u;
MAP_HISTORY * mh;
int ses;

	mpr = 0;
	if ( rc_ptr == 0 )
		return 0;
	if ( _ses == 0 )
		ses = open_session(SEST_OPTIMIZE);
	else	ses = _ses;
	_crd = ll_copy_str(get_url_str2(&c->h.entry));

	rlock_base_url(rc_ptr,"gv_zoom");

	if ( rc_ptr->base_url == 0 )
		goto individual;
	if ( l_strcmp(_crd,rc_ptr->base_url) == 0 ) {
		get_center_reso(rc_ptr->gf,&p,&reso,&_r);
		if ( c && c->h.visible_resolution > reso )
			reso = c->h.visible_resolution*1.1;
		if ( rc_ptr->win_reso_max == 0 )
			rc_ptr->win_reso_max = reso;
		wf_goto_point(rc_ptr->gf,_crd,p,_rot,reso);
		wakeup_win_manage(rc_ptr);

log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"GET CENTER RESO1 %f - %ls\n",reso, _crd);
		unlock_base_url(rc_ptr);

		goto end1;
	}

	if ( c->h.type == RT_COORDINATE )
		adjust_rect_by_reso(rc_ptr,&_r,
			c->h.visible_resolution,
			c->h.limit_resolution);
	else	adjust_rect_by_reso(rc_ptr,&_r,
			c->h.visible_resolution,0);

	ptr[0] = _r.tl;
	ptr[1] = _r.br;
	ptr[2].x = _r.tl.x;
	ptr[2].y = _r.br.y;
	ptr[3].x = _r.br.x;
	ptr[3].y = _r.tl.y;
	for ( i = 0 ; i < 4 ; i ++ )
		reso_list[i] = 1;

	{
	L_CHAR * tmp;
		tmp = ll_copy_str(rc_ptr->base_url);
		mpr = resolve_route(_crd,tmp,RR_WM_INDIRECT);
		d_f_ree(tmp);
	}

	if ( mpr == 0 || mpr == MP_NO_ROUTE )
		goto individual;
	get_url2(&u,_crd);
	mh = get_mh_from_route(ses,&u,mpr);

	free_url(&u);
	if ( mh == 0 )
		goto individual;
	map_from_flame(mh,ptr,reso_list,4);

	_r.tl.x = _r.tl.y = 0;
	_r.br.x = _r.br.y = -1;
	for ( i = 0 ; i < 4 ; i ++ )
		insert_rect(&_r,ptr[i]);
	get_center_reso(rc_ptr->gf,&p,&reso,&_r);
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"GET CENTER RESO2-1 %f - %ls\n",reso,rc_ptr->base_url);
/*
	if ( c && c->h.visible_resolution > reso )
		reso = c->h.visible_resolution*1.1;
*/
	if ( rc_ptr->win_reso_max == 0 )
		rc_ptr->win_reso_max = reso;

log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"GET CENTER RESO2-2 %f - %ls\n",reso,rc_ptr->base_url);
	wf_goto_point(rc_ptr->gf,rc_ptr->base_url,p,_rot,reso);
	wakeup_win_manage(rc_ptr);

	unlock_base_url(rc_ptr);

	goto end1;

individual:

	close_session(ses);
	lock_task(radar_lock);
	if ( rc_ptr->base_url )
		d_f_ree(rc_ptr->base_url);
	_free_query_thread_list(rc_ptr,rc_ptr->q_thread_lst,0);
	rc_ptr->q_thread_lst = 0;
	rc_ptr->base_url = ll_copy_str(_crd);
	get_center_reso(rc_ptr->gf,&p,&reso,&_r);
	if ( c && c->h.visible_resolution > reso )
		reso = c->h.visible_resolution*1.1;
	if ( rc_ptr->win_reso_max == 0 )
		rc_ptr->win_reso_max = reso;
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"GET CENTER RESO3 %f - %ls\n",reso,_crd);
	wf_goto_point(rc_ptr->gf,_crd,p,_rot,reso);

	unlock_task(radar_lock,"zoom");

	set_q_mode(rc_ptr);

	query_trigger2(rc_ptr);
	wakeup_win_manage(rc_ptr);

	reset_q_mode(rc_ptr);

	unlock_base_url(rc_ptr);
end1:
	flush_route(mpr);
	if ( _ses == 0 )
		close_session(ses);
/* end2: */
	d_f_ree(_crd);
	return 0;
}


XL_SEXP *
gv_zoom(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
XL_SEXP * crd;
L_CHAR * _crd;
XL_SEXP * r;
GB_RECT _r;
XL_SEXP * rot;
REAL1 _rot;
int ses;
URL u;
RESOURCE * c;
RADAR_CACHE * rc_ptr;

	rc_ptr = get_sf_rc_ptr(sf);
	crd = get_el(s,1);
	if ( get_type(crd) != XLT_STRING )
		goto type_missmatch;
	_crd = crd->string.data;
	c = 0;

	ses = open_session(SEST_OPTIMIZE);

	if ( list_length(s) == 3 ) {

		get_url2(&u,_crd);
	
		c = load_resource(ses,&u,Q_PRI_RADAR);
		free_url(&u);
		if ( c == 0 )
			goto cannot_jmp;

		r = get_el(s,2);
		if ( get_minrect(&c->h.cu,&_r,r) < 0 )
			goto type_missmatch;
		_rot = 0;
	}
	else if ( list_length(s) == 4 ) {

		get_url2(&u,_crd);

		c = load_resource(ses,&u,Q_PRI_RADAR);
		free_url(&u);
		if ( c == 0 )
			goto cannot_jmp;

		r = get_el(s,2);
		if ( get_minrect(&c->h.cu,&_r,r) < 0 )
			goto type_missmatch;

		rot = get_el(s,3);
		switch ( get_type(rot) ) {
		case XLT_ERROR :
			return rot;
		case XLT_FLOAT :
			_rot = rot->floating.data;
			break;
		case XLT_INTEGER :
			_rot = rot->integer.data;
			break;
		default :
			goto type_missmatch;
		}
	}
	else {

		_rot = 0;
		get_url2(&u,_crd);
	
		c = load_resource(ses,&u,Q_PRI_RADAR);


		free_url(&u);
		if ( c == 0 )
			goto cannot_jmp;
		_r = c->h.minrect;
	}

log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"GV_ZOOM (%f %f)-(%f %f)\n",
_r.tl.x,
_r.tl.y,
_r.br.x,
_r.br.y);

	rc_zoom(ses,rc_ptr,c,_r,_rot);
	return 0;

type_missmatch:
	close_session(ses);
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"gv-zoom"),
		List(n_get_string("type missmatch"),
			-1));
cannot_jmp:
	close_session(ses);
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"gv-zoom"),
		List(n_get_string("cannot jmp"),
			-1));
}

REAL1
get_win_rect(GBVIEW_FLAME * gf,GB_RECT * rp)
{
SURP_SET surp;
REAL1 ret_reso;
GB_RECT * _ret,ret;
int nos;

	wf_lock(gf);
	ret.tl.x = ret.tl.y = 0;
	ret.br.x = gf->win_width;
	ret.br.y = gf->win_height;
	set_surp(&surp,&ret,gf->flame_base_resolution);
	map_from_flame(&gf->flame_base_display_map,
			surp.ptr,
			surp.reso,
			SURP_NOS);
//	_ret = get_surp_rect(&nos,&surp,gf->flame_base->draw);
	_ret = get_surp_rect(&nos,&surp,0);
	if ( nos > 1 )
		er_panic("get_win_rect");
	if ( _ret ) {
		ret = *_ret;
		d_f_ree(_ret);
		ret_reso = surp.reso[SURP_NOS-1];
		wf_unlock(gf);
		*rp = ret;
		return ret_reso;
	}
	else {
		wf_unlock(gf);
		return -1;
	}
}


typedef struct cr_work {
	int		count[CRT_MAX+1];
	char		flags[CRT_MAX+1];
	L_CHAR *	base_url;
	int		loading_cnt;
	int		que_len;
	RADAR_INDICATE	ri;
	RADAR_CACHE *	rc_ptr;
} CR_WORK;

int check_routing(SYS_QUEUE * q,T_RESOURCE_TO_INSERT * n,CR_WORK * w);
void reset_cr_work(RADAR_CACHE * rc_ptr,CR_WORK * w);

int
check_routing(SYS_QUEUE * q,T_RESOURCE_TO_INSERT * n,CR_WORK * w)
{
int c;
int ret;

int sts1[2] = {
	LRWE_HANDLING,
	LRWE_DUP
};
int sts2[1] = {
	LRWE_OK
};
#define STS_LEN	2

	w->que_len ++;
	ret = 0;
	if ( w->base_url == 0 ) {
		ret = -1;
		goto end;
	}
	if ( check_lrw_status(n->lr_crd,sts1,STS_LEN,0,0) == 0 ) {
		ret = -1;
		goto end;
	}
	if ( check_lrw_status(n->lr_crd,sts2,1,0,RF_COMPLETE) == 0 ) {
		ret = -1;
		goto end;
	}
	set_lrw_err(n->lr_crd,LRWE_COMPLETE);
	if ( n->lr_obj ) {
		if ( check_lrw_status(n->lr_obj,sts1,STS_LEN,0,0) == 0 ) {
			ret = -1;
			goto end;
		}
		if ( check_lrw_status(n->lr_obj,sts2,1,0,RF_COMPLETE) == 0 ) {
			ret = -1;
			goto end;
		}
		set_lrw_err(n->lr_obj,LRWE_COMPLETE);
	}
end:
/*
	switch ( n->mappath_loading ) {
	case 0:
		c = check_mappath(w->base_url,n->crd_path,0);
		break;
	case 1:
*/
		c = check_mappath(w->base_url,n->crd_path,1);
		n->mappath_loading = 0;
		w->loading_cnt --;
/*
	case 2:
		c = check_mappath(w->base_url,n->crd_path,0);
		if ( c == CRT_LOADING_RES )
			c = CRT_LOADING_RES_RESOLVE;
		else	n->mappath_loading = 0;
		break;
	}
*/

// if ( w->rc_ptr == radar_cache_list )
//log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"ret %i %i %ls : %x\n",ret,c,n->crd_path,w->flags[c]);
//ss_printf("ret %i %i %ls : %x\n",ret,c,n->crd_path,w->flags[c]);

	if ( ret == 0 )
		w->ri.d.ready_res[c] ++;
	else	w->ri.d.loading_res[c] ++;

	if ( ret == 0 ) {
		w->count[c] ++;
		if ( w->flags[c] )
			return ret;
		return -1;
	}
	else if ( c != CRT_EXIST ) {
		w->count[c] ++;
		if ( w->flags[c] )
			return ret;
		return -1;
	}
	return -1;
}

void
reset_cr_work(RADAR_CACHE * rc_ptr,CR_WORK * w)
{
int i;
	for ( i = 0 ; i < CRT_MAX+1 ; i ++ ){
		w->count[i] = 0;
		w->flags[i] = 0;
	}
	w->que_len = 0;
	rlock_base_url(rc_ptr,"reset_cr_work");
	if ( w->base_url )
		d_f_ree(w->base_url);
	if ( rc_ptr->base_url )
		w->base_url = ll_copy_str(rc_ptr->base_url);
	else	w->base_url = 0;
	w->rc_ptr = rc_ptr;
	memset(&w->ri,0,sizeof(w->ri));
	unlock_base_url(rc_ptr);
}

L_CHAR * test_path;

void
beam_insert_task(TKEY d)
{
GB_RECT r;
REAL1 reso;
T_RESOURCE_TO_INSERT * n;
XL_INTERPRETER * xli;
int ses;
CR_WORK cr;
int ret;
T_RESOURCE_TO_INSERT * last;
int last_crt;
SYS_QUEUE * que;
L_CHAR * key;
RADAR_CACHE * rc_ptr;

	que = (SYS_QUEUE *)GET_TKEY(d);
	key = touch_qkey(que);
	if ( key == 0 )
		return;

	cr.base_url = 0;

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

	ses = open_session(SEST_OPTIMIZE);
	rc_ptr = que->work;

	cr.loading_cnt = 0;
	last = 0;
	last_crt = -1;
	for ( ; ; ) {
		if ( rc_ptr->status & GVFM_ZONBIE ) {
			for ( ; ; ) {
				n = delete_queue(&rc_ptr->resource_to_insert,
					0,0,0);
				if ( n == 0 )
					break;
				free_resource_to_insert(n);
			}
			break;
		}
		gc_push(0,0,"beam_insert_task");
		reset_cr_work(rc_ptr,&cr);
		if ( cr.base_url ) {
			ret = check_queue(&rc_ptr->resource_to_insert,
					check_routing,&cr);
			lock_task(radar_lock);
			call_indicate_event(rc_ptr,
				copy_ri(&rc_ptr->ri,&cr.ri));
			if ( cr.que_len == 0 ) {
				gc_pop(0,0);
				break;
			}
			if ( cr.count[CRT_EXIST] ) {
				last = 0;
				last_crt = -1;
				cr.flags[CRT_EXIST] = 1;
				n = delete_queue(&rc_ptr->resource_to_insert,
					check_routing,&cr,0);
				if ( n == 0 )
					goto loading;
				goto ok;
			}
			if ( cr.count[CRT_ROUTING_EXIST] ) {
/*
				if ( cr.loading_cnt > 10 )
					goto loading;
*/
				cr.flags[CRT_ROUTING_EXIST] = 1;
				n = delete_queue(&rc_ptr->resource_to_insert,
					check_routing,&cr,0);
				if ( n == 0 )
					goto loading;
				n->mappath_loading = 1;
				cr.loading_cnt ++;
				insert_queue(&rc_ptr->resource_to_insert,n,1);
				if ( last == n && last_crt == CRT_ROUTING_EXIST ) {
					goto loading;
				}
				else {
					last = n;
					last_crt = CRT_ROUTING_EXIST;
					goto imidiate;
				}
			}
			if ( cr.count[CRT_NOTHING] ) {
				cr.flags[CRT_NOTHING] = 1;
				n = delete_queue(&rc_ptr->resource_to_insert,
					check_routing,&cr,0);
				if ( n == 0 )
					goto loading;
				flush_route(resolve_route(
					cr.base_url,
					n->crd_path,
					RR_WM_NO_WAIT));
				insert_queue(&rc_ptr->resource_to_insert,n,1);
				if ( last == n && last_crt == CRT_NOTHING ) {
					goto loading;
				}
				else {
					last = n;
					last_crt = CRT_NOTHING;
					goto imidiate;
				}
			}
			if ( cr.count[CRT_ERROR] ) {
				cr.flags[CRT_ERROR] = 1;
				n = delete_queue(&rc_ptr->resource_to_insert,
					check_routing,&cr,1);
				last = 0;
				last_crt = -1;
				goto err;
			}
			goto loading;
		}
		else {
			n = delete_queue(&rc_ptr->resource_to_insert,
					0,0,0);
			if ( n == 0 ) {
				gc_pop(0,0);
				break;
			}
		}
	ok:
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"insert_task del %i\n",get_tid());
*/
		wlock_base_url(rc_ptr,"beam_insert_task");

		if ( rc_ptr->base_url == 0 ) {
			if ( goto_zoom(rc_ptr,ses,rc_ptr->gf,n->crd_path) >= 0 ) {
				if ( rc_ptr->base_url )
					d_f_ree(rc_ptr->base_url);
				rc_ptr->base_url = 
					ll_copy_str(n->crd_path);
				reso = get_win_rect(rc_ptr->gf,&r);
				lock_task(radar_lock);
				rc_ptr->first_max = rc_ptr->win_reso_max = reso;
				rc_ptr->first_r = rc_ptr->win_rect = r;
				wakeup_task((int)&rc_ptr->first_max);
				unlock_task(radar_lock,
					"beam_insert_task");
			}
		}
		unlock_base_url(rc_ptr);

		rc_task_lock(rc_ptr,TM_INS);


 		_insert_radar_url(rc_ptr,n->qt_id,ses,n->crd_path,n->obj_path);

		rc_task_unlock(rc_ptr,TM_INS);


		wakeup_win_manage(rc_ptr);

		gc_pop(0,0);

		free_resource_to_insert(n);

		wakeup_retrieve_lump_task(rc_ptr);
		continue;
	err:
		gc_pop(0,0);

		free_resource_to_insert(n);
		continue;

	loading:
		gc_pop(0,0);
		sleep_sec(3);
		continue;
	imidiate:
		gc_pop(0,0);
	}


	release_qkey(que,key);
	d_f_ree(key);

	close_session(ses);
	close_self_interpreter();

}

int
loading_first(RADAR_CACHE * rc_ptr,int qt_id,GB_RECT * last_r,REAL1 * last_max,int ses)
{
GB_RECT r;

	r.tl.x = r.tl.y = 0;
	r.br.x = r.br.y = -1;
	gc_push(0,0,"loading_first");
	beam_to_lump(rc_ptr,ses,&r,0,0,qt_id);
	gc_pop(0,0);
	rc_ptr->first_max = 0;
	if ( rc_ptr->query_mode )
		return -1;
	*last_r = rc_ptr->first_r;
	*last_max = rc_ptr->first_max;
	return 0;
}

int
_loading_lump(
	RADAR_CACHE * rc_ptr,
	int qt_id,
	int ses,
	GB_RECT * r,
	REAL1 min,
	REAL1 max)
{
void * sss;

	gc_push(0,0,"loading_lump");
sss = get_gc_check_point();
	beam_to_lump(rc_ptr,ses,r,min,max,qt_id);
compare_gc_check_point("_loading_lump",sss);
	gc_pop(0,0);
	return 0;
}

void
_turning_loaded_reso(RADAR_MATRIX * mx,REAL1 lr)
{
int x,y;
	for ( x = 0 ; x < 2 ; x ++ )
		for ( y = 0 ; y < 2 ; y ++ ) {
			if ( mx->mx[x][y] == 0 )
				continue;
			if ( mx->mx[x][y]->loaded_reso 
					== mx->mx[x][y]->resolution*2 )
				continue;
			if ( mx->mx[x][y]->loaded_reso > lr ) {
				mx->loaded_reso = lr;
				_turning_loaded_reso(mx->mx[x][y],lr);
			}
		}
}

void
turning_loaded_reso(RADAR_MATRIX * mx)
{
RADAR_MATRIX * p;
REAL1 lr;
int x,y;

	for ( p = mx->parent ; p ; p = p->parent ) {
		lr = 0;
		for ( x = 0 ; x < 2 ; x ++ )
			for ( y = 0 ; y < 2 ; y ++ ) {
				if ( p->mx[x][y] == 0 )
					goto next;
				if ( lr < p->mx[x][y]->loaded_reso )
					lr = p->mx[x][y]->loaded_reso;
			}
		if ( lr < p->loaded_reso )
			p->loaded_reso = lr;
	next:	{}
	}
	lr = mx->loaded_reso;
	_turning_loaded_reso(mx,lr);
}

int
_loading_cube(RADAR_CACHE * rc_ptr,int qt_id,int ses,RADAR_MATRIX * mx,REAL1 min,REAL1 max)
{
RADAR_MATRIX * p;
GB_RECT r;

/*
if ( rc_ptr->matrix && check_fnan(rc_ptr->matrix->resolution) < 0 )
er_panic("fnan(1)");
*/

	if ( mx->resolution*2 != max )
		er_panic("loading_cube(1)");
	if ( mx->loaded_reso <= min )
		return 0;
	r.tl = mx->rect[0][0].tl;
	r.br = mx->rect[1][1].br;
	if ( mx->parent == 0 )
		goto no_parent;
	for ( p = mx->parent ;
		p &&
		p->loaded_reso == p->resolution*2 ;
		p = p->parent );
	if ( p == 0 )
		goto no_parent;
/* exist_parent: */

	if ( p->loaded_reso <= min ) {
		if ( _loading_lump(rc_ptr,qt_id,ses,&r,p->resolution*2,mx->loaded_reso)
				< 0 )
			return -1;
		mx->loaded_reso = p->loaded_reso;
	}
	else {
		if ( _loading_lump(rc_ptr,qt_id,ses,&r,min,mx->loaded_reso) < 0 )
			return -1;
		mx->loaded_reso = min;
	}
	turning_loaded_reso(mx);
	return 0;
no_parent:

	_loading_lump(rc_ptr,qt_id,ses,&r,min,mx->loaded_reso);
	mx->loaded_reso = min;
	turning_loaded_reso(mx);
	return 0;
}

int
loading_matrix(
	RADAR_CACHE * rc_ptr,
	int qt_id,
	GB_RECT * last_r,
	REAL1 * last_window,REAL1 * last_max,int ses)
{
GB_RECT r;
REAL1 max,min,reso;
RADAR_MATRIX_LIST * lst, * lst2;
REAL1 window,_max,_min;
Q_THREAD_LIST * qt;
int pri;

	pri = push_pri(PRI_NETWORK);
	lock_task(radar_lock);
	qt = _search_q_thread(rc_ptr,qt_id);
	if ( qt == 0 ) {
		unlock_task(radar_lock,"loading_matrix");
		change_pri(0,pri);
		return -1;
	}
	if ( rc_ptr->base_url == 0 ) {

		if ( loading_first(rc_ptr,qt->qth->id,last_r,last_max,ses) < 0 ) {
			unlock_task(radar_lock,"loading_matrix");
			change_pri(0,pri);
			return -1;
		}

		*last_window = rc_ptr->win_reso_window;
		if ( qt->matrix == 0 ) {
			unlock_task(radar_lock,"loading_matrix");
			change_pri(0,pri);
			return 0;
		}
	}
/* retry_search: */


	r = rc_ptr->win_rect;
	window = rc_ptr->win_reso_window;
	max = rc_ptr->win_reso_max;
	lst = _get_radar_matrix(rc_ptr,qt,max,&r,1);


	if ( lst == 0 )
		er_panic("load_matrix(1)");
	min = max/window;
	for ( reso = lst->mx->resolution;
			reso >= min ; reso = reso / 2 );
	_max = lst->mx->resolution*2;
	_min = reso;
/*
if ( check_fnan(_max) < 0 )
er_panic("lm(1)");
if ( check_fnan(_min) < 0 )
er_panic("lm(2)");
*/


	for ( lst2 = lst ; lst2 ; lst2 = lst2->next )

		if ( _loading_cube(rc_ptr,qt_id,ses,lst2->mx,_min,_max) < 0 ) {
			unlock_task(radar_lock,"loading_matrix");
			change_pri(0,pri);
			return -1;
		}

	*last_r = r;
	*last_window = window;
	*last_max = max;

	unlock_task(radar_lock,"loading_matrix");
	change_pri(0,pri);

	return 0;

}


int
min_route_radar_pre_handle(RADAR_CACHE * rc_ptr)
{
RADAR_CRD * c;
L_CHAR * b_url,*c_path;

	c = 0;
	lock_task(radar_lock);
	_rlock_base_url(rc_ptr,"min_route_radar");
retry:
	if ( c == 0 )
		c = rc_ptr->crd[0].next;
	else 	c = c->next;
	if ( c == &rc_ptr->crd[0] ) {
		_unlock_base_url(rc_ptr);
		unlock_task(radar_lock,"min_route");
		return 0;
	}
	if ( c->lock )
		goto retry;
	if ( c->resolution == 0 ) {
		goto retry;
	}
	if ( c->base_url == 0 )
		goto do_ptr;
	if ( l_strcmp(c->base_url,rc_ptr->base_url) == 0 ) {
		goto retry;
	}
do_ptr:

	b_url = ll_copy_str(rc_ptr->base_url);
	c_path = ll_copy_str(c->crd_path);
	
	_unlock_base_url(rc_ptr);
	unlock_task(radar_lock,"min_route_radar");

	flush_route(resolve_route(b_url,c_path,RR_WM_DIRECT));

	d_f_ree(b_url);
	d_f_ree(c_path);
	return 1;
}

int
min_route_radar(RADAR_CACHE * rc_ptr,int ses)
{
int ret;
RADAR_CRD * c, *cc;
RADAR_NODE ** np1, ** np2, * n;
RADAR_MATRIX * mx;
int f,ff;
RADAR_MATRIX_LIST * lst,* lst2;
Q_THREAD_LIST ** qtp, ** qtl;
GB_RECT ins_r;

	c = 0;
	lock_task(radar_lock);
	_rlock_base_url(rc_ptr,"min_route_radar");
retry:
	if ( c == 0 )
		c = rc_ptr->crd[0].next;
	else 	c = c->next;
retry2:
	if ( c == &rc_ptr->crd[0] ) {
		_unlock_base_url(rc_ptr);
		unlock_task(radar_lock,"min_route");
		return 0;
	}
	if ( c->lock )
		goto retry;
	if ( c->resolution == 0 ) {
		cc = c->next;
		_delete_node_from_crd(c);
		_free_radar_crd(rc_ptr,c);
		c = cc;
		goto retry2;
	}
	c->lock = -1;
	if ( c->base_url == 0 )
		goto do_ptr;
	if ( l_strcmp(c->base_url,rc_ptr->base_url) == 0 ) {
		_flush_radar_crd(c);
		goto retry;
	}
do_ptr:

	unlock_task(radar_lock,"min_route");
	ret = set_ptr_list(rc_ptr,ses,c);
	lock_task(radar_lock);
	if ( ret < 0 ) {
		cc = c->next;
		_delete_node_from_crd(c);
		_free_radar_crd(rc_ptr,c);
		c = cc;
		goto retry2;
	}
	f = 0;
	qtl = 0;
	for ( np1 = &c->list ; *np1 ; ) {
		mx = (*np1)->matrix;
		n = *np1;
		for ( np2 = &mx->list ; *np2 ;
				np2 = &(*np2)->matrix_next )
			if ( *np2 == n )
				break;
		if ( *np2 == 0 )
			er_panic("min_route_radar");
		*np1 = n->crd_next;
		*np2 = n->matrix_next;
		d_f_ree(n);
		f = 1;
		mx->loaded_reso = mx->resolution*2;
		qtl = insert_q_thread_list_ptr(qtl,mx->root_qt);
	}
	if ( f ) {
		qtp = qtl;
		for ( ; *qtp ; qtp ++  ) {
			lst = _get_radar_matrix(rc_ptr,*qtp,c->resolution,
				&c->minrect,0);
			for ( lst2 = lst ; lst2 ; lst2 = lst2->next )
				_insert_radar_matrix(rc_ptr,lst2->mx,c);
			_free_radar_matrix_list(lst);

			ins_r = get_fitting_rect(&ff,&c->minrect,c->resolution,rc_ptr,*qtp);
			if ( ff ) {
				insert_rect(&(*qtp)->large_crd,ins_r.tl);
				insert_rect(&(*qtp)->large_crd,ins_r.br);
				c->flags |= RCF_LARGE_CRD;
			}
			lst = _get_radar_matrix(rc_ptr,*qtp,c->resolution,&ins_r,1);
			for ( lst2 = lst ; lst2 ; lst2 = lst2->next )
				_insert_radar_matrix(rc_ptr,lst2->mx,c);
			_free_radar_matrix_list(lst);
		}
	}
	if ( qtl )
		d_f_ree(qtl);
	_unlock_base_url(rc_ptr);
	unlock_task(radar_lock,"min_route_radar");
	flush_radar_crd(c);
	return 1;
}

/* sethomestatus
void
opening_timer()
{
	set_opening_state(OS_RUN);
}
*/

void
_wakeup_loading_task(RADAR_CACHE * rc_ptr)
{
	if ( rc_ptr->status != GVFS_ACTIVE )
		return;
	if ( rc_ptr->loading_task_wp == 0 ) {
		rc_ptr->loading_task_wp ++;
		create_task(loading_task,(int)rc_ptr,PRI_FETCH_RADAR);
	}
	rc_ptr->loading_task_req = 1;
	wakeup_task((int)&rc_ptr->loading_task_wp);
}

void
wakeup_loading_task(RADAR_CACHE * rc_ptr)
{
	lock_task(radar_lock);
	_wakeup_loading_task(rc_ptr);
	unlock_task(radar_lock,"wakeup_loading_task");
}


void
loading_task(TKEY d)
{
XL_INTERPRETER * xli;
int ses;
GB_RECT r,gr;
REAL1 g_reso_max,reso_max;
REAL1 g_reso_window,reso_window;
RADAR_CACHE * rc_ptr;
int * id_list;
int i;



	rc_ptr = (RADAR_CACHE*)GET_TKEY(d);

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

	ses = open_session(SEST_OPTIMIZE);

	r.tl.x = r.tl.y = 0;
	r.br.x = r.br.y = -1;
	reso_window = 0;
	reso_max = 0;

	lock_task(radar_lock);
	rc_ptr->loading_task_active ++;
/* sethomestatus
	new_tick(opening_timer,-OPENING_TIMEOUT,0);
	for ( ; opening_state < OS_RUN ; ) {
		_set_opening_state(OS_STANBY);
		sleep_task((int)&opening_state,radar_lock);
		lock_task(radar_lock);
	}
*/
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"START !!\n");
*/
	for ( ; ; ) {
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"START Loaindg\n");
*/
		g_reso_max = rc_ptr->win_reso_max;
		g_reso_window = rc_ptr->win_reso_window;
		gr = rc_ptr->win_rect;
		if ( rc_ptr->win_force ) {
			rc_ptr->win_force = 0;
			goto start;
		}
		if ( g_reso_max == 0 )
			goto sleep;
		if ( g_reso_window != reso_window )
			goto start;
		if ( g_reso_max != reso_max )
			goto start;
		if ( r.tl.x != gr.tl.x )
			goto start;
		if ( r.tl.y != gr.tl.y )
			goto start;
		if ( r.br.x != gr.br.x )
			goto start;
		if ( r.br.y != gr.br.y )
			goto start;
	sleep:
		rc_ptr->win_delete_lock = 0;
		_wakeup_win_manage(rc_ptr);

		_rc_task_unlock(rc_ptr,TM_LOAD);

		new_timeout((int)&rc_ptr->loading_task_wp,5);
		rc_ptr->loading_task_active --;
		sleep_task((int)&rc_ptr->loading_task_wp,radar_lock);
		del_timeout((int)&rc_ptr->loading_task_wp);

		lock_task(radar_lock);
		rc_ptr->loading_task_active ++;
		if ( rc_ptr->loading_task_req ) {
			rc_ptr->loading_task_req = 0;
			continue;
		}
		rc_ptr->loading_task_wp --;
		rc_ptr->loading_task_active --;
		unlock_task(radar_lock,"loading_task");

		close_session(ses);
		close_self_interpreter();
		return;
		

	start:

		unlock_task(radar_lock,"loading_task");

	loading_loop:

		set_l_mode(rc_ptr);
		rc_task_lock(rc_ptr,TM_LOAD);
		if ( rc_ptr->remake_req )
			goto next;

		id_list = get_valid_qt_id_list(rc_ptr);
		if ( id_list ) {
			for ( i = 0 ; id_list[i] ; i ++ ) {
				if ( loading_matrix(rc_ptr,
						id_list[i],
						&r,&reso_window,&reso_max,ses)
						< 0 ) {

					rc_task_unlock(rc_ptr,TM_LOAD);
					reset_l_mode(rc_ptr);

					d_f_ree(id_list);
					goto loading_loop;
				}
			}
			d_f_ree(id_list);
		}
	next:


		rc_task_unlock(rc_ptr,TM_LOAD);
		reset_l_mode(rc_ptr);
		if ( rc_ptr->remake_req )
			sleep_sec(1);

		lock_task(radar_lock);
		rc_ptr->win_load = 1;
		rc_ptr->win_delete_lock = 0;
		_wakeup_win_manage(rc_ptr);

	}
}


void
_wakeup_min_route_task(RADAR_CACHE * rc_ptr)
{
	if ( rc_ptr->status != GVFS_ACTIVE )
		return;
	if ( rc_ptr->min_route_task_wp == 0 ) {
		rc_ptr->min_route_task_wp ++;
		create_task(min_route_task,(int)rc_ptr,PRI_FETCH_RADAR);
	}
	rc_ptr->min_route_task_req = 1;
	wakeup_task((int)&rc_ptr->min_route_task_wp);
}

void
wakeup_min_route_task(RADAR_CACHE * rc_ptr)
{
	lock_task(radar_lock);
	_wakeup_min_route_task(rc_ptr);
	unlock_task(radar_lock,"wakeup_min_route_task");
}


void
min_route_task(TKEY d)
{
XL_INTERPRETER * xli;
int ses;
int ret;
int min_ret;
RADAR_CACHE * rc_ptr;


	rc_ptr = (RADAR_CACHE*)GET_TKEY(d);
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"min_route task\n");
*/
	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);

	ses = open_session(SEST_OPTIMIZE);

	lock_task(radar_lock);
	rc_ptr->min_route_task_active ++;
	unlock_task(radar_lock,"min_route_task");
	for ( ; ; ) {

		min_ret = 0;
		lock_task(radar_lock);
	remake:
		if ( rc_ptr->win_remake || min_ret ) {
			rc_ptr->win_remake = 0;

/*
			_rc_task_lock(TM_MIN);
*/
			unlock_task(radar_lock,"min_route_task");
			min_ret = min_route_wf(rc_ptr->gf,ses);

log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"min_ret = %i\n",min_ret);

			lock_task(radar_lock);
/*
			_rc_task_unlock(TM_MIN);
*/
		}
		unlock_task(radar_lock,"min_route");

		for ( ; ; ) {
			lock_task(radar_lock);
			if ( rc_ptr->win_remake )
				goto remake;
			unlock_task(radar_lock,"min_route");

			min_route_radar_pre_handle(rc_ptr);

			rc_task_lock(rc_ptr,TM_MIN);
			ret = min_route_radar(rc_ptr,ses);
			rc_task_unlock(rc_ptr,TM_MIN);
			lock_task(radar_lock);
			if ( rc_ptr->win_remake )
				goto remake;
			if ( ret == 0 ) {
				break;
			}
			unlock_task(radar_lock,"min_route");
			sleep_sec(2);

			lock_task(radar_lock);
			if ( min_ret )
				goto remake;
			unlock_task(radar_lock,"min_route");
		}

/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"minroute %i\n",get_tid());
if ( rc_ptr->matrix ) {
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"(%f %f)-(%f %f)\n",
rc_ptr->matrix->rect[0][0].tl.x,
rc_ptr->matrix->rect[0][0].tl.y,
rc_ptr->matrix->rect[1][1].br.x,
rc_ptr->matrix->rect[1][1].br.y);
}
*/

		new_timeout((int)&rc_ptr->min_route_task_wp,5);
		rc_ptr->min_route_task_active --;
		sleep_task((int)&rc_ptr->min_route_task_wp,radar_lock);
		del_timeout((int)&rc_ptr->min_route_task_wp);
		lock_task(radar_lock);
		rc_ptr->min_route_task_active ++;
		if ( rc_ptr->min_route_task_req == 0 ) {
			rc_ptr->min_route_task_wp --;
			rc_ptr->min_route_task_active --;
			unlock_task(radar_lock,"min_route_task");
			close_session(ses);
			close_self_interpreter();
			return;
		}
		rc_ptr->min_route_task_req = 0;
		unlock_task(radar_lock,"min_route_task");
	}
}

/***/
void
_wakeup_win_manage(RADAR_CACHE * rc_ptr)
{
	if ( rc_ptr->status != GVFS_ACTIVE )
		return;
	if ( rc_ptr->win_manage_task_wp == 0 ) {
		create_task(win_manage_task,(int)rc_ptr,PRI_FETCH_RADAR);
		rc_ptr->win_manage_task_wp ++;
	}
	rc_ptr->win_manage_task_req = 1;
	wakeup_task((int)&rc_ptr->win_manage_task_wp);
}
void
wakeup_win_manage(RADAR_CACHE * rc_ptr)
{
	lock_task(radar_lock);
	_wakeup_win_manage(rc_ptr);
	unlock_task(radar_lock,"wakeup_win_manage");
}


void
re_lock_base(RADAR_CACHE * rc_ptr)
{
	lock_task(radar_lock);
	rc_ptr->win_load = 1;
	rc_ptr->base_change_flag = 0;
	_wakeup_win_manage(rc_ptr);
	unlock_task(radar_lock,"wakeup_win_manage");
}

/***/
void
win_manage_task(TKEY d)
{
XL_INTERPRETER * xli;
int ses;
GB_RECT r,gr;
REAL1 g_reso,reso;
WF_ID ret,next;
int rr;
RADAR_CACHE * rc_ptr;

log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"---------------- W WIN_MANAGE\n");

	rc_ptr = (RADAR_CACHE*)GET_TKEY(d);
	lock_task(radar_lock);
	rc_ptr->win_manage_task_active ++;
	unlock_task(radar_lock,"win_manage_task");

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

	ses = open_session(SEST_OPTIMIZE);

	r.tl.x = r.tl.y = 0;
	r.br.x = r.br.y = -1;
	reso = -1;

	for ( ; ; ) {

		lock_task(radar_lock);
		if ( wf_get_current(rc_ptr->gf) == 0 ) {
			goto sleep;
		}
		g_reso = get_win_rect(rc_ptr->gf,&gr);
		if ( rc_ptr->win_load ) {
			rc_ptr->win_load = 0;
			goto start;
		}
		if ( rc_ptr->gf->move_flag ) {
			rc_ptr->gf->move_flag = 0;
			rc_ptr->base_change_flag = 0;
			goto start;
		}
/*
		if ( g_reso != reso )
			goto start;
		if ( r.tl.x != gr.tl.x )
			goto start;
		if ( r.tl.y != gr.tl.y )
			goto start;
		if ( r.br.x != gr.br.x )
			goto start;
		if ( r.br.y != gr.br.y )
			goto start;
*/
	sleep:
/*
		clean_radar_matrix();
*/
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"sleep win_manage %i\n",get_tid());
*/

		_rc_task_unlock(rc_ptr,TM_WMAN);
		new_timeout((int)&rc_ptr->win_manage_task_wp,2);
		rc_ptr->win_manage_task_active --;
		sleep_task((int)&rc_ptr->win_manage_task_wp,radar_lock);

		lock_task(radar_lock);
		rc_ptr->win_manage_task_active ++;
		del_timeout((int)&rc_ptr->win_manage_task_wp);
		if ( rc_ptr->win_manage_task_req ) {
			rc_ptr->win_manage_task_req = 0;
			unlock_task(radar_lock,"win_manage_task");
			continue;
		}

		rc_ptr->win_manage_task_wp --;
		rc_ptr->win_manage_task_active --;
		unlock_task(radar_lock,"win_manage_task");
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"---------------- W WIN_MANAGE END\n");
*/
		close_session(ses);
		close_self_interpreter();
		return;

	start:
/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"win_manage start!!\n");
*/
		_rc_task_lock(rc_ptr,TM_WMAN);
		unlock_task(radar_lock,"win_manage_task");
		r = gr;
		reso = g_reso;
/*
log_printf(LOG_MESSAGE,LOG_LAYER_GB,0,"win_manage (%f %f)-(%f %f) %f\n",
r.tl.x,
r.tl.y,
r.br.x,
r.br.y,
reso);
*/
		rc_ptr->delete_insert_flag = 0;
		if ( r.tl.x != r.br.x && r.tl.y != r.br.y )
			ret = win_manage(rc_ptr,&next,ses,reso,&r);
		else {
			ret = 0;
			next = 0;
		}

/*
log_printf(LOG_DEBUG,LOG_LAYER_GB,0,"** win_manage %i\n",ret);
*/


		rc_task_unlock(rc_ptr,TM_WMAN);

		if ( ret >= 0 ) {
			if ( rc_task_lock_check(rc_ptr,TM_REMK) == 0 ) {
				rc_task_lock(rc_ptr,TM_REMK);

				if ( ret == 0 ) {
					if ( rc_ptr->base_change_flag == 0 ||
							rc_ptr->delete_insert_flag == 1 )
						rr = remake_cache(rc_ptr,ses,
							RCT_CHANGE,ret,next);
				}
				else	rr = remake_cache(rc_ptr,ses,
							RCT_DELETE,ret,next);

				lock_task(radar_lock);
				_rc_task_unlock(rc_ptr,TM_REMK);

				if ( rr ) {
					rc_ptr->win_remake = 1;
					_wakeup_min_route_task(rc_ptr);
				}
				unlock_task(radar_lock,"remake");
			}
			rc_ptr->remake_req = 0;
			wakeup_loading_task(rc_ptr);
			continue;
		}
		else {
			rc_ptr->remake_req = 1;

			if ( rc_task_lock_check(rc_ptr,TM_REMK) )
				continue;

		}


		rc_task_lock(rc_ptr,TM_REMK);
		remake_cache(rc_ptr,ses,RCT_DELETE,ret,next);
		rc_ptr->remake_req = 0;

		lock_task(radar_lock);
		_rc_task_unlock(rc_ptr,TM_REMK);

		rc_ptr->win_remake = 1;
		unlock_task(radar_lock,"remake");
		wakeup_loading_task(rc_ptr);
		wakeup_min_route_task(rc_ptr);
	}
}

L_CHAR *
get_q_thread_subtitle(QUERY_THREAD * qth)
{
char * format1, * format2, * format3;
L_CHAR * ret;
	format1 = d_alloc(1000);
	format2 = d_alloc(1000);
	format3 = d_alloc(1000);
	if ( qth->url ) {
		ret = l_string(std_cm,"*");
	}
	else {
		if ( valid_gb_time(&qth->content_period_from) == 0 ) {
			if ( valid_gb_time(&qth->content_period_to) == 0 ) {
				gb_time_format(format1,&qth->content_period_from);
				gb_time_format(format2,&qth->content_period_to);
				sprintf(format3,"%s / %s",format1,format2);
			}
			else {
				gb_time_format(format1,&qth->content_period_from);
				sprintf(format3,"%s /",format1);
			}
		}
		else {
			if ( valid_gb_time(&qth->content_period_to) == 0 ) {
				gb_time_format(format2,&qth->content_period_to);
				sprintf(format3,"/ %s",format2);
			}
			else {
				sprintf(format3,"*");
			}
		}
		ret = l_string(std_cm,format3);
	}
	d_f_ree(format1);
	d_f_ree(format2);
	d_f_ree(format3);
	return ret;
}

L_CHAR *
get_q_thread_title(QUERY_THREAD * qth)
{
	if ( qth->title )
		return qth->title;
	if ( qth->url )
		return qth->url;
	if ( qth->property )
		return qth->property;
	return get_q_thread_subtitle(qth);
}



int rc_warp(
	RADAR_CACHE * rc_ptr,
	int type,
	GB_RECT * rect,
	GB_POINT * center,
	REAL1 resolution,
	REAL1 rotate,
	L_CHAR * target)
{
int ses;
RESOURCE * c;
int ret;
URL u;
	ses = open_session(SEST_OPTIMIZE);
	switch ( type ) {
	case WT_RECT:
		get_url2(&u,target);
		c = load_resource(ses,&u,Q_PRI_RADAR);
		ret = rc_zoom(ses,
			rc_ptr,
			c,
			*rect,
			rotate);
		break;
	case WT_CENTER:
		ret = wf_goto_point(rc_ptr->gf,target,*center,rotate,resolution);
		break;
	case WT_TARGET:
		ret = goto_zoom(rc_ptr,ses,rc_ptr->gf,target);
		break;
	default:
		ret = -1;
	}
	if ( ret == 0 )	{
		rc_task_lock(rc_ptr,TM_INS);
 		_insert_radar_url(rc_ptr,0,ses,target,target);
		rc_task_unlock(rc_ptr,TM_INS);
		wakeup_retrieve_lump_task(rc_ptr);
	}
	close_session(ses);
	return ret;
}


int
get_rc_loading_status(RADAR_CACHE * rc_ptr,RC_LOADING_STATUS * rcs)
{
int ret;
	ret = 0;
	memset(rcs,0,sizeof(*rcs));
	lock_task(radar_lock);
	if ( rc_ptr == 0 ) {
		ret = -1;
		goto end;
	}
	if ( rc_ptr->status & GVFM_ZONBIE ) {
		ret = -1;
		goto end;
	}
	rcs->status = rc_ptr->status;
	memcpy(&rcs->ri,&rc_ptr->ri,sizeof(rcs->ri));
	if ( rc_ptr->win_manage_task_req ||
			rc_ptr->win_manage_task_active )
		rcs->layer_management = 1;
	if ( rc_ptr->loading_task_req ||
			rc_ptr->loading_task_active )
		rcs->search_loading = 1;
	if ( rc_ptr->min_route_task_req ||
			rc_ptr->min_route_task_active )
		rcs->change_base_coord = 1;
	ret = 0;
end:
	unlock_task(radar_lock,"get_rc_status");
	return ret;
}



