/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#include	<stdlib.h>
#include	<string.h>

extern "C" {

#include	"task.h"
#include	"memory_debug.h"
#include	"machine/param_gbview.h"
#include	"xl.h"
#include	"lock_level.h"
#include	"pri_level.h"
#include	"viewindex.h"
#include	"rcache.h"
#include	"resource.h"
#include	"gbview.h"
#include	"pri_level.h"
#include	"win_flame.h"
#include	"memory_routine.h"

}

#include	"v/v.h"
#include 	"v/VgbFlame.h"
#include	"v/v_switch.h"


#define INSTOP_TIMEOUT 1

void mem_test(char*);
extern "C" void set_change_page(char * page,int force);
extern "C" void vfq_event_task(TKEY);


#define OPAC_STOP_TIMEOUT	1

#define DEF_FONT_SIZE		159
#define BACKGROUND_COLOR	COL(0x3ff,0x3ff,0x3ff)
#define BACKGROUND_COLOR_MID	COL(0x200,0x200,0x200)

#ifdef GB2MCOLOR
#undef GB2MCOLOR
#endif
#define GB2MCOLOR(a,x)	SET_RGB8_32(a,			\
	((x)&COL_MASK)>>(COL_BIT-8),			\
	((x)&(COL_MASK<<COL_BIT))>>(COL_BIT*2-8),	\
	((x)&(COL_MASK<<(COL_BIT*2)))>>(COL_BIT*3-8),	\
	RGB8_MAX)

#ifdef MCOLOR2GB
#undef MCOLOR2GB
#endif
#define MCOLOR2GB(r,g,b,dat)		\
	{	int alpha;				\
		GET_RGB8_32(dat,r,g,b,alpha);		\
		(r) = (r)<<(COL_BIT-8);		\
		(g) = (g)<<(COL_BIT-8);		\
		(b) = (b)<<(COL_BIT-8);		\
	}

void tick_xli();
void _lock_select_mode(FLAME_WORK * fw,char * file,int line);
void unlock_select_mode(FLAME_WORK * fw);
void checkin_seq(FLAME_WORK * fw,int seq);
void checkout_seq(FLAME_WORK * fw,int seq);
void countup_seq(FLAME_WORK * fw,int seq);
void get_wh(int * w,int * h,VDraw * d);
void _free_index(FLAME_WORK * fw);
void _set_index(FLAME_WORK * fw,int type,int w,int h);
int grab_index_func_2d(FLAME_WORK * fw);
int grab_index_func_globe(FLAME_WORK * fw,GBVIEW_STATUS * sts);
void acc_bg_32(int col[3],long a);
long make_bg(int col[3],int cnt);
long get_bg_32(long * buf,int w,int h);
VImage * v_copy_image(VDraw * draw);
void convert_image_32_plane(FLAME_WORK * fw);
void convert_image_32(FLAME_WORK * fw);
void convert_image_32_line(FLAME_WORK * fw);
void convert_image(FLAME_WORK * fw);
void _opac_move(FLAME_WORK * fw);
void _set_opac_mode(FLAME_WORK * fw,MOVE_SET * ms);
void set_opac_mode(FLAME_WORK * fw,MOVE_SET * ms);
void opac_move(FLAME_WORK * fw);
void __opac_stop(FLAME_WORK * fw);
void _opac_stop(FLAME_WORK * fw);
void opac_stop(FLAME_WORK * fw);
int set_plane_32(FLAME_WORK * fw,GBVIEW_PLANE * p);
int set_plane(FLAME_WORK * fw,GBVIEW_PLANE * p);
int set_plane_trans_32(FLAME_WORK * fw,GBVIEW_PLANE * p);
int set_plane_trans(FLAME_WORK * fw,GBVIEW_PLANE * p);
void interface_redraw_func(FLAME_WORK * fw,int type);
void interface_click_func(FLAME_WORK * fw,int type,GBVIEW_PLANE * gbp);
void interface_insert_func(FLAME_WORK * fw);
void interface_event_func(GBVIEW_FLAME * gf,int type,void * w,void * _fw);
TV_SHADOW * shadow_search(TV_SHADOW * sh,int nos,RESOURCE * r);
void delete_tv_shadow(FLAME_WORK * fw,int nos);
V_CALLBACK_D(eye_handler);
VexDraw * new_VexDrawEye(VObjectStatus * v_sts,FLAME_WORK * fw,VImage ** imgs,V_CALLBACK(cb));
VexDraw * new_VexDrawInfo(VObjectStatus * v_sts,FLAME_WORK * fw,VImage ** imgs,V_CALLBACK(cb));
void insert_tv_shadow(FLAME_WORK * fw,int nos,GBVIEW_LAYER_STATUS * ls);
void test_count(FLAME_WORK * fw);
void free_vgb_flame_t(VGB_FLAME_T * n);
void set_move_mode(FLAME_WORK * fw,int mode);
void redraw_handler(FLAME_WORK * fw,VSize size);
void indicate_coordinate(FLAME_WORK * fw,int x,int y);
void image_button_handler(FLAME_WORK * fw,int subtype,int t,int x,int y);
int flame_status_check(FLAME_WORK * fw);
V_CALLBACK_D(drag_image_handler);
void limit_opac(FLAME_WORK * fw);
V_CALLBACK_D(zoom_in);
V_CALLBACK_D(zoom_out);
V_CALLBACK_D(mode_button_handler);
void make_img(short w, short h, VImage *img);
V_CALLBACK_D(resize_handler);
void pixelmap_task(TKEY d);
void setup_indicate(FLAME_WORK * fw);
V_CALLBACK_D(cb_indicate_from_radar);
void indicate_from_radar(
	RADAR_INDICATE * ri,
	void * _fw);
void all_clear_flame_status(VgbFlameStatus * s);
void all_clear_flame_switch_status(VgbFlameSwitchStatus * s);
void all_clear_fw(FLAME_WORK * fw);
V_CALLBACK_D(setup_button_handler);
void setup_button(VObject * me,
	FLAME_WORK * fw,
	VButton * old_obj,
	VButton * new_obj,
	V_CALLBACK_D((*func)));
int radio_button_setup_ins(VRadioButton ** ary,int len,VRadioButton * b);
void radio_button_setup(FLAME_WORK * fw);
VImage * v_get_image_element(VImage * img,VRect elr);
void interface_infolist_func(FLAME_WORK * fw,int type,GBVIEW_STATUS * sts);
void interface_info_error_func();
void interface_info_func(FLAME_WORK * fw,int type,GBVIEW_STATUS * sts);
void click_op(FLAME_WORK *);
VgbFlameLayers * copy_out_layers(GBVIEW_LAYER_STATUS * layer);
void instop_handler(FLAME_WORK * fw,int subtype,int t,int x,int y,int w,int h);
void instop_tick(int data);
V_CALLBACK_D(instop_callback);
V_CALLBACK_D(base_handler);
VexDraw *
new_VexDrawBase(VObjectStatus * v_sts,FLAME_WORK * fw,VImage ** imgs,V_CALLBACK(cb));
void vfq_gc_func(VGB_FLAME_T * n);
void vfq_gc_get(VGB_FLAME_T * n);

void interface_change_base_func(FLAME_WORK * fw);
void _interface_infolist_func(FLAME_WORK * fw,VGB_FLAME_T * n);
void get_marshaler_mode(FLAME_WORK * fw,VMarshaler * m);
void setup_buttons_control(VgbFlameStandard * obj,FLAME_WORK * fw);
V_CALLBACK_D(buttons_control_handler);
V_CALLBACK_D(flame_focus_obey_command);
V_CALLBACK_D(flame_focus_command_status);



int ptr_param_func(FLAME_WORK *,I_POINT **);
int ptr_cmp(FLAME_WORK *,I_POINT *,I_POINT *);
int real_param_func(FLAME_WORK *,REAL1 **);
int real_cmp(FLAME_WORK *,REAL1 *,REAL1 *);

int grab_flame_func(FLAME_WORK *);
int grab_index_func(FLAME_WORK *);

int rotate_flame_func(FLAME_WORK *);
int rotate_index_func(FLAME_WORK *);

int zoom_flame_func(FLAME_WORK *);
int zoom_index_func(FLAME_WORK *);

int flame_focus_handler(
	int event_type,
	VObject * tv,
	int edit_type,
	int data1,
	VBackColorView  ** data2,
	void *);


MOVE_SET ms_grab = {
	(int (*)(FLAME_WORK *,void**))ptr_param_func,
	grab_flame_func,
	grab_index_func,
	(int (*)(FLAME_WORK *,void*,void*))ptr_cmp
};
MOVE_SET ms_rotate = {
	(int (*)(FLAME_WORK *,void**))ptr_param_func,
	rotate_flame_func,
	rotate_index_func,
	(int (*)(FLAME_WORK *,void*,void*))ptr_cmp
};
MOVE_SET ms_zoom = {
	(int (*)(FLAME_WORK *,void**))real_param_func,
	zoom_flame_func,
	zoom_index_func,
	(int (*)(FLAME_WORK *,void*,void*))real_cmp
};


SEM interface_lock,opac_lock,interface_redraw_lock;
int interface_event_flag;
SYS_QUEUE vgb_flame_queue;

void
tick_xli()
{
XL_INTERPRETER * xli;
	if ( get_my_xli() == 0 ) {
		xli = new_xl_interpreter();
		xli->a_type = XLA_SELF;
		setup_i(xli);
	}
}


void gbf_test_task(TKEY);

void
gbf_test_task(TKEY d)
{
//VgbFlameRadarStatus s;
VgbFlameCoordinateStatus fs;
VgbFlameStandard * obj;
//int i;
XL_INTERPRETER * xli;

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);
	obj = (VgbFlameStandard *)GET_TKEY(d);
	sleep_sec(5);
/*
	for ( ; ; ) {
		sleep_sec(1);
		obj->get_radar_status(&s,VSF_FLAME_R_LOADING_STATUS);
		ss_printf("LS = RC(%i %i %i %i ri(",
			s.loading_status.rc.status,
			s.loading_status.rc.search_loading,
			s.loading_status.rc.layer_management,
			s.loading_status.rc.change_base_coord);
		for ( i = 0 ; i < R_IND_ARY_LEN ; i ++ )
			ss_printf("%i ",s.loading_status.rc.ri.ary[i]);
		ss_printf("))\n");
		ss_printf("(%i %i %i %i - %i - %i %i %i)\n",
			s.loading_status.wf.draw,
			s.loading_status.wf.exit,
			s.loading_status.wf.load_structure,
			s.loading_status.wf.dirty,
			s.loading_status.wf.data_request,
			s.loading_status.wf.indicate_request,
			s.loading_status.wf.indicate,
			s.loading_status.wf.raw_image_request);

	}
*/
	memset(&fs,0,sizeof(fs));
	fs.flame_base_center.x = 139.433;
	fs.flame_base_center.y = 35.679;
	fs.flame_base_rotate = 0;
	fs.flame_base_resolution = 400;
	fs.flame_base_unit = l_string(std_cm,"degree");
	fs.target = l_string(std_cm,"xlp://isjhp2.nichibun.ac.jp:8080/world/00.crd");
	ss_printf("GOTO TEST ==================\n");
	obj->set_coordinate_status(&fs,
		VSF_FLAME_C_FLAME_BASE_CENTER|
		VSF_FLAME_C_FLAME_BASE_ROTATE|
		VSF_FLAME_C_FLAME_BASE_RESOLUTION|
		VSF_FLAME_C_FLAME_BASE_UNIT|
		VSF_FLAME_C_TARGET);
}


extern "C" void
init_VgbFlameStandard()
{
//void interface_event_func();
//void init_gv_flame_switch(XLISP_ENV *);

	init_gv_flame_switch(gblisp_top_env0);

	new_tick((void(*)(int))tick_xli,0,0);

	interface_lock = new_lock(LL_INTERFACE);
	interface_redraw_lock = new_lock(LL_INTERFACE_R);
	opac_lock = new_lock(LL_INTERFACE_O);

	memset(&vgb_flame_queue,0,sizeof(SYS_QUEUE));
	vgb_flame_queue.flags = QF_FIFO;
	vgb_flame_queue.key_func = vfq_event_task;
	vgb_flame_queue.gc_func = (void (*)())vfq_gc_func;
	vgb_flame_queue.gc_get =  (void (*)())vfq_gc_get;
	vgb_flame_queue.pri = PRI_V_RECONFIG;
	setup_queue(&vgb_flame_queue);

}


void
vfq_gc_func(VGB_FLAME_T * n)
{
INFO_LIST * il;
	switch ( n->type ) {
	case VGBFT_INFOLIST:
		for ( il = n->infolist ; il ; il = il->next )
			gc_gb_sexp(il->info);
	}
}

void
vfq_gc_get(VGB_FLAME_T * n)
{
INFO_LIST * il;
	switch ( n->type ) {
	case VGBFT_INFOLIST:
		for ( il = n->infolist ; il ; il = il->next ) {
			lock_mem();
			gc_set_nl(il->info,(void (*)())gc_gb_sexp);
			unlock_mem();
		}
	}
}

void
_lock_select_mode(FLAME_WORK * fw,char * file,int line)
{
	lock_task(interface_redraw_lock);
	for ( ; fw->select_mode_lock ; ) {
		sleep_task((int)fw,interface_redraw_lock);
		lock_task(interface_redraw_lock);
	}
	fw->select_mode_lock = 1;
	fw->select_mode_lock_file = file;
	fw->select_mode_lock_line = line;
	unlock_task(interface_redraw_lock,"lock");
}

#define lock_select_mode(fw)	_lock_select_mode(fw,__FILE__,__LINE__);


void
unlock_select_mode(FLAME_WORK * fw)
{
	lock_task(interface_redraw_lock);
	fw->select_mode_lock = 0;
	fw->select_mode_lock_file = 0;
	fw->select_mode_lock_line = 0;
	wakeup_task((int)fw);
	unlock_task(interface_redraw_lock,"lock");
}

void
checkin_seq(FLAME_WORK * fw,int seq)
{
int _seq;
retry:
	lock_task(interface_redraw_lock);
	if ( seq > 0 ) {
		if ( fw->seq_lock ) {
			sleep_task((int)&fw->seq,
					interface_redraw_lock);
			goto retry;
		}
		if ( fw->seq < 0 ) {
			sleep_task((int)&fw->seq,
					interface_redraw_lock);
			goto retry;
		}
		else if ( fw->seq > 0 ) {
			_seq = fw->seq + 1;
			if ( _seq < 1 )
				_seq = 1;
			if ( seq != _seq ) {
				sleep_task((int)&fw->seq,
					interface_redraw_lock);
				goto retry;
			}
		}
		fw->seq = - seq;
	}
	else if ( seq < 0 ) {
		if ( fw->seq_lock ) {
			sleep_task((int)&fw->seq,
					interface_redraw_lock);
			goto retry;
		}
		if ( fw->seq < 0 ) {
			sleep_task((int)&fw->seq,
					interface_redraw_lock);
			goto retry;
		}
		fw->seq_lock = 1;
	}
	unlock_task(interface_redraw_lock,"check_in_seq");
}

void
checkout_seq(FLAME_WORK * fw,int seq)
{
	lock_task(interface_redraw_lock);
	if ( seq > 0 ) {
		if ( fw->seq_lock )
			er_panic("checkout_seq 1");
		if ( fw->seq >= 0 )
			er_panic("checkout_seq 2");
		fw->seq = - fw->seq;
		wakeup_task((int)&fw->seq);
	}
	else if ( seq < 0 ) {
		if ( fw->seq_lock == 0 )
			er_panic("checkout_seq 3");
		fw->seq_lock = 0;
		wakeup_task((int)&fw->seq);
	}
	unlock_task(interface_redraw_lock,"checkout_seq");
}

void
countup_seq(FLAME_WORK * fw,int seq)
{
	checkin_seq(fw,seq);
	checkout_seq(fw,seq);
}



int
ptr_param_func(FLAME_WORK * fw,I_POINT ** ptr)
{
I_POINT * ret;
	ret = (I_POINT*)d_alloc(sizeof(*ret));
	ret->x = fw->press.x;
	ret->y = fw->press.y;
	*ptr = ret;
	return 0;
}

int
ptr_cmp(FLAME_WORK * fw,I_POINT * a,I_POINT * b)
{
	if ( a->x != b->x )
		return -1;
	if ( a->y != b->y )
		return -1;
	return 0;
}

int
real_param_func(FLAME_WORK * fw,REAL1 ** ptr)
{
REAL1 * ret;

	ret = (REAL1*)d_alloc(sizeof(REAL1));
	*ret = fw->press_zoom;
	*ptr = ret;
	return 0;
}

int
real_cmp(FLAME_WORK * fw,REAL1 * a,REAL1 * b)
{
	if ( *a != *b )
		return -1;
	return 0;
}


void
get_wh(int * w,int * h,VDraw * d)
{
VImage * img;
	img = d->draw_start();
	if ( img == 0 )
		return;
	*w = img->size.w;
	*h = img->size.h;
	d->draw_end();
}



void
_free_index(FLAME_WORK * fw)
{
	switch ( fw->ix.type ) {
	case 0:
		break;
	case PIT_XY:
		d_f_ree(fw->ix.xy.index_x);
		d_f_ree(fw->ix.xy.index_y);
		break;
	case PIT_PLANE:
		d_f_ree(fw->ix.p.index);
		break;
	default:
		er_panic("free_index");
	}
	fw->ix.type = 0;
}

void
_set_index(FLAME_WORK * fw,int type,int w,int h)
{
	_free_index(fw);
	switch ( type ) {
	case PIT_XY:
		fw->ix.xy.index_x =
			(int*)d_alloc(sizeof(int)*w);
		fw->ix.xy.index_y =
			(int*)d_alloc(sizeof(int)*h);
		fw->ix.type = PIT_XY;
		break;
	case PIT_PLANE:
		fw->ix.p.index =
			(I_POINT*)d_alloc(sizeof(I_POINT)*w*h);
		fw->ix.type = PIT_PLANE;
		break;
	default:
		er_panic("_set_index");
	}
}




int
grab_flame_func(FLAME_WORK * fw)
{
I_POINT * from,* to;
	if ( fw->start_shot == 0 || fw->last_shot == 0 )
		return 0;
	from = (I_POINT*)fw->start_shot;
	to = (I_POINT*)fw->last_shot;
	return call_wf_move(&fw->sw,*from,*to);
}

int
grab_index_func_2d(FLAME_WORK * fw)
{
I_POINT * from,* to;
int i,w,h;
int * index;
int ofs,tar;
	if ( fw->start_shot == 0 || fw->last_shot == 0 )
		return 0;
	get_wh(&w,&h,fw->im);
	_set_index(fw,PIT_XY,w,h);
/*
	if ( fw->ix.type == 0 ) {
		fw->ix.xy.index_x =
			d_alloc(sizeof(int)*w);
		fw->ix.xy.index_y =
			d_alloc(sizeof(int)*h);
		fw->ix.type = PIT_XY;
	}
	else if ( fw->ix.type != PIT_XY )
		er_panic("grab_index_func");
*/
	from = (I_POINT*)fw->start_shot;
	to = (I_POINT*)fw->last_shot;

	index = fw->ix.xy.index_x;
	ofs = from->x - to->x;
	for ( i = 0; i < w ; i ++ ) {
		tar = i + ofs;
		if ( tar < 0 )
			tar = -1;
		else if ( tar >= w )
			tar = -1;
		index[i] = tar;
	}
	index = fw->ix.xy.index_y;
	ofs = from->y - to->y;
	for ( i = 0 ; i < h ; i ++ ) {
		tar = i + ofs;
		if ( tar < 0 )
			tar = -1;
		else if ( tar >= h )
			tar = -1;
		index[i] = tar;
	}
	return 0;
}

int
grab_index_func_globe(FLAME_WORK * fw,GBVIEW_STATUS * sts)
{
GB_POINT from,to;
int w,h;
	if ( fw->start_shot == 0 || fw->last_shot == 0 )
		return 0;
	get_wh(&w,&h,fw->im);
	_set_index(fw,PIT_PLANE,w,h);
/*
	if ( fw->ix.type == 0 ) {
		fw->ix.p.index =
			d_alloc(sizeof(I_POINT)*w*h);
		fw->ix.type = PIT_PLANE;
	}
	else if ( fw->ix.type != PIT_XY )
		er_panic("grab_index_func");
*/
	from = v2gb_point(*(I_POINT*)fw->start_shot);
	to = v2gb_point(*(I_POINT*)fw->last_shot);

	return wf_make_gmatrix_index(
		fw->ix.p.index,
		from,to,
		sts->pp_radius,
		sts->width,
		sts->height);

}

int
grab_index_func(FLAME_WORK * fw)
{
GBVIEW_STATUS sts;
	if ( call_wf_status(&fw->sw,&sts,CALL_STS_CACHE_NORMAL) < 0 )
		return -1;
	if ( sts.flame_base_display_map_type == MHT_PP )
		return grab_index_func_globe(fw,&sts);
	else	return grab_index_func_2d(fw);
}

int
rotate_flame_func(FLAME_WORK * fw)
{
I_POINT * from,* to;
GB_POINT _from,_to;
	if ( fw->start_shot == 0 || fw->last_shot == 0 )
		return 0;
	from = (I_POINT*)fw->start_shot;
	to = (I_POINT*)fw->last_shot;
	_from.x = from->x;
	_from.y = from->y;
	_to.x = to->x;
	_to.y = to->y;
	return call_wf_rotate(&fw->sw,_from,_to);
}

int
rotate_index_func(FLAME_WORK * fw)
{
I_POINT * from,* to;
int w,h;
GB_POINT _from,_to;
	if ( fw->start_shot == 0 || fw->last_shot == 0 )
		return 0;
	get_wh(&w,&h,fw->im);
	_set_index(fw,PIT_PLANE,w,h);
/*
	if ( fw->ix.type == 0 ) {
		fw->ix.p.index =
			d_alloc(sizeof(I_POINT)*w*h);
		fw->ix.type = PIT_PLANE;
	}
	else if ( fw->ix.type != PIT_PLANE )
		er_panic("grab_index_func");
*/
	from = (I_POINT*)fw->start_shot;
	to = (I_POINT*)fw->last_shot;

	_from.x = from->x;
	_from.y = from->y;
	_to.x = to->x;
	_to.y = to->y;

	wf_make_rotate_index(
		fw->ix.p.index,
		_from,_to,
		w,h);
	return 0;
}

int
zoom_flame_func(FLAME_WORK * fw)
{
REAL1 * from,* to;
	if ( fw->start_shot == 0 || fw->last_shot == 0 )
		return 0;
	from = (REAL1*)fw->start_shot;
	to = (REAL1*)fw->last_shot;
	return call_wf_zoom(&fw->sw,0,(*to)/(*from));
}

int
zoom_index_func(FLAME_WORK * fw)
{
REAL1 * from,* to;
int w,h;
	if ( fw->start_shot == 0 || fw->last_shot == 0 )
		return 0;
	get_wh(&w,&h,fw->im);
	_set_index(fw,PIT_XY,w,h);
/*
	if ( fw->ix.type == 0 ) {
		fw->ix.xy.index_x =
			d_alloc(sizeof(int)*w);
		fw->ix.xy.index_y =
			d_alloc(sizeof(int)*h);
		fw->ix.type = PIT_XY;
	}
	else if ( fw->ix.type != PIT_XY )
		er_panic("grab_index_func");
*/
	from = (REAL1*)fw->start_shot;
	to = (REAL1*)fw->last_shot;
	wf_make_zoom_index(
		fw->ix.xy.index_x,
		fw->ix.xy.index_y,
		(*to)/(*from),
		w,h);
	return 0;
}


void
acc_bg_32(int col[3],long a)
{
int c[3];
int i;
	c[0] = c[1] = c[2] = 0;
	MCOLOR2GB(c[0],c[1],c[2],a);
	for ( i = 0 ; i < 3 ; i ++ )
		col[i] += c[i];
}

long
make_bg(int col[3],int cnt)
{
int i;
long ret;
	for ( i = 0 ; i < 3 ; i ++ )
		col[i] = col[i]/cnt;
	GB2MCOLOR(ret,COL(col[0],col[1],col[2]));
	return ret;
}


long
get_bg_32(long * buf,int w,int h)
{
int col[3];
int i;
	col[0] = col[1] = col[2] = 0;

	for ( i = 0 ; i < w ; i ++ ) {
		acc_bg_32(col,buf[i]);
		acc_bg_32(col,buf[i + (h-1)*w]);
	}
	for ( i = 0 ; i < h ; i ++ ) {
		acc_bg_32(col,buf[i*w]);
		acc_bg_32(col,buf[i*w + (w-1)]);
	}
	return make_bg(col,2*(w+h));
}


VImage *
v_copy_image(VDraw * draw)
{
VImage * ret;
VImage * img;
	img = draw->draw_start();
	if ( img == 0 )
		return 0;
	ret = v_image_new(img->size.w,img->size.h,32);
	v_image_draw_start(ret, 0);

	memcpy(ret->buf_32,img->buf_32,
		img->size.h * img->w_border * 4);

	v_image_draw_end(ret);

	draw->draw_end();
	return ret;
}


void
convert_image_32_plane(FLAME_WORK * fw)
{
long * from,* to, * _to;
I_POINT * index;
int x,y,w,h,wb,w_border;
int xx,yy;
long bg;
VImage * img;


	img = fw->im->draw_start();

	v_image_draw_start(fw->ss, 0);

	from = fw->ss->buf_32;
	_to = img->buf_32;
	index = fw->ix.p.index;
	w = img->size.w;
	h = img->size.h;
	w_border = fw->ss->w_border;

	bg = get_bg_32(from,w,h);

	wb = img->w_border;

	for ( y = 0 ; y < h ; y ++ ) {
		to = &_to[y * wb];
		for ( x = 0 ; x < w ; x ++ ) {
			xx = index->x;
			yy = index->y;
			if ( xx >= 0 )
				*to = from[yy*w_border + xx];
			else	*to = bg;
			index ++;
			to ++;
		}
	}

//	v_image_unref(img);
	v_image_draw_end(fw->ss);

	fw->im->draw_end();
}

void
convert_image_32_line(FLAME_WORK * fw)
{
long * from,* to, * _to;
int * index_x, * index_y;
int x,y,w,h,wb,w_border;
int xx,yy;
long bg;
VImage * img;

	img = fw->im->draw_start();
	v_image_draw_start(fw->ss, 0);

	from = fw->ss->buf_32;
	_to = img->buf_32;
	index_x = fw->ix.xy.index_x;
	index_y = fw->ix.xy.index_y;
	w = img->size.w;
	h = img->size.h;

	bg = get_bg_32(from,w,h);

	wb = img->w_border;
	w_border = fw->ss->w_border;

	for ( y = 0 ; y < h ; y ++ ) {
		to = &_to[y * wb];
		for ( x = 0 ; x < w ; x ++ ) {
			xx = index_x[x];
			yy = index_y[y];
			if ( xx >= 0 && yy >= 0 )
				*to = from[yy*w_border + xx];
			else	*to = bg;
			to ++;
		}
	}

//	v_image_unref(img);
	v_image_draw_end(fw->ss);

	fw->im->draw_end();
}

void
convert_image_32(FLAME_WORK * fw)
{
	switch ( fw->ix.type ) {
	case PIT_PLANE:
		convert_image_32_plane(fw);
		break;
	case PIT_XY:
		convert_image_32_line(fw);
		break;
	default:
		er_panic("_conveert_image_32");
	}
}


void
convert_image(FLAME_WORK * fw)
{
	convert_image_32(fw);
}


void
_opac_move(FLAME_WORK * fw)
{
void * move_param,* last_shot;
VImage * ptr;


	if ( fw->ms == 0 )
		return;

	(*fw->ms->param_func)(fw,&move_param);

	if ( fw->start_shot == 0 ) {
		fw->start_shot = move_param;
		return;
	}

	if ( (*fw->ms->cmp_func)(
			fw,
			fw->start_shot,
			move_param) == 0 ) {
		d_f_ree(move_param);
		return;
	}
	if ( fw->last_shot &&
		(*fw->ms->cmp_func)(
			fw,
			fw->last_shot,
			move_param) == 0 ) {
		d_f_ree(move_param);
		return;
	}
	last_shot = fw->last_shot;
	fw->last_shot = move_param;



	if ( fw->ss ) {
		checkin_seq(fw,-1);
		if ( fw->im && fw->fw_active ) {
			if ( (*fw->ms->index_func)(fw) == 0 ) {
				convert_image_32(fw);
				if ( last_shot )
					d_f_ree(last_shot);
			}
			else {
				if ( fw->last_shot )
					d_f_ree(fw->last_shot);
				fw->last_shot = last_shot;
			}
		}
		checkout_seq(fw,-1);
	}
	else {
		checkin_seq(fw,-1);
		if ( fw->im && fw->fw_active ) {
			if ( (*fw->ms->index_func)(fw) == 0 ) {

				if ( last_shot )
					d_f_ree(last_shot);

				lock_task(interface_lock);

				ptr = v_copy_image(fw->im);
				fw->ss = ptr;

				unlock_task(interface_lock,"opac_move");
				convert_image(fw);
			}
			else {
				if ( fw->last_shot )
					d_f_ree(fw->last_shot);
				fw->last_shot = last_shot;
			}
		}
		checkout_seq(fw,-1);

	}
}



void
_set_opac_mode(FLAME_WORK * fw,MOVE_SET * ms)
{
void _opac_stop(FLAME_WORK *);

	if ( fw->ms != ms )
		_opac_stop(fw);
	if ( ms ) {
		fw->ms = ms;
		(*ms->param_func)(fw,&fw->start_shot);
	}
	else if ( fw->ms ) {
		(*fw->ms->param_func)(fw,&fw->start_shot);
	}
}

void
set_opac_mode(FLAME_WORK * fw,MOVE_SET * ms)
{
	del_tick((void(*)(int))set_opac_mode);
	lock_task(opac_lock);
	_set_opac_mode(fw,ms);
	unlock_task(opac_lock,"set_opac_mode");
}

void
opac_move(FLAME_WORK * fw)
{
	del_tick((void(*)(int))set_opac_mode);
	lock_task(opac_lock);
	_opac_move(fw);
	unlock_task(opac_lock,"opac_move");
}

void
__opac_stop(FLAME_WORK * fw)
{

	lock_task(interface_lock);

	if ( fw->ss ) {
		v_image_unref(fw->ss);
		fw->ss = 0;
	}
	switch ( fw->ix.type ) {
	case PIT_PLANE:
		d_f_ree(fw->ix.p.index);
		break;
	case PIT_XY:
		d_f_ree(fw->ix.xy.index_x);
		d_f_ree(fw->ix.xy.index_y);
		break;
	default:
		er_panic("_opac_stop");
	}
	fw->ix.type = 0;
	if ( fw->start_shot )
		d_f_ree(fw->start_shot);
	if ( fw->last_shot )
		d_f_ree(fw->last_shot);
	fw->start_shot = fw->last_shot = 0;

	unlock_task(interface_lock,"opac_stop");
}


void
_opac_stop(FLAME_WORK * fw)
{
int seq;

	if ( fw->ms == 0 )
		return;
	if ( fw->start_shot == 0 )
		return;
	if ( fw->ix.type == 0 )
		return;

	_opac_move(fw);

	seq = (*fw->ms->flame_func)(fw);

	checkin_seq(fw,seq);
	if ( seq && fw->im && fw->fw_active )
		__opac_stop(fw);

	checkout_seq(fw,seq);
	return;

}

void
opac_stop(FLAME_WORK * fw)
{

	del_tick((void(*)(int))set_opac_mode);
	lock_task(opac_lock);
	_opac_stop(fw);
	unlock_task(opac_lock,"opac_stop");
}

int
set_plane_32(FLAME_WORK * fw,GBVIEW_PLANE * p)
{
long * buf;
int y_src,y_dest,y_max,x,x_ofs;
unsigned long * sp;
long * dp;
int w,ow;
unsigned long c,bg;
int ret;
VImage * img;

	if ( p->r.r.tl.x >= p->r.r.br.x )
		return -1;
	if ( p->r.r.tl.y >= p->r.r.br.y )
		return -1;

	if ( fw->ss ) {
		img = fw->ss;
		v_image_draw_start(img, 0);
		ret = 1;
	}
	else {
		img = fw->im->draw_start();
		if ( img == 0 )
			return -1;
		ret = 0;
	}

	buf = img->buf_32;
	ow = img->w_border;

	GB2MCOLOR(bg,BACKGROUND_COLOR);

	w = p->r.r.br.x - p->r.r.tl.x;
	x_ofs = p->r.r.tl.x;
	y_src = 0;
	y_dest = p->r.r.tl.y;
	y_max = p->r.r.br.y;

	for ( ; y_dest < y_max ; y_dest ++ , y_src ++ ) {
		sp = &p->r.plane[y_src*w];
		dp = &buf[y_dest*ow + x_ofs];
		for ( x = 0 ; x < w ; x ++ ) {
			c = *sp ++;
			if ( c & C_TRANSPARENT )
				*dp = bg;
			else	GB2MCOLOR(*dp,c);
			dp ++;
		}
	}

	if ( ret == 0 )
		fw->im->draw_end();
	else	v_image_draw_end(img);

	return ret;
}

int
set_plane(FLAME_WORK * fw,GBVIEW_PLANE * p)
{
int ret;
	lock_task(interface_lock);
	ret = set_plane_32(fw,p);
	unlock_task(interface_lock,"set_plane");
	return ret;
}

int
set_plane_trans_32(FLAME_WORK * fw,GBVIEW_PLANE * p)
{
long * buf;
int y_src,y_dest,y_max,x,x_ofs;
unsigned long * sp;
long * dp;
int w,ow;
unsigned long c,bg;
int ret;
VImage * img;


	if ( p->r.r.tl.x >= p->r.r.br.x )
		return -1;
	if ( p->r.r.tl.y >= p->r.r.br.y )
		return -1;

	if ( fw->ss ) {
		img = fw->ss;
		v_image_draw_start(img, 0);
		ret = 1;
	}
	else {
		img = fw->im->draw_start();
		if ( img == 0 )
			return -1;
		ret = 0;
	}

	buf = img->buf_32;
	ow = img->w_border;

	GB2MCOLOR(bg,BACKGROUND_COLOR);

	w = p->r.r.br.x - p->r.r.tl.x;
	x_ofs = p->r.r.tl.x;
	y_src = 0;
	y_dest = p->r.r.tl.y;
	y_max = p->r.r.br.y;

	for ( ; y_dest < y_max ; y_dest ++ , y_src ++ ) {
		sp = &p->r.plane[y_src*w];
		dp = &buf[y_dest*ow + x_ofs];
		for ( x = 0 ; x < w ; x ++ ) {
			c = *sp ++;
			if ( !(c & C_TRANSPARENT) )
				GB2MCOLOR(*dp,c);
			dp ++;
		}
	}

	if ( ret == 0 )
		fw->im->draw_end();
	else	v_image_draw_end(img);

	return ret;
}

int
set_plane_trans(FLAME_WORK * fw,GBVIEW_PLANE * p)
{
int ret;
	lock_task(interface_lock);
	ret = set_plane_trans_32(fw,p);
	unlock_task(interface_lock,"set_plane");
	return ret;
}



void
interface_redraw_func(FLAME_WORK * fw,int type)
{
	lock_task(interface_redraw_lock);
	if ( fw->redraw_flag == 0 ) {
		fw->redraw_flag = 1;
		wakeup_task((int)&fw->redraw_flag);
	}
	unlock_task(interface_redraw_lock,"cosmos_redraw_event");
}

void
interface_click_func(FLAME_WORK * fw,int type,GBVIEW_PLANE * gbp)
{
int seq;
GBVIEW_STATUS sts;
GBVIEW_PLANE gbp2;



	if ( gbp->h.seq ) {
		checkin_seq(fw,gbp->h.seq);
		if ( fw->im && fw->fw_active ) {
			set_plane_trans(fw,gbp);
			fw->im->redraw();
		}
		checkout_seq(fw,gbp->h.seq);
	}

	if ( (seq = call_wf_purge_select(&fw->sw)) == 0 ) {
		return;
	}

	countup_seq(fw,seq);


	if ( call_wf_status(&fw->sw,&sts,CALL_STS_CACHE_NORMAL) < 0 )
		return;


	seq = call_wf_redraw(&fw->sw,&gbp2,0,0,
		sts.width,sts.height);

	checkin_seq(fw,seq);
	if ( seq && fw->im && fw->fw_active ) {
		set_plane(fw,&gbp2);
		if ( gbp2.r.r.tl.x != gbp2.r.r.br.x ) {
		VRect rr;
			rr = rect_conv_i2s(gbp2.r.r);
			fw->im->redraw(&rr);
		}

		wf_free_plane(&gbp2);
		wf_free_status(&sts);
	}
	checkout_seq(fw,seq);

}


void
_interface_infolist_func(FLAME_WORK * fw,VGB_FLAME_T * n)
{
INFO_LIST * il;
XL_SEXP * ind;
	if ( n->infolist ) {
		ss_printf("ON_MOUSE INFORMATION(EVENT)\n");
		for ( il = n->infolist ; il ; il = il->next ) {
			ss_printf("\t>> ");
			print_sexp(s_stdout,il->info,0);
			ss_printf("\n");
		}
		ind = 0;
		for ( il = n->infolist ; il ; il = il->next ) {
			if ( get_type(il->info) == XLT_NULL )
				continue;
			ind = cons(il->info,ind);
		}
		if ( ind && fw->oattribute_handler ) {
ss_printf("INTERFACE\n");
			(*fw->oattribute_handler)(
				fw->this_object,
				fw->oattribute_handler_arg,
				ind);
ss_printf("INTERFACE END\n");
		}
	}
	free_infolist(n->infolist);
}


void
interface_infolist_func(FLAME_WORK * fw,int type,GBVIEW_STATUS * ss)
{
VGB_FLAME_T *n, * n1;
char buf[20];
	if ( fw->sts.indicate_tree_obj == 0 )
		return;
	if ( ss->infolist == 0 )
		return;
	sprintf(buf,"%p-2",fw);
	n = (VGB_FLAME_T*)new_queue_node(sizeof(*n));
	n->type = VGBFT_INFOLIST;
	n->fw = fw;
	n->infolist = copy_infolist_r(ss->infolist);
	n->h.key = nl_copy_str(std_cm,buf);

	n1 = (VGB_FLAME_T*)delete_queue(&vgb_flame_queue,
			(int(*)())sq_key_cond,(void*)n->h.key,0);
	if ( n1 )  {
		free_infolist(n1->infolist);
		free_vgb_flame_t(n1);
	}
	insert_queue(&vgb_flame_queue,n,0);
}


void
interface_info_error_func()
{
char * page;
	page = (char*)d_alloc(1000);
	sprintf(page,"http://%s:%i/sys/error.html",
		http_hostname,
		http_port);
	set_change_page(page,1);
	d_f_ree(page);
}

void
interface_info_func(FLAME_WORK * fw,int type,GBVIEW_STATUS * sts)
{
	if ( sts->flags & SF_REFERENCE )
		set_change_page(n_string(std_cm,sts->reference),1);
	else if ( sts->flags & SF_INFOLIST )
		interface_infolist_func(fw,type,sts);
	else if ( sts->flags & SF_ERROR )
		interface_info_error_func();
	else	er_panic("interface_info_func");
}

void
interface_insert_func(FLAME_WORK * fw)
{
VGB_FLAME_T *n;
char buf[20];
	if ( fw->sts.indicate_tree_obj == 0 )
		return;
	sprintf(buf,"%p-1",fw);
	n = (VGB_FLAME_T*)new_queue_node(sizeof(*n));
	n->type = VGBFT_INSERT;
	n->fw = fw;
	n->h.key = nl_copy_str(std_cm,buf);
	insert_queue(&vgb_flame_queue,n,0);
}

void
interface_change_base_func(FLAME_WORK * fw)
{
VGB_FLAME_T *n;
char buf[20];
	if ( fw->sts.indicate_tree_obj == 0 )
		return;
	sprintf(buf,"%p-1",fw);
	n = (VGB_FLAME_T*)new_queue_node(sizeof(*n));
	n->type = VGBFT_CHANGE_BASE;
	n->fw = fw;
	n->h.key = nl_copy_str(std_cm,buf);
	insert_queue(&vgb_flame_queue,n,0);
}

void
interface_event_func(GBVIEW_FLAME * gf,int type,void * w,void * _fw)
{
FLAME_WORK * fw;

	fw = (FLAME_WORK *)_fw;
	switch ( type ) {
	case ET_REDRAW:
		interface_redraw_func(fw,type);
		break;
	case ET_CLICK:
		interface_click_func(fw,type,(GBVIEW_PLANE*)w);
		break;
	case ET_INFO:
		interface_info_func(fw,type,(GBVIEW_STATUS*)w);
		break;
	case ET_INSERT:
		interface_insert_func(fw);
		break;
	case ET_CHANGE_BASE:
		interface_change_base_func(fw);
		break;
	default:
		er_panic("interface_event_func(1)");
	}
}

TV_SHADOW *
shadow_search(TV_SHADOW * sh,int nos,RESOURCE * r)
{
	for ( ; nos ; sh ++ , nos -- ) {
		if ( sh->r == r )
			return sh;
	}
	return 0;
}

void
delete_tv_shadow(FLAME_WORK * fw,int nos)
{
int i;
	if ( fw->tree_view_data == 0 )
		return;
	if ( fw->tree_view_data_len <= nos )
		return;
	fw->sts.indicate_tree_obj->delete_line(nos);
	for ( i = nos ; i < fw->tree_view_data_len - 1 ; i ++ ) {
		fw->tree_view_data[i] = fw->tree_view_data[i+1];
	}
	fw->tree_view_data_len --;
	fw->tree_view_data = (TV_SHADOW*)
		d_re_alloc(fw->tree_view_data,
			fw->tree_view_data_len*sizeof(TV_SHADOW));
}



void
VgbFlameStandard::_eye_handler(VObject * obj)
{
VObjectStatus v_sts;
TV_SHADOW * sh;
int i;
L_CHAR * _url;
	_VM_OP_START_VOID
	if ( fw.tree_view_data == 0 )
		goto end;
	for ( i = 0 ; i < fw.tree_view_data_len ; i ++ )
		if ( ((VObject*)fw.tree_view_data[i].eye) == obj )
			break;
	if ( i == fw.tree_view_data_len )
		goto end;
	sh = &fw.tree_view_data[i];
	obj->get_status(&v_sts,VSF_VALUE);
	if ( sh->r ) {
		_url = ll_copy_str(get_url_str2(&sh->r->h.entry));
		switch ( v_sts.value ) {
		case 0:
			call_wf_set_overlay(&fw.sw,_url,0,WFF_HIDE);
			sh->flags &= ~WFF_HIDE;
			break;
		case 1:
			call_wf_set_overlay(&fw.sw,_url,WFF_HIDE,WFF_HIDE);
			sh->flags |= WFF_HIDE;
			break;
		}
		d_f_ree(_url);
	}
end:
	VM_OP_END
}

V_CALLBACK_D(eye_handler)
{
FLAME_WORK * fw;
	fw = (FLAME_WORK*)user_arg;
	fw->this_object->_eye_handler(object);
}

VexDraw *
new_VexDrawEye(VObjectStatus * v_sts,FLAME_WORK * fw,VImage ** imgs,V_CALLBACK(cb))
{
VexDraw * ret;
int vsf_value_eh;
	if ( imgs[0] == 0 )
		return 0;
	v_sts->padding.w = v_sts->padding.h = 0;
	v_sts->spacing.w = v_sts->spacing.h = 0;
	v_sts->size = v_sts->min_size = imgs[0]->size;
	v_sts->attr = VexDraw::click_rotate_zero;
	v_sts->value_event_handler = cb;
	v_sts->value_eh_arg = (void*)fw;
	if ( cb == 0 )
		vsf_value_eh = 0;
	else	vsf_value_eh = VSF_VALUE_EH;
	ret = VexDraw::create(v_sts,
			VSF_PARENT|VSF_ALIGN|VSF_SPACING|
			VSF_PADDING|VSF_MIN_SIZE|VSF_SIZE|
			VSF_VALUE|
			VSF_ATTR|vsf_value_eh);
	ret->set_images(2,imgs,imgs[0]->size);
	ret->set_status(v_sts,VSF_VALUE);
	return ret;
}


VexDraw *
new_VexDrawInfo(VObjectStatus * v_sts,FLAME_WORK * fw,VImage ** imgs,V_CALLBACK(cb))
{
VexDraw * ret;
int vsf_value_eh;
	if ( imgs[0] == 0 )
		return 0;
	v_sts->padding.w = v_sts->padding.h = 0;
	v_sts->spacing.w = v_sts->spacing.h = 0;
	//v_sts->size = v_sts->min_size = imgs[0]->size;
	v_sts->attr = VexDraw::press_img_zero;
	v_sts->value_event_handler = cb;
	v_sts->value_eh_arg = (void*)fw;
	if ( cb == 0 )
		vsf_value_eh = 0;
	else	vsf_value_eh = VSF_VALUE_EH;
	ret = VexDraw::create(v_sts,
			VSF_PARENT|VSF_ALIGN|VSF_SPACING|
			VSF_PADDING|//VSF_MIN_SIZE|VSF_SIZE|
			VSF_ATTR|vsf_value_eh);
	ret->set_images(2,imgs,imgs[0]->size);
	return ret;
}

void
VgbFlameStandard::_base_handler(VObject * obj)
{
VObjectStatus v_sts;
int v;
TV_SHADOW * sh, * sh2;
int i;
L_CHAR * _url;
	_VM_OP_START_VOID
	if ( fw.tree_view_data == 0 )
		goto end;
	for ( i = 0 ; i < fw.tree_view_data_len ; i ++ )
		if ( ((VObject*)fw.tree_view_data[i].base) == obj )
			break;
	if ( i == fw.tree_view_data_len )
		goto end;
	sh = &fw.tree_view_data[i];
	if ( sh->flags & WFF_BASE_LOCK )
		sh->flags &= ~WFF_BASE_LOCK;
	else	sh->flags |= WFF_BASE_LOCK;
	v_sts.value = ((sh->flags&WFF_BASE) >> WFF_BASE_OFFSET) + 1;
	v_sts.value_event_handler = 0;
	v_sts.value_eh_arg = 0;
	obj->set_status(&v_sts,VSF_VALUE_EH);

	obj->set_status(&v_sts,VSF_VALUE);

	v_sts.value_event_handler = base_handler;
	v_sts.value_eh_arg = (void*)&fw;
	obj->set_status(&v_sts,VSF_VALUE_EH);

	v = v_sts.value;
	if ( sh->flags & WFF_BASE_LOCK ) {
		for ( i = 0 ; i < fw.tree_view_data_len ; i ++ ) {
			sh2 = &fw.tree_view_data[i];
			if ( (VObject*)sh2->base == obj )
				continue;
			if ( !(sh2->flags & WFF_BASE_LOCK) )
				continue;
			sh2->flags &= ~WFF_BASE_LOCK;
			v_sts.value = ((sh2->flags&WFF_BASE) >> WFF_BASE_OFFSET) + 1;

			v_sts.value_event_handler = 0;
			v_sts.value_eh_arg = 0;
			sh2->base->set_status(&v_sts,VSF_VALUE_EH);

			sh2->base->set_status(&v_sts,VSF_VALUE);


			v_sts.value_event_handler = base_handler;
			v_sts.value_eh_arg = (void*)&fw;
			sh2->base->set_status(&v_sts,VSF_VALUE_EH);
		}
	}
	_url = ll_copy_str(get_url_str2(&sh->r->h.entry));
	if ( sh->flags & WFF_BASE_LOCK ) {
		call_wf_set_overlay(&fw.sw,_url,WFF_BASE_LOCK,WFF_BASE_LOCK);
	}
	else {
		call_wf_set_overlay(&fw.sw,_url,0,WFF_BASE_LOCK);
	}
	d_f_ree(_url);
end:
	VM_OP_END
}


V_CALLBACK_D(base_handler)
{
FLAME_WORK * fw;
	fw = (FLAME_WORK*)user_arg;
	fw->this_object->_base_handler(object);
}

VexDraw *
new_VexDrawBase(VObjectStatus * v_sts,FLAME_WORK * fw,VImage ** imgs,V_CALLBACK(cb))
{
VexDraw * ret;
	if ( imgs[0] == 0 )
		return 0;
	v_sts->padding.w = v_sts->padding.h = 0;
	v_sts->spacing.w = v_sts->spacing.h = 0;
	v_sts->size = v_sts->min_size = imgs[0]->size;
	v_sts->attr = VexDraw::click_rotate;
	v_sts->value_event_handler = cb;
	v_sts->value_eh_arg = (void*)fw;
	ret = VexDraw::create(v_sts,
			VSF_PARENT|VSF_ALIGN|VSF_SPACING|
			VSF_PADDING|VSF_MIN_SIZE|VSF_SIZE|
			VSF_ATTR);
	v_sts->spacing.w = v_sts->spacing.h = 0;
	ret->set_images(5,imgs,imgs[0]->size);
	if ( ret )
		ret->set_status(v_sts,VSF_VALUE);
	if ( ret && cb )
		ret->set_status(v_sts,VSF_VALUE_EH);
	return ret;
}

L_CHAR*
insert_copy_dd(L_CHAR * copy_dd,VStaticText * str);
L_CHAR*
insert_copy_dd(L_CHAR * copy_dd,VStaticText * str)
{
int len,len2;
VObjectStatus sts;
	if ( copy_dd )
		len = l_strlen(copy_dd);
	else	len = 0;
	str->get_status(&sts,VSF_DESC);
	len2 = l_strlen((L_CHAR*)sts.descriptor);
	if ( copy_dd )
		copy_dd = (L_CHAR*)d_re_alloc(copy_dd,sizeof(L_CHAR)*(len+len2+2));
	else	copy_dd = (L_CHAR*)d_alloc(sizeof(L_CHAR)*(len2+2));
	l_strcpy(&copy_dd[len],(L_CHAR*)sts.descriptor);
	copy_dd[len+len2] = '\n';
	copy_dd[len+len2+1] = 0;
//	d_f_ree((void*)sts.descriptor);
	return copy_dd;
}


extern "C" void test_set_buffer();


int
VgbFlameStandard::_flame_focus_handler(int type,int len,VBackColorView ** bcl)
{
int i,j;
L_CHAR * copy_dd;
VdataLString * vstr;
int ret;
	_VM_OP_START(0)
	ret = 0;
	switch ( type ) {
	case VMT_COPY:
		copy_dd = 0;
		for ( i = 0 ; i < fw.tree_view_data_len ; i ++ ) {
			for ( j = 0 ; j < len ; j ++ ) {
				if ( bcl[j] == fw.tree_view_data[i].main_bc )
					copy_dd = insert_copy_dd(
						copy_dd,
						fw.tree_view_data[i].main_text);
				if ( bcl[j] == fw.tree_view_data[i].chi_bc )
					copy_dd = insert_copy_dd(
						copy_dd,
						fw.tree_view_data[i].chi_text);
			}
		}
		vstr = new VdataLString(copy_dd);
		vstr->store_into_clipboard();
		ret = VMF_COPY;
		break;
	}
	VM_OP_END
	return ret;
}



int flame_focus_handler(
	int event_type,
	VObject * tv,
	int edit_type,
	int data1,
	VBackColorView  ** data2,
	void * arg)
{
int ret;
VgbFlameStandard * f;
	f = (VgbFlameStandard*)arg;
	switch ( event_type ) {
	case FHT_CLICK_BC:
		if ( data1 )
			ret = VMF_COPY;
		else	ret = 0;
		break;
	case FHT_OBEY_EDIT:
		ret = f->_flame_focus_handler(edit_type,data1,data2);
		break;
	case FHT_FOCUS_IN:
	case FHT_FOCUS_OUT:
		ret = 0;
		break;
	default:
		er_panic("flame_focus_handler");
	}
	return ret;
}



void
insert_tv_shadow(FLAME_WORK * fw,int nos,GBVIEW_LAYER_STATUS * ls)
{
int i;
TV_SHADOW * sh;
VObjectStatus v_sts;
int align;
VHAlignView * base,* chi;

	if ( fw->tree_view_data_len < nos )
		er_panic("insert_tv_shadow");
	fw->tree_view_data_len ++;
	fw->tree_view_data = (TV_SHADOW*)
		d_re_alloc(fw->tree_view_data,
			fw->tree_view_data_len*sizeof(TV_SHADOW));
	for ( i = fw->tree_view_data_len-1 ; i > nos ; i -- )
		fw->tree_view_data[i] = fw->tree_view_data[i-1];

	sh = &fw->tree_view_data[nos];
	sh->flags = ls->flags & WFF_BASE;
	sh->r = ls->r;
	sh->main_bc = 0;
	sh->chi_bc = 0;
	v_sts.parent = fw->sts.indicate_tree_obj->macro_base_parent();
	v_sts.padding.w = v_sts.padding.h = 3;
	v_sts.spacing.w = v_sts.spacing.h = 3;
	v_sts.alignv = VALIGN_TOP;
	v_sts.alignh = VALIGN_FILL;
	v_sts.visible = 1;
	v_sts.descriptor = l_string(std_cm,"BASE");
	base = VHAlignView::create(&v_sts,
			VSF_PADDING|VSF_SPACING|
			VSF_PARENT|
			VSF_ALIGN|
			VSF_DESC|
			VSF_VISIBLE);
	if ( fw->tree_view_data_dir == VSD_H_L2R )
		align = VALIGN_LEFT;
	else	align = VALIGN_RIGHT;
	v_sts.alignh = align;
	v_sts.descriptor = l_string(std_cm,"CHI");
	v_sts.visible = 0;
	v_sts.parent = fw->sts.indicate_tree_obj->macro_base_parent();
	chi = VHAlignView::create(&v_sts,
			VSF_PADDING|VSF_SPACING|
			VSF_PARENT|
			VSF_ALIGN|
			VSF_DESC|
			VSF_VISIBLE);
	if ( fw->tree_view_data_dir == VSD_H_L2R ) {
		v_sts.parent = base;
		v_sts.visible = 1;
		v_sts.descriptor = ls->entry_url;

		v_sts.value = (ls->flags&WFF_HIDE) >> WFF_HIDE_OFFSET;
		sh->eye = new_VexDrawEye(&v_sts,fw,(VImage**)fw->tree_view_eye,eye_handler);
		v_sts.value = ((ls->flags&WFF_BASE) >> WFF_BASE_OFFSET) + 1;
		sh->base = new_VexDrawBase(&v_sts,fw,(VImage**)fw->tree_view_base,base_handler);
		sh->info = new_VexDrawInfo(&v_sts,fw,(VImage**)fw->tree_view_info,0);
		sh->main_bc = static_cast<VBackColorView*>(
			v_sts.parent = fw->sts.indicate_tree_obj->get_backcolorview(
				&v_sts,
				VSF_PADDING|VSF_SPACING|
				VSF_PARENT|
				VSF_ALIGN|
				VSF_DESC|
				VSF_VISIBLE));
		v_sts.padding.w = v_sts.padding.h = 0;
		v_sts.spacing.w = v_sts.spacing.h = 0;
		sh->main_text = VStaticText::create(&v_sts,
				VSF_PADDING|VSF_SPACING|
				VSF_PARENT|
				VSF_ALIGN|
				VSF_DESC|
				VSF_VISIBLE);
		v_sts.padding.w = v_sts.padding.h = 0;
		v_sts.spacing.w = v_sts.spacing.h = 0;
		v_sts.parent = chi;
		v_sts.descriptor = l_string(std_cm,"Coordinate");
		sh->chi_bc = static_cast<VBackColorView*>(
			v_sts.parent = fw->sts.indicate_tree_obj->get_backcolorview(
				&v_sts,
				VSF_PARENT|
				VSF_ALIGN|
				VSF_DESC|
				VSF_VISIBLE));
		v_sts.padding.w = v_sts.padding.h = 0;
		v_sts.spacing.w = v_sts.spacing.h = 0;
		sh->chi_text = VStaticText::create(&v_sts,
				VSF_PADDING|VSF_SPACING|
				VSF_PARENT|
				VSF_ALIGN|
				VSF_DESC|
				VSF_VISIBLE);
	}
	else {
		v_sts.parent = base;
		v_sts.visible = 1;
		sh->main_bc = static_cast<VBackColorView*>(
			v_sts.parent = fw->sts.indicate_tree_obj->get_backcolorview(
				&v_sts,
				VSF_PARENT|
				VSF_ALIGN|
				VSF_DESC|
				VSF_VISIBLE));
		v_sts.descriptor = ls->entry_url;
		v_sts.padding.w = v_sts.padding.h = 0;
		v_sts.spacing.w = v_sts.spacing.h = 0;
		sh->main_text = VStaticText::create(&v_sts,
				VSF_PADDING|VSF_SPACING|
				VSF_PARENT|
				VSF_ALIGN|
				VSF_DESC|
				VSF_VISIBLE);
		v_sts.padding.w = v_sts.padding.h = 0;
		v_sts.spacing.w = v_sts.spacing.h = 0;
		v_sts.parent = base;
		sh->info = new_VexDrawInfo(&v_sts,fw,fw->tree_view_info,0);

		v_sts.value = (ls->flags&WFF_HIDE) >> WFF_BASE_OFFSET;
		sh->base = new_VexDrawBase(&v_sts,fw,(VImage**)fw->tree_view_base,base_handler);
		v_sts.value = ((ls->flags&WFF_BASE) >> WFF_HIDE_OFFSET) + 1;
		sh->eye = new_VexDrawEye(&v_sts,fw,fw->tree_view_eye,eye_handler);
		v_sts.parent = chi;
		v_sts.descriptor = l_string(std_cm,"Coordinate");
		sh->chi_bc = static_cast<VBackColorView*>(
			v_sts.parent = fw->sts.indicate_tree_obj->get_backcolorview(
				&v_sts,
				VSF_PARENT|
				VSF_ALIGN|
				VSF_DESC|
				VSF_VISIBLE));
		v_sts.padding.w = v_sts.padding.h = 0;
		v_sts.spacing.w = v_sts.spacing.h = 0;
		sh->chi_text = VStaticText::create(&v_sts,
				VSF_PADDING|VSF_SPACING|
				VSF_PARENT|
				VSF_ALIGN|
				VSF_DESC|
				VSF_VISIBLE);
	}
	fw->sts.indicate_tree_obj->insert_line(base,nos);
	fw->sts.indicate_tree_obj->attach_child(chi,nos);
}

void
test_count(FLAME_WORK * fw)
{
int i;
VObjectStatus v_sts;
char buf[100];
VxlTreeViewStatus tv_sts;
	fw->sts.indicate_tree_obj->get_xltreeview_status(&tv_sts,
				VSF_XL_TREEVIEW_LINE_NOS);
	for ( i = 0 ; i < fw->tree_view_data_len ; i ++ ) {
		sprintf(buf,"Coordinate%i-%i-%i",i,
			tv_sts.line_nos,fw->tree_view_data_len);
		v_sts.descriptor = l_string(std_cm,buf);
		fw->tree_view_data[i].chi_text->set_status(&v_sts,VSF_DESC);
	}
}

void
VgbFlameStandard::_vfq_event_task_insert(VGB_FLAME_T * n)
{
GBVIEW_STATUS gb_sts;
GBVIEW_LAYER_STATUS * ls;
int nos;
TV_SHADOW * sh;
	if ( fw.sts.indicate_tree_obj == 0 )
		return;
	if ( call_wf_status(&n->fw->sw,&gb_sts,CALL_STS_CACHE_NORMAL) < 0 )
		return;
	_VM_OP_START_VOID
	if ( fw.sts.indicate_tree_obj == 0 )
		goto end;
	nos = fw.tree_view_data_len-1;
	for ( ls = gb_sts.layers ; ls ; ) {
		if ( nos < 0 ) {
			insert_tv_shadow(&fw,0,ls);
			ls = ls->next;
			continue;
		}
		sh = &fw.tree_view_data[nos];
		if ( sh->r == ls->r ) {
			nos --;
			ls = ls->next;
			continue;
		}
		if ( shadow_search(fw.tree_view_data,nos,ls->r) ) {
			// EXIST -> delete
			delete_tv_shadow(&fw,nos);
			nos --;
			continue;
		}
		else {
			// NOT EXIST -> insert
			insert_tv_shadow(&fw,nos+1,ls);
			ls = ls->next;
			continue;
		}
	}
	for ( ; nos >= 0 ; nos -- ) {
		delete_tv_shadow(&fw,nos);
	}


end:
	wf_free_status(&gb_sts);
	VM_OP_END
}

void
VgbFlameStandard::_vfq_event_task_change_base(VGB_FLAME_T * n)
{
GBVIEW_STATUS gb_sts;
GBVIEW_LAYER_STATUS * ls;
int nos;
TV_SHADOW * sh;
int sv;
VObjectStatus st;
	if ( fw.sts.indicate_tree_obj == 0 )
		return;
	if ( call_wf_status(&n->fw->sw,&gb_sts,CALL_STS_CACHE_NORMAL) < 0 )
		return;
	_VM_OP_START_VOID
	if ( fw.sts.indicate_tree_obj == 0 )
		goto end;
	for ( ls = gb_sts.layers ; ls ; ls = ls->next )
		if ( ls->id == gb_sts.current )
			break;
	if ( ls == 0 )
		goto end;
	for ( nos = 0 ; nos < fw.tree_view_data_len ; nos ++ ) {
		sh = &fw.tree_view_data[nos];
		sv = 0;
		if ( sh->r == ls->r ) {
			if ( !(sh->flags & WFF_BASE_CURRENT) )
				sv = 1;
			sh->flags |= WFF_BASE_CURRENT;
		}
		else {
			if ( sh->flags & WFF_BASE_CURRENT )
				sv = 1;
			sh->flags &= ~WFF_BASE_CURRENT;
		}
		if ( sv ) {
			st.value = ((sh->flags & WFF_BASE) >> WFF_BASE_OFFSET) + 1;

			st.value_event_handler = 0;
			st.value_eh_arg = 0;
			sh->base->set_status(&st,VSF_VALUE_EH);

			sh->base->set_status(&st,VSF_VALUE);

			st.value_event_handler = base_handler;
			st.value_eh_arg = (void*)&fw;
			sh->base->set_status(&st,VSF_VALUE_EH);
		}
	}
end:
	wf_free_status(&gb_sts);
	VM_OP_END
}


void
VgbFlameStandard::_vfq_event_task_point(VGB_FLAME_T * n)
{
GBVIEW_STATUS gb_sts;
TV_SHADOW * sh;
INDICATE * in;
VObjectStatus v_sts;
L_CHAR * buf;
double dd_x,dd_y,dd;

	if ( fw.sts.indicate_tree_obj == 0 )
		return;
	call_wf_indicate(&n->fw->sw,0,n->pt.x,n->pt.y,0);
	if ( call_wf_status(&n->fw->sw,&gb_sts,CALL_STS_CACHE_NORMAL) < 0 )
		return;
	_VM_OP_START_VOID
	buf = (L_CHAR*)d_alloc(1000);
	for ( in = gb_sts.indicate ; in ; in = in->next ) {
		if ( (in->flags & IF_COORDINATE) == 0 )
			continue;
		sh = shadow_search(fw.tree_view_data,
			fw.tree_view_data_len,in->target);
		if ( sh == 0 )
			continue;
		if ( sh->chi_text == 0 )
			continue;
		dd_x = (in->result[1].x - in->result[0].x);
		dd_y = (in->result[1].y - in->result[0].y);
		dd = sqrt(dd_x*dd_x + dd_y*dd_y);
		if ( dd == 0 )
			dd = -1;
		else dd = 1/dd;
		ss_sprintf(buf,"(%f%ls %f%ls) reso=%fdot/%ls",
			in->result[0].x, in->unit,
			in->result[0].y, in->unit,
			dd,in->unit);
		v_sts.descriptor = buf;
		sh->chi_text->set_status(&v_sts,VSF_DESC);
	}
	d_f_ree(buf);
	wf_free_status(&gb_sts);
	VM_OP_END
}


void
free_vgb_flame_t(VGB_FLAME_T * n)
{
	d_f_ree(n->h.key);
	d_f_ree(n);
}

extern "C"
void vfq_event_task(TKEY t)
{
VGB_FLAME_T * n,* n_next;
L_CHAR * key;
XL_INTERPRETER * xli;

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

	key = touch_qkey(&vgb_flame_queue);
	n = n_next = 0;
	for ( ; ; ) {
		gc_push(0,0,"vfq_event_task");
		n_next = (VGB_FLAME_T*)delete_queue(&vgb_flame_queue,
					(int(*)())sq_key_cond,(void*)key,0);
		if ( n_next && n ) {
			if ( n->type == n_next->type ) {
				free_vgb_flame_t(n);
				n = n_next;

				gc_pop(0,0);
				continue;
			}
		}
		else if ( n_next ) {
			n = n_next;

			gc_pop(0,0);
			continue;
		}
		else if ( n == 0 ) {
			gc_pop(0,0);
			break;
		}
		switch ( n->type ) {
		case VGBFT_INSERT:
			n->fw->this_object->_vfq_event_task_insert(n);
			break;
		case VGBFT_POINT:
			n->fw->this_object->_vfq_event_task_point(n);
			break;
		case VGBFT_CHANGE_BASE:
			n->fw->this_object->_vfq_event_task_change_base(n);
			break;
		case VGBFT_INFOLIST:
			_interface_infolist_func(n->fw,n);
			break;
		default:
			er_panic("vfg_event_task");
		}
		free_vgb_flame_t(n);
		n = n_next;

		gc_pop(0,0);
	}
	release_qkey(&vgb_flame_queue,key);

	close_self_interpreter();
}


void
set_move_mode(FLAME_WORK * fw,int mode)
{
VObjectStatus sts;
	sts.value = true;
	if ( fw->sts.select_mode == mode )
		return;
	fw->sts.select_mode = mode;
	switch ( mode ) {
	case VGB_MODE_GRAB:
		if ( fw->sts.grab_mode_button ) {
			fw->sts.grab_mode_button->set_status(&sts,VSF_VALUE);
			sts.enabled = true;
			if ( fw->sts.zoom_in )
				fw->sts.zoom_in->set_status(&sts,VSF_ENABLED);
			if ( fw->sts.zoom_out )
				fw->sts.zoom_out->set_status(&sts,VSF_ENABLED);
		}
		break;
	case VGB_MODE_ROTATE:
		if ( fw->sts.rotate_mode_button ) {
			fw->sts.rotate_mode_button->set_status(&sts,VSF_VALUE);
			sts.enabled = false;
			if ( fw->sts.zoom_in )
				fw->sts.zoom_in->set_status(&sts,VSF_ENABLED);
			if ( fw->sts.zoom_out )
				fw->sts.zoom_out->set_status(&sts,VSF_ENABLED);
		}
		break;
	default:
		er_panic("set_move_mode");
	}
}

void
get_marshaler_mode(FLAME_WORK * fw,VMarshaler * m)
{
int mode;
	mode = m->get_value(VM_MODE);
	switch ( mode ) {
	case VGB_MODE_GRAB:
	case VGB_MODE_ROTATE:
		lock_select_mode(fw);
		fw->sts.select_mode = mode;
		unlock_select_mode(fw);
		break;
	default:
		log_printf(LOG_ERROR,LOG_LAYER_UI,0,"mode error %i\n",mode);
	}
}

void
redraw_handler(FLAME_WORK * fw,VSize size)
{
int change;
GBVIEW_STATUS sts;
GBVIEW_PLANE gbp;
int seq;
VImage * img;

	change = 0;
	if ( call_wf_status(&fw->sw,&sts,CALL_STS_CACHE_NORMAL) < 0 )
		return;
	sts.flags = 0;
	if ( sts.width != size.w ) {
		sts.width = size.w;
		if ( sts.width < 1 )
			sts.width = 1;
		sts.flags |= SF_WIDTH;
		change = 1;
	}
	if ( sts.height != size.h ) {
		sts.height = size.h;
		if ( sts.height < 1 )
			sts.height = 1;
		sts.flags |= SF_HEIGHT;
		change = 1;
	}

	if ( change ) {
	void make_img(short,short,VImage*);

		opac_stop(fw);
		seq = call_wf_set_status(&fw->sw,&sts);

		checkin_seq(fw,seq);
		if ( seq && fw->im && fw->fw_active ) {
			img = v_image_new(size.w, size.h, 32);
			v_image_draw_start(img, 0);
			make_img(size.w,size.h,img);
			v_image_draw_end(img);
			fw->im->set_image(img);
			v_image_unref(img);
		}
		checkout_seq(fw,seq);

		seq = call_wf_redraw(&fw->sw,&gbp,0,0,sts.width,sts.height);

		checkin_seq(fw,seq);
		if ( seq && fw->im && fw->fw_active ) {
			set_plane(fw,&gbp);
			wf_free_plane(&gbp);
		}
		checkout_seq(fw,seq);

	}
	wf_free_status(&sts);
}


void
indicate_coordinate(FLAME_WORK * fw,int x,int y)
{
VGB_FLAME_T *n;
char buf[20];
	if ( fw->sts.indicate_tree_obj == 0 )
		return;
	sprintf(buf,"%p",fw);
	n = (VGB_FLAME_T*)new_queue_node(sizeof(*n));
	n->type = VGBFT_POINT;
	n->fw = fw;
	n->h.key = nl_copy_str(std_cm,buf);
	n->pt.x = x;
	n->pt.y = y;
	insert_queue(&vgb_flame_queue,n,0);
}


void
click_op(FLAME_WORK * fw)
{
GBVIEW_STATUS sts;
int x,y;


	x = fw->press.x;
	y = fw->press.y;
	call_wf_click(&fw->sw,&sts,0,x,y);
	if ( sts.flags & SF_REFERENCE )
		set_change_page(n_string(std_cm,sts.reference),1);

	wf_free_status(&sts);
}



void
image_button_handler(FLAME_WORK * fw,int subtype,int t,int x,int y)
{
GB_POINT rp,from;

	switch ( subtype ) {
	case V_EV_MOUSE_DOWN:
		if ( fw->focus ) {
			fw->focus->focus();
			fw->this_object->_flame_focus_command_status();
		}
		fw->mode = GBM_PRESS_IMAGE;
		fw->press.x = x;
		fw->press.y = y;
		fw->press_time = t;
/*
		switch ( fw->sts.select_mode ) {
		case VGB_MODE_ROTATE:
			set_opac_mode(fw,&ms_rotate);
			break;
		case VGB_MODE_GRAB:
			set_opac_mode(fw,&ms_grab);
			break;
		default:
			er_panic("button_handler");
		}

		set_opening_state_query();
*/
		return;
	case V_EV_MOUSE_UP:
		if ( fw->mode == GBM_PRESS_IMAGE ) {
			click_op(fw);
		}
		fw->mode = GBM_IDLE;
		fw->press.x = x;
		fw->press.y = y;
		set_opac_mode(fw,0);
		break;
	case V_EV_MOUSE_MOVE:
		if ( fw->mode == GBM_PRESS_IMAGE ) {
			switch ( fw->sts.select_mode ) {
			case VGB_MODE_ROTATE:
				set_opac_mode(fw,&ms_rotate);
				break;
			case VGB_MODE_GRAB:
				set_opac_mode(fw,&ms_grab);
				break;
			default:
				er_panic("button_handler");
			}
			fw->mode = GBM_MOVE_IMAGE;
		}
		if ( (fw->mode & GBM_PRESS) &&
				fw->sts.select_mode == VGB_MODE_ROTATE ) {

			from.x = fw->press.x;
			from.y = fw->press.y;
			rp.x = x;
			rp.y = y;

			fw->press.x = x;
			fw->press.y = y;
			opac_move(fw);

			checkin_seq(fw,-1);
			if ( fw->im && fw->fw_active )
				fw->im->redraw();
			checkout_seq(fw,-1);
		}
		else if ( (fw->mode & GBM_PRESS) &&
				fw->sts.select_mode == VGB_MODE_GRAB ) {

			fw->press.x = x;
			fw->press.y = y;
			opac_move(fw);

			checkin_seq(fw,-1);
			if ( fw->im && fw->fw_active )
				fw->im->redraw();
			checkout_seq(fw,-1);
		}

		fw->im->mouse_move_event_done();

		if ( fw->mode == GBM_IDLE ) {
			indicate_coordinate(fw,x,y);

			return;
		}
		if ( fw->mode != GBM_PRESS_IMAGE )
			return;
		break;
	default:
		return;
	}
}

int
flame_status_check(FLAME_WORK * fw)
{
VgbFlameSwitchStatus ss;
VExError er;
	er = fw->this_object->get_switch_status(&ss,VSF_FLAME_S_MODE);
	if ( er.code )
		return -1;
	return ss.mode;
}

V_CALLBACK_D(instop_callback)
{
FLAME_WORK * fw;
INFO_LIST * il;
GBVIEW_STATUS sts;
XL_SEXP * ind;
	fw = (FLAME_WORK *)user_arg;
	if ( fw->instop_time + INSTOP_TIMEOUT > get_xltime() )
		return;
	if ( fw->instop_update.x == fw->instop_pt.x &&
			fw->instop_update.y == fw->instop_pt.y )
		return;
ss_printf("INSTOP!!\n");
	fw->instop_update = fw->instop_pt;

	call_wf_click(&fw->sw,&sts,0,
		fw->instop_update.x,
		fw->instop_update.y);
	gc_push(0,0,"instop_callback");
	if ( sts.infolist ) {
		ss_printf("ON_MOUSE INFORMATION\n");
		for ( il = sts.infolist ; il ; il = il->next ) {
			ss_printf("\t>> ");
			print_sexp(s_stdout,il->info,0);
			ss_printf("\n");
		}
		ind = 0;
		for ( il = sts.infolist ; il ; il = il->next ) {
			if ( get_type(il->info) == XLT_NULL )
				continue;
			ind = cons(il->info,ind);
		}
		if ( ind && fw->oattribute_handler ) {
			(*fw->oattribute_handler)(
				object,
				fw->oattribute_handler_arg,
				ind);
		}
	}
	gc_pop(0,0);
	wf_free_status(&sts);
}

void
instop_tick(int data)
{
FLAME_WORK * fw;
	fw = (FLAME_WORK *)data;
	vq_insert_callback(
		fw->this_object,
		instop_callback,
		(void*)fw,
		0,
		0);

}


void
instop_handler(FLAME_WORK * fw,int subtype,int t,int x,int y,int w,int h)
{
	if ( fw->mode != GBM_IDLE ) {
		fw->instop_in = 0;
		del_tick_with_data((void(*)())instop_tick,(int)fw);
		return;
	}
	if ( subtype != V_EV_MOUSE_MOVE ) {
		fw->instop_in = 0;
		del_tick_with_data((void(*)())instop_tick,(int)fw);
		return;
	}
	if ( x < 0 || y < 0 ||
			x >= w || y >= h ) {
		fw->instop_in = 0;
		del_tick_with_data((void(*)())instop_tick,(int)fw);
	}
	else  {
		if ( fw->instop_pt.x != x ||
				fw->instop_pt.y != y ) {
			fw->instop_in = 1;
			fw->instop_pt.x = x;
			fw->instop_pt.y = y;
			fw->instop_time = get_xltime();
			del_tick_with_data((void(*)())instop_tick,(int)fw);
			new_tick((void(*)(int))instop_tick,-INSTOP_TIMEOUT,(int)fw);
		}
	}
}


V_CALLBACK_D(drag_image_handler)
{
XL_INTERPRETER * xli;
int subtype;
int t;
int x,y;
VImage * img;
int w,h;
VMouseEvent* ev = (VMouseEvent*)sys_arg;
FLAME_WORK * fw;
	fw = (FLAME_WORK *)user_arg;
	if ( flame_status_check(fw) <= 0 )
		return;
	t = 0;

	xli = get_my_xli();

	if ( xli == 0 ) {
		xli = new_xl_interpreter();
		xli->a_type = XLA_SELF;
		setup_i(xli);
	}
	x = ev->point.x;
	y = ev->point.y;
	img = ((VDraw*)object)->draw_start();
	w = img->size.w;
	h = img->size.h;
	((VDraw*)object)->draw_end();
	subtype = ev->type;

	instop_handler(fw,subtype,t,x,y,w,h);

	if ( x < 0 )
		x = 0;
	if ( x >= w )
		x = w-1;
	if ( y < 0 )
		y = 0;
	if ( y >= h )
		y = h-1;
	image_button_handler(fw,subtype,t,x,y);

}

void
limit_opac(FLAME_WORK * fw)
{
	set_opac_mode(fw,0);
}


V_CALLBACK_D(zoom_in)
{
WF_ID wfid;
GBVIEW_STATUS sts;
FLAME_WORK * fw;

	fw = (FLAME_WORK*)user_arg;
	if ( flame_status_check(fw) <= 0 )
		return;
	if ( fw->sts.select_mode != VGB_MODE_GRAB )
		return;
	if ( call_wf_status(&fw->sw,&sts,CALL_STS_CACHE_NORMAL) < 0 )
		return;
	if ( fw->ms != &ms_zoom ) {
		fw->press_zoom = sts.flame_base_resolution;
		set_opac_mode(fw,&ms_zoom);
	}
	fw->mode = GBM_PRESS_ZOOM_IN;
	wfid = sts.current;
	wf_free_status(&sts);
	if ( wfid ) {

		fw->press_zoom *= RESO_PITCH;
		opac_move(fw);

		checkin_seq(fw,-1);
		if ( fw->im && fw->fw_active )
			fw->im->redraw();
		checkout_seq(fw,-1);

		new_tick((void(*)(int))limit_opac,-OPAC_STOP_TIMEOUT,(int)fw);
	}
	fw->mode = GBM_IDLE;
}

V_CALLBACK_D(zoom_out)
{
WF_ID wfid;
GBVIEW_STATUS sts;
FLAME_WORK * fw;
	fw = (FLAME_WORK*)user_arg;
	if ( fw->focus )
	if ( flame_status_check(fw) <= 0 )
		return;
	if ( fw->sts.select_mode != VGB_MODE_GRAB )
		return;
	if ( call_wf_status(&fw->sw,&sts,CALL_STS_CACHE_NORMAL) < 0 )
		return;
	if ( fw->ms != &ms_zoom ) {
		fw->press_zoom = sts.flame_base_resolution;
		set_opac_mode(fw,&ms_zoom);
	}
	fw->mode = GBM_PRESS_ZOOM_OUT;
	wfid = sts.current;
	wf_free_status(&sts);
	if ( wfid ) {
		fw->press_zoom /= RESO_PITCH;
		opac_move(fw);

		checkin_seq(fw,-1);
		if ( fw->im && fw->fw_active )
			fw->im->redraw();
		checkout_seq(fw,-1);

		new_tick((void(*)(int))limit_opac,-OPAC_STOP_TIMEOUT,(int)fw);
	}
	fw->mode = GBM_IDLE;
}

/*
V_CALLBACK_D(webpage_handler)
{
char * page;

	page = (char*)d_alloc(1000);
	sprintf(page,"http://%s:%i/",
		http_hostname,http_port);
	set_change_page(page,1);
	d_f_ree(page);
}
*/


V_CALLBACK_D(mode_button_handler)
{
FLAME_WORK * fw;
int mode;
VObjectStatus sts;

	object->get_status(&sts,VSF_VALUE);
	if ( sts.value == false )
		return;
	fw = (FLAME_WORK *)user_arg;
	if ( flame_status_check(fw) <= 0 )
		return;
	lock_select_mode(fw);
	if ( fw->sts.grab_mode_button == object )
		mode = VGB_MODE_GRAB;
	else if ( fw->sts.rotate_mode_button == object )
		mode = VGB_MODE_ROTATE;
	else if ( fw->sts.click_mode_button == object )
		mode = VGB_MODE_CLICK;
	else	return;
	set_move_mode(fw,mode);
	unlock_select_mode(fw);
}



void
make_img(short w, short h, VImage *img)
{
	for ( int x = 0 ; x < w ; x++ ) {
		for ( int y = 0 ; y < h ; y++ ) {
			SET_RGB8_32(img->buf_32[x+img->w_border*y],0,0,0,0);
		}
	}
}

V_CALLBACK_D(resize_handler)
{
FLAME_WORK * fw;
	fw = (FLAME_WORK*)user_arg;
	if ( flame_status_check(fw) <= 0 )
		return;
	redraw_handler(fw,*(VSize*)sys_arg);
}

void
pixelmap_task(TKEY d)
{
GBVIEW_STATUS sts;
GBVIEW_PLANE gbp;
XL_INTERPRETER * xli;
int seq;
int setp = 0;
FLAME_WORK * fw;
int st_ck;

	fw = (FLAME_WORK*)GET_TKEY(d);

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


	fw->redraw_flag = 1;
	for ( ; ; ) {
		st_ck = flame_status_check(fw);
		lock_task(interface_redraw_lock);
		for ( ; st_ck > 0 && fw->redraw_flag && fw->fw_active ; ) {
			if ( fw->im_out_off )
				break;

			fw->redraw_flag = 0;
			unlock_task(interface_redraw_lock,"pixelmap_task");

			if ( call_wf_status(&fw->sw,&sts,CALL_STS_CACHE_NORMAL) < 0 )
				goto next;

			seq = call_wf_redraw(&fw->sw,&gbp,0,0,sts.width,sts.height);

			checkin_seq(fw,seq);
			if ( seq && fw->im && fw->fw_active && seq ) {
				setp = set_plane(fw,&gbp);
				wf_free_plane(&gbp);
				if ( gbp.r.r.tl.x != gbp.r.r.br.x &&
						setp == 0 ) {
				VRect rr;
					rr = rect_conv_i2s(gbp.r.r);
					fw->im->redraw(&rr);
				}
			}


			checkout_seq(fw,seq);

			wf_free_status(&sts);
		next:
			lock_task(interface_redraw_lock);
		}
		if ( fw->fw_active == 0 ) {
			unlock_task(interface_redraw_lock,"redraw");
			break;
		}
		sleep_task((int)&fw->redraw_flag,interface_redraw_lock);
	}
	close_self_interpreter();
}

void
setup_indicate(FLAME_WORK * fw)
{
VgbIndicate * obj;
int i;
VgbIndicateMeter m;
#define RI_RATE	5
	obj = fw->sts.indicate_obj;
	if ( obj == 0 )
		return;
	m.ary[0] = fw->ri.d.beam;
	for ( i = 0 ; i < 5 ; i ++ )
		m.ary[i+1] = fw->ri.d.loading_res[i]*RI_RATE;
	for ( i = 0 ; i < 5 ; i ++ )
		m.ary[i+1+5] = fw->ri.d.ready_res[i]*RI_RATE;
	m.ary[1+5+5] = (fw->ri.d.loading_res[5] + fw->ri.d.ready_res[5])*RI_RATE;
	obj->set_indicate_meter(&m,(1<<12)-1);
}

typedef struct indicate_from_radar_t {
	RADAR_INDICATE		ri;
	FLAME_WORK*		fw;
} INDICATE_FROM_RADAR_T;

V_CALLBACK_D(cb_indicate_from_radar)
{
INDICATE_FROM_RADAR_T * t;
	t= (INDICATE_FROM_RADAR_T*)user_arg;
	t->fw->ri = t->ri;
	setup_indicate(t->fw);
}

void
indicate_from_radar(
	RADAR_INDICATE * ri,
	void * _fw)
{
INDICATE_FROM_RADAR_T * t;
	t = (INDICATE_FROM_RADAR_T*)d_alloc(sizeof(*t));
	t->ri = *ri;
	t->fw = (FLAME_WORK*)_fw;
	vq_insert_callback(
		t->fw->this_object,
		cb_indicate_from_radar,
		(void*)t,
		0,
		0);
}

void
VgbFlameStandard::_flame_focus_command_status()
{
	fw.focus->set_editable_flags(VMF_COPY);
}

V_CALLBACK_D(flame_focus_command_status)
{
VgbFlameStandard * obj;
	obj = static_cast<VgbFlameStandard*>(user_arg);
	obj->_flame_focus_command_status();
}

void
VgbFlameStandard::_flame_focus_obey_command(int type)
{
VImage * img;
VdataImage *im;
	_VM_OP_START_VOID
	switch ( type ) {
	case VMT_COPY:
		im = new VdataImage(img = v_copy_image(fw.im));
		v_image_unref(img);
		im->store_into_clipboard();
		break;
	default:
		ss_printf("OBEY_COMMAND %i\n",type);
	}
	VM_OP_END
}

V_CALLBACK_D(flame_focus_obey_command)
{
VgbFlameStandard * obj;
int type;
	type = *(int*)sys_arg;
	obj = static_cast<VgbFlameStandard*>(user_arg);
	obj->_flame_focus_obey_command(type);
}



VExError
VgbFlameStandard::create_do(const VObjectStatus* s, int flags,VObject * nmp, void * arg)
{
VImage * img;
GBVIEW_STATUS wf_sts;
VObjectStatus sts;
VExError err;
VObjectAppStatusAry * app;
VgbFlameStatus * in_sts;
int in_flags;

	if ( arg ) {
		app = (VObjectAppStatusAry*)arg;
		in_sts = (VgbFlameStatus*)app[0].sts;
		in_flags = app[0].flags;
	}
	else {
		in_sts = 0;
		in_flags = 0;
	}
	
	
	err = initial_VExError(V_ER_NO_ERR,0,0);

	info = 0;

	memset(&fw,0,sizeof(fw));

	fw.this_object = this;
	fw.seq = 0;
	fw.seq_lock = 0;
	fw.fw_active = 1;
	fw.im = 0;
	fw.im_out_off = 0;
	fw.mode = GBM_IDLE;
	fw.press.x = fw.press.y = 0;
	fw.press_zoom = 1;
	fw.press_time = 0;
	fw.ss = 0;
	fw.last_shot = 0;
	fw.start_shot = 0;
	fw.ms = 0;

	fw.select_flag = 0;

	fw.sts.select_mode = VGB_MODE_GRAB;

	create_task((void(*)())pixelmap_task,(int)&fw,PRI_REDRAW);
	
	wf_sts.flags = SF_EVENT;
	wf_sts.event = interface_event_func;
	wf_sts.event_user_arg = (void*)&fw;
	call_wf_set_status(&fw.sw,&wf_sts);

	sts = *s;
	if ( (flags & VSF_SIZE) == 0 ) {
		sts.size.w = 600;
		sts.size.h = 400;
	}
	img = v_image_new(sts.size.w,sts.size.h, 32);
	v_image_draw_start(img, 0);
	make_img(sts.size.w,sts.size.h,img);
	v_image_draw_end(img);

	// create_add_children_do

	if ( in_flags & VSF_FLAME_FOCUS ) {
		sts.parent = this;
		fw.focus = VFocusView::create(
				&sts,VSF_PARENT|flags,&err);
		fw.focus->set_obey_command_handler(flame_focus_obey_command, (void*)this);
		fw.focus->set_command_status_handler(flame_focus_command_status, (void*)this);
		sts.parent = fw.focus;
		sts.attr = VDraw::mouse_move_wait;
		sts.padding.h = sts.padding.w = 4;
		sts.spacing.h = sts.spacing.w = 0;
		fw.im = VDraw::create(&sts, 
			VSF_PARENT|VSF_ATTR|VSF_PADDING|VSF_SPACING|flags, &err);
	}
	else {
		fw.focus = 0;
		sts.parent = this;
		sts.attr = VDraw::mouse_move_wait;
		fw.im = VDraw::create(&sts, VSF_PARENT | VSF_ATTR | flags, &err);
	}
	if ( err.code ) {
		destroy();
		return err;
	}
	VError e = fw.im->set_image(img, img->size);
	if ( e != V_ER_NO_ERR ) {
		err = initial_VExError(e,0,0);
		fw.im->destroy();
		destroy();
		return err;
	}
	v_image_unref(img);
	fw.im->redraw();
	fw.im->set_resize_event_handler(resize_handler,&fw);
	fw.im->set_mouse_event_handler(drag_image_handler,&fw);

//	create_task((void(*)())gbf_test_task,(int)this,5);

	return err;
}

VExError 
VgbFlameStandard::create_do_out_of_lock(
	const VObjectStatus *,int flags,VObject * nmp,void * arg)
{
VgbFlameStatus * in_sts;
int in_flags;
VObjectAppStatusAry * app;
	if ( arg == 0 )
		return initial_VExError(V_ER_NO_ERR,0,0);
	app = (VObjectAppStatusAry*)arg;
	in_sts = (VgbFlameStatus*)app[0].sts;
	in_flags = app[0].flags;
	in_flags &= ~(VSF_FLAME_FOCUS);
	if ( in_sts == 0 )
		return initial_VExError(V_ER_NO_ERR,0,0);
	return this->set_flame_status(in_sts,in_flags);
}

void
all_clear_flame_status(VgbFlameStatus * s)
{
	memset(s,0,sizeof(*s));
}

void
all_clear_flame_switch_status(VgbFlameSwitchStatus * s)
{
	if ( s->format )
		d_f_ree(s->format);
	if ( s->quality )
		d_f_ree(s->quality);
	if ( s->peripheral )
		d_f_ree(s->peripheral);
	if ( s->parameter )
		d_f_ree(s->parameter);
	if ( s->agent_url )
		d_f_ree(s->agent_url);
	memset(s,0,sizeof(*s));
}


void
all_clear_fw(FLAME_WORK * fw)
{
	all_clear_flame_status(&fw->sts);
	all_clear_flame_switch_status(&fw->sw_sts);
}


void
VgbFlameStandard::destroy_do(VObject * nmp)
{
	all_clear_fw(&fw);
	call_wf_set_flame_switch(&fw.sw,SW_MODE_IDLE,0,0,0,0,0);
	checkin_seq(&fw,-1);
	if ( fw.im ) {
//		fw.im->destroy();
		fw.im = 0;
	}
	lock_task(interface_redraw_lock);
	fw.fw_active = 0;
	wakeup_task((int)&fw);
	wakeup_task((int)&fw.redraw_flag);
	unlock_task(interface_redraw_lock,"VgbFlameStandard");
	checkout_seq(&fw,-1);
}


VExError
VgbFlameStandard::get_status(VObjectStatus * s,int flags) const
{
VExError err;
GBVIEW_STATUS wf_sts;


	err = initial_VExError(V_ER_NO_ERR,flags,0);
	if ( flags & VSF_SIZE ) {
		VM_OP_START_EX
		wf_sts.flags = SF_WIDTH|SF_HEIGHT;
		if ( call_wf_status((FLAME_SWITCH*)&fw.sw,&wf_sts,CALL_STS_CACHE_NORMAL) >= 0 ) {
			s->size.w = wf_sts.width;
			s->size.h = wf_sts.height;
			wf_free_status(&wf_sts);
			err.code = V_ER_NOT_READY;
			err.subcode2 = VSF_SIZE;
		}
		flags &= ~VSF_SIZE;
		VM_OP_END
	}
	err.subcode1 = flags;
	err = merge_VExError_vstatus_type(err,VMacro::get_status(s,flags));
	return err;
}

VExError
VgbFlameStandard::set_status(const VObjectStatus * s,int flags)
{
VExError err;
	err = initial_VExError(V_ER_NO_ERR,flags,0);
	if ( flags & VSF_SIZE ) {
		VM_OP_START_EX
		redraw_handler(&fw,s->size);
		err.subcode1 &= ~ VSF_SIZE;
		VM_OP_END
	}
	flags &= ~VSF_ATTR; // not to unset VDraw::mouse_move_wait
	err = merge_VExError_vstatus_type(err,VMacro::set_status(s,flags));
	return err;
}

VgbFlameStandard::~VgbFlameStandard()
{
}


VExError
VgbFlameStandard::set_switch_status(const VgbFlameSwitchStatus * s,int flags)
{
int status;
#define _S_STATUS_SET	0x00000001
#define _S_STATUS_FLAME	0x00000002
int seq;
GBVIEW_STATUS gs;
VExError err;
	VM_OP_START_EX
	status = 0;
	err.code = V_ER_NO_ERR;
	err.subcode1 = err.subcode2 = 0;
	if ( flags & VSF_FLAME_S_FORMAT ) {
		if ( fw.sw_sts.format )
			d_f_ree(fw.sw_sts.format);
		fw.sw_sts.format = ll_copy_str(s->format);
		status |= _S_STATUS_SET;
		flags &= ~VSF_FLAME_S_FORMAT;
	}
	if ( flags & VSF_FLAME_S_QUALITY ) {
		if ( fw.sw_sts.quality )
			d_f_ree(fw.sw_sts.quality);
		fw.sw_sts.quality = ll_copy_str(s->quality);
		status |= _S_STATUS_SET;
		flags &= ~VSF_FLAME_S_QUALITY;
	}
	if ( flags & VSF_FLAME_S_PERIPHERAL ) {
		if ( fw.sw_sts.peripheral )
			d_f_ree(fw.sw_sts.peripheral);
		fw.sw_sts.peripheral = ll_copy_str(s->peripheral);
		status |= _S_STATUS_SET;
		flags &= ~VSF_FLAME_S_PERIPHERAL;
	}
	if ( flags & VSF_FLAME_S_PARAMETER ) {
		if ( fw.sw_sts.parameter )
			d_f_ree(fw.sw_sts.parameter);
		fw.sw_sts.parameter = ll_copy_str(s->parameter);
		status |= _S_STATUS_SET;
		flags &= ~VSF_FLAME_S_PARAMETER;
	}
	if ( flags & VSF_FLAME_S_AGENT_URL ) {
		if ( fw.sw_sts.agent_url )
			d_f_ree(fw.sw_sts.agent_url);
		fw.sw_sts.agent_url = ll_copy_str(s->agent_url);
		status |= _S_STATUS_SET;
		flags &= ~VSF_FLAME_S_AGENT_URL;
	}
	if ( flags & VSF_FLAME_S_MODE ) {
		if ( fw.sw_sts.mode != s->mode )
			status |= _S_STATUS_SET|_S_STATUS_FLAME;
		fw.sw_sts.mode = s->mode;
		flags &= ~VSF_FLAME_S_MODE;
	}
	err.subcode1 = flags;

	if ( status & _S_STATUS_SET ) {
		call_wf_set_flame_switch(&fw.sw,
			fw.sw_sts.mode,
			fw.sw_sts.agent_url,
			fw.sw_sts.parameter,
			fw.sw_sts.peripheral,
			fw.sw_sts.format,
			fw.sw_sts.quality);
		lock_task(interface_redraw_lock);
		wakeup_task((int)&fw.redraw_flag);
		unlock_task(interface_redraw_lock,"set");
	}
	if ( status & _S_STATUS_FLAME ) {
	VObjectStatus sss;
		VMacro::get_status(&sss,VSF_SIZE);
		gs.flags = SF_WIDTH|SF_HEIGHT|SF_DEFAULT_WS|SF_EVENT;
		gs.width = sss.size.w;
		gs.height = sss.size.h;
		gs.default_ws = fw.sts.default_ws;
		gs.event = interface_event_func;
		gs.event_user_arg = (void*)&fw;
		seq = call_wf_set_status(&fw.sw,&gs);
		countup_seq(&fw,seq);
	}
	VM_OP_END
	return err;
}

VExError
VgbFlameStandard::get_switch_status(VgbFlameSwitchStatus * s,int flags) const
{
VExError err;
	VM_OP_START_EX
	err.code = V_ER_NO_ERR;
	err.subcode1 = 0;
	err.subcode2 = 0;
	if ( flags & VSF_FLAME_S_FORMAT ) {
		s->format = ll_copy_str(fw.sw_sts.format);
		flags &= ~VSF_FLAME_S_FORMAT;
	}
	if ( flags & VSF_FLAME_S_QUALITY ) {
		s->quality = ll_copy_str(fw.sw_sts.quality);
		flags &= ~VSF_FLAME_S_QUALITY;
	}
	if ( flags & VSF_FLAME_S_PERIPHERAL ) {
		s->peripheral = ll_copy_str(fw.sw_sts.peripheral);
		flags &= ~VSF_FLAME_S_PERIPHERAL;
	}
	if ( flags & VSF_FLAME_S_PARAMETER ) {
		s->parameter = ll_copy_str(fw.sw_sts.parameter);
		flags &= ~VSF_FLAME_S_PARAMETER;
	}
	if ( flags & VSF_FLAME_S_AGENT_URL ) {
		s->agent_url = ll_copy_str(fw.sw_sts.agent_url);
		flags &= ~VSF_FLAME_S_AGENT_URL;
	}
	if ( flags & VSF_FLAME_S_MODE ) {
		s->mode = fw.sw_sts.mode;
		flags &= ~VSF_FLAME_S_MODE;
	}
	err.subcode1 = flags;
	VM_OP_END
	return err;
}

typedef struct setup_button_arg {
	FLAME_WORK *		fw;
	VButton *		new_obj;
	VButton *		old_obj;
	V_CALLBACK_D		((*handler));
} SETUP_BUTTON_ARG;


V_CALLBACK_D(setup_button_handler)
{
SETUP_BUTTON_ARG * arg;
VObjectStatus sts;
	arg = (SETUP_BUTTON_ARG*)sys_arg;
	if ( arg->old_obj ) {
		sts.value_event_handler = 0;
		sts.value_eh_arg = 0;
		arg->old_obj->set_status(&sts,VSF_VALUE_EH);
	}
	if ( arg->new_obj ) {
		sts.value_event_handler = arg->handler;
		sts.value_eh_arg = (void*)arg->fw;
		arg->new_obj->set_status(&sts,VSF_VALUE_EH);
	}
}

void setup_button(VObject * me,
	FLAME_WORK * fw,
	VButton * old_obj,
	VButton * new_obj,
	V_CALLBACK_D((*func)))
{
SETUP_BUTTON_ARG arg;
VQueEventHandler q;
	if ( new_obj == 0 )
		return;
	arg.fw = fw;
	arg.old_obj = old_obj;
	arg.new_obj = new_obj;
	arg.handler = func;

	vq_insert_callback(me, setup_button_handler, &q, &arg, sizeof(arg));
}

int
radio_button_setup_ins(VRadioButton ** ary,int len,VRadioButton * b)
{
	if ( b == 0 )
		return len;
	ary[len++] = b;
	return len;
}

void
radio_button_setup(FLAME_WORK * fw)
{
VRadioButton * b[4];
int len,i;
	len = radio_button_setup_ins(b,0,
		fw->sts.grab_mode_button);
	len = radio_button_setup_ins(b,len,
		fw->sts.rotate_mode_button);
	len = radio_button_setup_ins(b,len,
		fw->sts.click_mode_button);
	for ( i = 1 ; i < len ; i ++ )
		b[i]->set_radio_group(b[i-1]);
}


V_CALLBACK_D(buttons_control_handler)
{
VM_ARG * a;
FLAME_WORK*fw;
	a = (VM_ARG*)sys_arg;
	fw = (FLAME_WORK*)user_arg;
	switch ( a->id ) {
	case VM_MODE:
		get_marshaler_mode(fw,fw->sts.buttons_control);
		break;
	case VM_ZOOM_IN:
		zoom_in(0,(void*)fw,0);
		break;
	case VM_ZOOM_OUT:
		zoom_out(0,(void*)fw,0);
		break;
	default:
		er_panic("buttons_control_handler");
	}
}

void
setup_buttons_control(VgbFlameStandard * obj,FLAME_WORK * fw)
{
VMarshaler * m;
	m = fw->sts.buttons_control;
	m->set_event_handler(VM_MODE,obj,buttons_control_handler,fw);	// mode
	m->set_event_handler(VM_ZOOM_IN,obj,buttons_control_handler,fw);	// Click ZoomIn
	m->set_event_handler(VM_ZOOM_OUT,obj,buttons_control_handler,fw);	// Click ZoomOut
	get_marshaler_mode(fw,m);
}

VExError
VgbFlameStandard::set_flame_status(
	const VgbFlameStatus * s,
	int flags)
{
VExError err;
int status;
#define _S_GB_SELECT_MODE	0x00000001
GBVIEW_STATUS gs;
int seq;
	VM_OP_START_EX
	err.code = V_ER_NO_ERR;
	err.subcode1 = 0;
	err.subcode2 = 0;
	status = 0;
	gs.flags = 0;
	if ( flags & VSF_FLAME_STYLE ) {
		if ( s->style <= 0 || s->style >= VGB_STYLE_MAX ) {
			err.code = V_ER_PARAM;
			err.subcode2 = VSF_FLAME_STYLE;
			goto ret_err;
		}
		fw.sts.style = s->style;
		flags &= ~VSF_FLAME_STYLE;
	}
	if ( flags & VSF_FLAME_DEFAULT_WS ) {
		if ( fw.sts.default_ws != s->default_ws ) {
			gs.flags |= SF_DEFAULT_WS;
			gs.default_ws = s->default_ws;
		}
		fw.sts.default_ws = s->default_ws;
		flags &= ~VSF_FLAME_DEFAULT_WS;
	}
	if ( flags & VSF_FLAME_ZOOM_IN ) {
		if ( (status & _S_GB_SELECT_MODE) == 0 )
			lock_select_mode(&fw);
		setup_button(this,&fw,fw.sts.zoom_in,s->zoom_in,zoom_in);
		fw.sts.zoom_in = s->zoom_in;
		flags &= ~VSF_FLAME_ZOOM_IN;
		status |= _S_GB_SELECT_MODE;
	}
	if ( flags & VSF_FLAME_ZOOM_OUT ) {
		if ( (status & _S_GB_SELECT_MODE) == 0 )
			lock_select_mode(&fw);
		setup_button(this,&fw,fw.sts.zoom_out,s->zoom_out,zoom_out);
		fw.sts.zoom_out = s->zoom_out;
		flags &= ~VSF_FLAME_ZOOM_OUT;
		status |= _S_GB_SELECT_MODE;
	}
	if ( flags & VSF_FLAME_GRAB_MODE_BUTTON ) {
		if ( (status & _S_GB_SELECT_MODE) == 0 )
			lock_select_mode(&fw);
		setup_button(this,&fw,
			fw.sts.grab_mode_button,
			s->grab_mode_button,
			mode_button_handler);
		fw.sts.grab_mode_button = s->grab_mode_button;
		flags &= ~VSF_FLAME_GRAB_MODE_BUTTON;
		status |= _S_GB_SELECT_MODE;
	}
	if ( flags & VSF_FLAME_ROTATE_MODE_BUTTON ) {
		if ( (status & _S_GB_SELECT_MODE) == 0 )
			lock_select_mode(&fw);
		setup_button(this,&fw,
			fw.sts.rotate_mode_button,
			s->rotate_mode_button,
			mode_button_handler);
		fw.sts.rotate_mode_button = s->rotate_mode_button;
		flags &= ~VSF_FLAME_ROTATE_MODE_BUTTON;
		status |= _S_GB_SELECT_MODE;
	}
	if ( flags & VSF_FLAME_CLICK_MODE_BUTTON ) {
		if ( (status & _S_GB_SELECT_MODE) == 0 )
			lock_select_mode(&fw);
		setup_button(this,&fw,
			fw.sts.click_mode_button,
			s->click_mode_button,
			mode_button_handler);
		fw.sts.rotate_mode_button = s->rotate_mode_button;
		flags &= ~VSF_FLAME_CLICK_MODE_BUTTON;
		status |= _S_GB_SELECT_MODE;
	}
	if ( flags & VSF_FLAME_BUTTONS_CONTROL ) {
		fw.sts.buttons_control = s->buttons_control;
		setup_buttons_control(this,&fw);
		flags &= ~VSF_FLAME_BUTTONS_CONTROL;
	}
	if ( flags & VSF_FLAME_INDICATE_OBJ ) {
		fw.sts.indicate_obj = s->indicate_obj;
		flags &= ~VSF_FLAME_INDICATE_OBJ;
// setup indicate mode
		call_wf_radar_set_indicate_event(
			(FLAME_SWITCH*)&fw.sw,
			indicate_from_radar,
			(void*)&fw);
	}
	if ( flags & VSF_FLAME_INDICATE_TREE_OBJ ) {
		fw.sts.indicate_tree_obj = s->indicate_tree_obj;
		flags &= ~VSF_FLAME_INDICATE_TREE_OBJ;
		if ( s->indicate_tree_obj == 0 && fw.tree_view_data ) {
			d_f_ree(fw.tree_view_data);
			fw.tree_view_data = 0;
			fw.tree_view_data_len = 0;
		}
		if ( s->indicate_tree_obj ) {
		VxlTreeViewStatus tv_sts;
			s->indicate_tree_obj
				->get_xltreeview_status
					(&tv_sts,VSF_XL_TREEVIEW_DIR);
			fw.tree_view_data_dir = tv_sts.dir;
			tv_sts.focus_handler = flame_focus_handler;
			tv_sts.focus_handler_arg = this;
			s->indicate_tree_obj
				->set_xltreeview_status
					(&tv_sts,VSF_XL_TREEVIEW_FOCUS);
		}
	}
	if ( flags & VSF_FLAME_INDICATE_TREE_EYE ) {
		fw.tree_view_eye[0] = v_get_image_element(s->indicate_tree_eye,
							s->indicate_tree_eye_elr[0]);
		fw.tree_view_eye[1] = v_get_image_element(s->indicate_tree_eye,
							s->indicate_tree_eye_elr[1]);
	}
	if ( flags & VSF_FLAME_INDICATE_TREE_INFO ) {
		fw.tree_view_info[0] = v_get_image_element(s->indicate_tree_info,
							s->indicate_tree_info_elr[0]);
		fw.tree_view_info[1] = v_get_image_element(s->indicate_tree_info,
							s->indicate_tree_info_elr[1]);
	}
	if ( flags & VSF_FLAME_INDICATE_TREE_BASE ) {
		fw.tree_view_base[0] = v_get_image_element(s->indicate_tree_base,
							s->indicate_tree_base_elr[0]);
		fw.tree_view_base[1] = v_get_image_element(s->indicate_tree_base,
							s->indicate_tree_base_elr[1]);
		fw.tree_view_base[2] = v_get_image_element(s->indicate_tree_base,
							s->indicate_tree_base_elr[2]);
		fw.tree_view_base[3] = v_get_image_element(s->indicate_tree_base,
							s->indicate_tree_base_elr[3]);
		fw.tree_view_base[4] = v_get_image_element(s->indicate_tree_base,
							s->indicate_tree_base_elr[4]);
	}
	if ( flags & VSF_FLAME_OATTRIBUTE_HANDLER ) {
		fw.oattribute_handler = s->oattribute_handler;
		fw.oattribute_handler_arg = s->oattribute_handler_arg;
	}
	if ( flags & VSF_FLAME_SELECT_MODE ) {
		if ( (status & _S_GB_SELECT_MODE) == 0 )
			lock_select_mode(&fw);
		fw.sts.select_mode = s->select_mode;
		flags &= ~VSF_FLAME_SELECT_MODE;
		status |= _S_GB_SELECT_MODE;
	}
	if ( flags & VSF_FLAME_RELATED_FLAME ) {
		fw.sts.related_flame = s->related_flame;
		flags &= ~VSF_FLAME_RELATED_FLAME;
	}
ret_err:
	err.subcode1 = flags;

	if ( status & _S_GB_SELECT_MODE ) {
		radio_button_setup(&fw);
		set_move_mode(&fw,fw.sts.select_mode);
		unlock_select_mode(&fw);
	}
	
	if ( gs.flags ) {
		seq = call_wf_set_status(&fw.sw,&gs);
		countup_seq(&fw,seq);
	}
		
	VM_OP_END
	return err;
}




VExError
VgbFlameStandard::get_flame_status(
	VgbFlameStatus * s,
	int flags) const
{
VExError err;
	VM_OP_START_EX
	err.code = V_ER_NO_ERR;
	err.subcode1 = 0;
	err.subcode2 = 0;
	if ( flags & VSF_FLAME_STYLE ) {
		s->style = fw.sts.style;
		flags &= ~VSF_FLAME_STYLE;
	}
	if ( flags & VSF_FLAME_DEFAULT_WS ) {
		s->default_ws = fw.sts.default_ws;
		flags &= ~VSF_FLAME_DEFAULT_WS;
	}
	if ( flags & VSF_FLAME_ZOOM_IN ) {
		s->zoom_in = fw.sts.zoom_in;
		flags &= ~VSF_FLAME_ZOOM_IN;
	}
	if ( flags & VSF_FLAME_ZOOM_OUT ) {
		s->zoom_out = fw.sts.zoom_out;
		flags &= ~VSF_FLAME_ZOOM_OUT;
	}
	if ( flags & VSF_FLAME_GRAB_MODE_BUTTON ) {
		s->grab_mode_button = fw.sts.grab_mode_button;
		flags &= ~VSF_FLAME_GRAB_MODE_BUTTON;
	}
	if ( flags & VSF_FLAME_ROTATE_MODE_BUTTON ) {
		s->rotate_mode_button = fw.sts.rotate_mode_button;
		flags &= ~VSF_FLAME_ROTATE_MODE_BUTTON;
	}
	if ( flags & VSF_FLAME_CLICK_MODE_BUTTON ) {
		s->rotate_mode_button = fw.sts.rotate_mode_button;
		flags &= ~VSF_FLAME_CLICK_MODE_BUTTON;
	}
	if ( flags & VSF_FLAME_INDICATE_OBJ ) {
		s->indicate_obj = fw.sts.indicate_obj;
		flags &= ~VSF_FLAME_INDICATE_OBJ;
	}
	if ( flags & VSF_FLAME_INDICATE_TREE_OBJ ) {
		s->indicate_tree_obj = fw.sts.indicate_tree_obj;
		flags &= ~VSF_FLAME_INDICATE_TREE_OBJ;
	}
	if ( flags & VSF_FLAME_SELECT_MODE ) {
		s->select_mode = fw.sts.select_mode;
		flags &= ~VSF_FLAME_SELECT_MODE;
	}
	if ( flags & VSF_FLAME_RELATED_FLAME ) {
		s->related_flame = fw.sts.related_flame;
		flags &= ~VSF_FLAME_RELATED_FLAME;
	}
	err.subcode1 = flags;

	VM_OP_END
	return err;
}


VExError VgbFlameStandard::get_radar_status(
	VgbFlameRadarStatus * s,
	int flags) const
{
VExError err;
int ret;
	VM_OP_START_EX
	err.code = V_ER_NO_ERR;
	err.subcode1 = 0;
	err.subcode2 = 0;
	if ( flags & (VSF_FLAME_R_QUERY_GET|
			VSF_FLAME_R_QUERY_SET|
			VSF_FLAME_R_QUERY_INSERT) ) {
		s->result_query = call_wf_radar_get_query(&fw.sw);
		flags &= ~
			(VSF_FLAME_R_QUERY_GET|
			VSF_FLAME_R_QUERY_SET|
			VSF_FLAME_R_QUERY_INSERT);
	}
	if ( flags & (VSF_FLAME_R_LOADING_STATUS) ) {
		ret = call_wf_loading_status(&fw.sw,&s->loading_status);
		flags &= ~VSF_FLAME_R_LOADING_STATUS;
		if ( ret < 0 ) {
			err.code = V_ER_CANT_GET;
			err.subcode2 = ret;
			goto end;
		}
	}
end:
	err.subcode1 = flags;

	VM_OP_END
	return err;
}

VExError VgbFlameStandard::set_radar_status(
	VgbFlameRadarStatus * s,
	int flags)
{
VExError err;
	VM_OP_START_EX
	err.code = V_ER_NO_ERR;
	err.subcode1 = 0;
	err.subcode2 = 0;
	if ( flags & VSF_FLAME_R_QUERY_DELETE_BYNO ) {
		s->result = call_wf_radar_delete_query(
				&fw.sw,
				s->delete_byno);
		flags &= ~VSF_FLAME_R_QUERY_DELETE_BYNO;
	}
	if ( flags & VSF_FLAME_R_QUERY_SET ) {
		s->result = call_wf_radar_set_query(
					&fw.sw,
					s->query_set);
		flags &= ~VSF_FLAME_R_QUERY_SET;
	}
	if ( flags & VSF_FLAME_R_QUERY_REPLACE ) {
		s->result = call_wf_radar_replace_query(
					&fw.sw,
					s->query_replace);
		flags &= ~VSF_FLAME_R_QUERY_REPLACE;
	}
	if ( flags & VSF_FLAME_R_QUERY_INSERT ) {
		s->result = call_wf_radar_insert_query(
					&fw.sw,
					s->query_insert);
		flags &= ~VSF_FLAME_R_QUERY_INSERT;
	}
	if ( flags & VSF_FLAME_R_EVENT_HANDLER ) {
		call_wf_radar_set_condition_event(
				&fw.sw,
				s->event_handler,
				s->eh_user_arg);
		flags &= ~VSF_FLAME_R_EVENT_HANDLER;
	}
	err.subcode1 = flags;

	VM_OP_END
	return err;
}


VgbFlameLayers *
copy_out_layers(GBVIEW_LAYER_STATUS * layer)
{
GBVIEW_LAYER_STATUS * l;
VgbFlameLayers * ret,* p, ** pp;
	ret = 0;
	pp = &ret;
	for ( l = layer ; l ; l = l->next ) {
		p = (VgbFlameLayers*)d_alloc(sizeof(*p));
		p->next = 0;
		p->id = l->id;
		p->entry_url = ll_copy_str(l->entry_url);
		p->target_url = ll_copy_str(l->target_url);
		p->flags = l->flags;
		*pp = p;
		pp = &p->next;
	}
	return ret;
}

VExError 
VgbFlameStandard::get_coordinate_status(
	VgbFlameCoordinateStatus * ret,
	int flags) const
{
VExError err;
GBVIEW_STATUS wf_sts;
	err.code = V_ER_NO_ERR;
	err.subcode1 = 0;
	err.subcode2 = 0;
	if ( flags == 0 )
		goto end;
	VM_OP_START_EX
	call_wf_status((struct flame_switch*)&fw.sw,&wf_sts,1);
	VM_OP_END

	if ( flags &  VSF_FLAME_C_STATUS ) {
		ret->status = wf_sts.status;
		flags &= ~VSF_FLAME_C_STATUS;
	}
	if ( flags &  VSF_FLAME_C_LAYER_NOS ) {
		ret->layer_nos = wf_sts.layer_nos;
		flags &= ~VSF_FLAME_C_STATUS;
	}
	if ( flags &  VSF_FLAME_C_FLAME_BASE_CENTER ) {
		ret->flame_base_center = wf_sts.flame_base_center;
		flags &= ~VSF_FLAME_C_FLAME_BASE_CENTER;
	}
	if ( flags &  VSF_FLAME_C_FLAME_BASE_ROTATE ) {
		ret->flame_base_rotate = wf_sts.flame_base_rotate;
		flags &= ~VSF_FLAME_C_FLAME_BASE_ROTATE;
	}
	if ( flags &  VSF_FLAME_C_FLAME_BASE_RESOLUTION  ) {
		ret->flame_base_resolution = wf_sts.flame_base_resolution;
		flags &= ~VSF_FLAME_C_FLAME_BASE_RESOLUTION;
	}
	if ( flags &  VSF_FLAME_C_FLAME_BASE_UNIT ) {
		ret->flame_base_unit = wf_sts.flame_base_unit;
		wf_sts.flame_base_unit = 0;
		flags &= ~VSF_FLAME_C_FLAME_BASE_UNIT;
	}
	if ( flags &  VSF_FLAME_C_FLAME_BASE_DISPLAY_MAP_TYPE ) {
		ret->flame_base_display_map_type
				= wf_sts.flame_base_display_map_type;
		flags &= ~VSF_FLAME_C_FLAME_BASE_DISPLAY_MAP_TYPE;
	}
	if ( flags &  VSF_FLAME_C_CURRENT ) {
		ret->current = wf_sts.current;
		flags &= ~VSF_FLAME_C_CURRENT;
	}
	if ( flags &  VSF_FLAME_C_LAYERS ) {
		ret->layers = copy_out_layers(wf_sts.layers);
		flags &= ~VSF_FLAME_C_LAYERS;
	}
	if ( flags &  VSF_FLAME_C_PP_RADIUS ) {
		if ( wf_sts.flags & SF_PP_RADIUS ) {
			ret->pp_radius = wf_sts.pp_radius;
			flags &= ~VSF_FLAME_C_PP_RADIUS;
		}
	}
	wf_free_status(&wf_sts);
	err.subcode1 = flags;
end:
	return err;
}


VExError
VgbFlameStandard::set_coordinate_status(
	const VgbFlameCoordinateStatus * c_sts,
	int flags)
{
VExError err;
int c;
int er;
REAL1 rot;

	err.code = V_ER_NO_ERR;
	err.subcode1 = 0;
	err.subcode2 = 0;
	if ( flags == 0 )
		return err;

	VM_OP_START_EX

	if ( flags & VSF_FLAME_C_FLAME_BASE_ROTATE )
		rot = c_sts->flame_base_rotate;
	else	rot = 0;
	c = VSF_FLAME_C_FLAME_BASE_RECT|
		VSF_FLAME_C_TARGET;
	if ( (flags & c) == c ) {
		er = call_wf_radar_warp(&fw.sw,
			WT_RECT,
			(GB_RECT*)&c_sts->flame_base_rect,
			0,
			0,
			rot,
			(L_CHAR*)c_sts->target);
		if ( er )
			err.subcode2 = c;
		goto call_end;
	}
	c = VSF_FLAME_C_FLAME_BASE_CENTER|
		VSF_FLAME_C_FLAME_BASE_RESOLUTION|
		VSF_FLAME_C_TARGET;
	if ( (flags & c) == c ) {
		er = call_wf_radar_warp(&fw.sw,
			WT_CENTER,
			0,
			(GB_POINT*)&c_sts->flame_base_center,
			(REAL1)c_sts->flame_base_resolution,
			rot,
			(L_CHAR*)c_sts->target);
		if ( er )
			err.subcode2 = c;
		goto call_end;
	}
	c = VSF_FLAME_C_TARGET;
	if ( (flags & c) == c ) {
		er = call_wf_radar_warp(&fw.sw,
			WT_TARGET,
			0,
			0,
			0,
			rot,
			(L_CHAR*)c_sts->target);
		if ( er )
			err.subcode2 = c;
		goto call_end;
	}
	err.code = V_ER_FLAGS_CONBINATION;
	err.subcode1 = flags;
	goto end;
call_end:
	if ( er ) {
		err.code = V_ER_CANT_SET;
		err.subcode1 = er;
	}
end:
	VM_OP_END

	return err;
}


void
free_VgbFlameLayers(VgbFlameLayers * l)
{
VgbFlameLayers * l2;
	for ( ; l ; ) {
		l2 = l->next;
		d_f_ree(l->entry_url);
		d_f_ree(l->target_url);
		d_f_ree(l);
		l = l2;
	}
}

void 
free_VgbFlameCoordinateStatus(struct _VgbFlameCoordinateStatus * sts,int flags)
{
	if ( flags & VSF_FLAME_C_FLAME_BASE_UNIT )
		d_f_ree(sts->flame_base_unit);
	if ( flags & VSF_FLAME_C_LAYERS )
		free_VgbFlameLayers(sts->layers);
	if ( flags & VSF_FLAME_C_TARGET )
		d_f_ree(sts->target);
}


