/**********************************************************************
 
	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	"http.h"
#include	"gbview.h"
#include	"xlerror.h"
#include	"memory_debug.h"
#include	"machine/param_gbview.h"
#include	"xl.h"
#include	"lock_level.h"
#include	"pri_level.h"
#include	"cosmos.h"
#include	"viewindex.h"

#define OPAC_STOP_TIMEOUT	1

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

int motion_cnt;

VDISPLAY * env_display;


SEM interface_lock,opac_lock,interface_redraw_lock;

extern int test_lock;
XL_SEXP * xl_gv_interface_status();
XL_SEXP * xl_gv_change_mode();
XL_SEXP * xl_gv_event_default();
void change_interface_mode(int mode);
XLISP_ENV * interface_env;
void interface_event_task();
int interface_event_flag;

COSMOS_FLAME	cflame;

#define MODE_CHAR_COLOR		COL(0x3ff,0x3ff,0x200)
#define MODE_SELECT_BG_COLOR	COL(0x200,0,0)
#define MODE_NOT_SEL_BG_COLOR	COL(0x180,0,0)
#define MODE_NOT_SEL_CHAR_COLOR	COL(0x380,0x380,0x380)

#define UNUSE_CHAR_COLOR	COL(0x200,0x200,0x200)
#define USE_CHAR_COLOR		COL(0x3ff,0x3ff,0x3ff)
#define UNUSE_BG_COLOR		COL(0x180,0,0)
#define USE_BG_COLOR		COL(0x200,0,0)

int grab_mode();
int rotate_mode();

char mode_text[MODE_NOS][16] = {
	"GRAB",
	"ROTATE"
};
char mode_btn_text[MODE_NOS][16] = {
	"GRAB    ",
	"ROTATE  "
};
int (*mode_func[MODE_NOS])() = {
	grab_mode,
	rotate_mode
};

int ptr_param_func();
int ptr_cmp();
int real_param_func();
int real_cmp();

int grab_flame_func();
int grab_index_func();

int rotate_flame_func();
int rotate_index_func();

int zoom_flame_func();
int zoom_index_func();

MOVE_SET ms_grab = {
	ptr_param_func,
	grab_flame_func,
	grab_index_func,
	ptr_cmp
};
MOVE_SET ms_rotate = {
	ptr_param_func,
	rotate_flame_func,
	rotate_index_func,
	ptr_cmp
};
MOVE_SET ms_zoom = {
	real_param_func,
	zoom_flame_func,
	zoom_index_func,
	real_cmp
};

int td_break;

void
tate_ditect(char * msg,unsigned long * buf,int st,int pitch,int lines)
{
static ditect;
unsigned long * ptr;
unsigned long col;
	ptr = &buf[st];
	col = (*ptr)&C_COLOR;
	for ( ; lines ; lines -- , ptr += pitch )
		if ( ((*ptr)&C_COLOR) != (col&C_COLOR) )
			return;
	printf("****************************** TATE DITECT %i (%i) %s\n",ditect++,get_tid(),msg);
/*
	if ( td_break )
		er_panic("TATE");
*/
}

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

void
init_interface()
{
XLISP_ENV * e;
GBVIEW_STATUS sts;
void interface_event_func();

	new_tick(tick_xli,0,0);

	e = new_env(gblisp_top_env0);
	set_env(e,l_string(std_cm,"gv-status"),
		get_func_prim(xl_gv_interface_status,FO_APPLICATIVE,0,1,1));
	set_env(e,l_string(std_cm,"gv-change-mode"),
		get_func_prim(xl_gv_change_mode,FO_APPLICATIVE,0,2,2));
	set_env(e,l_string(std_cm,"gv-event"),
		get_func_prim(xl_gv_event_default,FO_APPLICATIVE,0,3,3));

	set_gv_sp_resource(RID_INTERFACE,e);
	interface_env = e;

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

	sts.flags = SF_EVENT;
	sts.event = interface_event_func;
	call_wf_set_status(&sts);

	create_task(interface_event_task,0,PRI_HTMLDB);
}



int
ptr_param_func(VPOINT ** ptr)
{
VPOINT * ret;
	ret = d_alloc(sizeof(*ret));
	ret->x = cflame.press_x;
	ret->y = cflame.press_y;
	*ptr = ret;
	return 0;
}

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

int
real_param_func(REAL1 ** ptr)
{
REAL1 * ret;

	ret = d_alloc(sizeof(REAL1));
	*ret = cflame.press_zoom;
	*ptr = ret;
	return 0;
}

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


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

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

void
countup_seq(int seq)
{
	checkin_seq(seq);
	checkout_seq(seq);
}

void
interface_event_task()
{
XL_INTERPRETER * xli;
XL_SEXP * ret;
	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);
	for ( ; ; ) {
		lock_task(interface_lock);
		if ( interface_event_flag == 0 ) {
			sleep_task((int)&interface_event_flag,
				interface_lock);
			lock_task(interface_lock);
			interface_event_flag = 0;
			unlock_task(interface_lock,"interface");
		}
		else {
			interface_event_flag = 0;
			unlock_task(interface_lock,"interface");
		}
		call_gv_event(RID_INTERFACE,l_string(std_cm,"select-event"));
	}
}

XL_SEXP *
xl_gv_event_default()
{
	return 0;
}

XL_SEXP *
xl_gv_change_mode(
	XLISP_ENV * e,
	XL_SEXP * s)
{
XL_SEXP * mode;
int i;
	mode = get_el(s,1);
	if ( get_type(mode) != XLT_STRING )
		goto type_missmatch;
	for ( i = 0 ; i < MODE_NOS ; i ++ ) {
		if ( l_strcmp(mode->string.data,
			l_string(std_cm,mode_text[i])) == 0 ) {
			change_interface_mode(i);
			return 0;
		}
	}
	goto param_error;
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"gv-change-mode"),
		List(n_get_string("type missmatch"),
			-1));
param_error:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"gv-change-mode"),
		List(n_get_string("invalid mode"),
			-1));
}

XL_SEXP *
xl_gv_interface_status(
	XLISP_ENV * e,
	XL_SEXP * s)
{
char * select;
L_CHAR * entry;
int rid;
GB_POINT plist[4];
XL_SEXP * point_list[4];
int i;
GBVIEW_STATUS sts;
	if ( cflame.select_flag )
		select = "valid";
	else	select = "invalid";

	call_wf_status(&sts,CALL_STS_CACHE_NORMAL);

	lock_task(interface_lock);
	if ( sts.layer_nos ) {
		if ( cflame.select_st.x < cflame.select_end.x &&
				cflame.select_st.y < cflame.select_end.y ) {
			plist[0].x = cflame.select_st.x;
			plist[0].y = cflame.select_st.y;
			plist[1].x = cflame.select_st.x;
			plist[1].y = cflame.select_end.y;
			plist[2].x = cflame.select_end.x;
			plist[2].y = cflame.select_end.y;
			plist[3].x = cflame.select_end.x;
			plist[3].y = cflame.select_st.y;
		}
		else if ( cflame.select_st.x < cflame.select_end.x &&
				cflame.select_st.y >= cflame.select_end.y ) {
			plist[0].x = cflame.select_st.x;
			plist[0].y = cflame.select_end.y;
			plist[1].x = cflame.select_st.x;
			plist[1].y = cflame.select_st.y;
			plist[2].x = cflame.select_end.x;
			plist[2].y = cflame.select_st.y;
			plist[3].x = cflame.select_end.x;
			plist[3].y = cflame.select_end.y;
		}
		else if ( cflame.select_st.x >= cflame.select_end.x &&
				cflame.select_st.y < cflame.select_end.y ) {
			plist[0].x = cflame.select_end.x;
			plist[0].y = cflame.select_st.y;
			plist[1].x = cflame.select_end.x;
			plist[1].y = cflame.select_end.y;
			plist[2].x = cflame.select_st.x;
			plist[2].y = cflame.select_end.y;
			plist[3].x = cflame.select_st.x;
			plist[3].y = cflame.select_st.y;
		}
		else {
			plist[0].x = cflame.select_end.x;
			plist[0].y = cflame.select_end.y;
			plist[1].x = cflame.select_end.x;
			plist[1].y = cflame.select_st.y;
			plist[2].x = cflame.select_st.x;
			plist[2].y = cflame.select_st.y;
			plist[3].x = cflame.select_st.x;
			plist[3].y = cflame.select_end.y;
		}
		call_wf_get_coordinate_info(&entry,&rid,plist,4);
		for ( i = 0 ; i < 4 ; i ++ ) {
			point_list[i] = 
				List(get_floating(plist[i].x,
						l_string(std_cm,"m")),
					get_floating(plist[i].y,
						l_string(std_cm,"m")),
					-1);
		}
		goto coordinate_valid;
	}
	else	goto coordinate_invalid;
coordinate_valid:
	unlock_task(interface_lock,"interface-status");
	wf_free_status(&sts);
	return List(	n_get_symbol("interface"),
			List(	n_get_symbol("mode"),
				n_get_string(mode_text[cflame.select_mode]),
				-1),
			List(	n_get_symbol("SELECT"),
				n_get_string(select),
				List(n_get_symbol("ondisplay"),
					List(
					 List(get_integer(
						cflame.select_st.x,0),
					      get_integer(
						cflame.select_st.y,0),
						-1),
					 List(get_integer(
						cflame.select_end.x,0),
					      get_integer(
						cflame.select_end.y,0),
						-1),
					-1),
				    -1),
				List(n_get_symbol("coordinate"),
					get_string(entry),
					get_integer(rid,0),
					point_list[0],
					point_list[1],
					point_list[2],
					point_list[3],
					-1),
				-1),
			-1);
coordinate_invalid:
	unlock_task(interface_lock,"interface-status");
	wf_free_status(&sts);
	return List(	n_get_symbol("interface"),
			List(	n_get_symbol("mode"),
				n_get_string(mode_text[cflame.select_mode]),
				-1),
			List(	n_get_symbol("SELECT"),
				n_get_string(select),
				List(n_get_symbol("ondisplay"),
					List(
					 List(get_integer(
						cflame.select_st.x,0),
					      get_integer(
						cflame.select_st.y,0),
						-1),
					 List(get_integer(
						cflame.select_end.x,0),
					      get_integer(
						cflame.select_end.y,0),
						-1),
					-1),
				    -1),
				-1),
			-1);
}

int
rotate_mode(int edge)
{
VPOINT st,end;
	switch ( edge ) {
	case 0:
		break;
	case 1:
		break;
	}
	return 0;
}

int
grab_mode(int edge)
{
VERROR err;


	switch ( edge ) {
	case 0:
		v_set_text(&err,
			cflame.zoom_in,
			USE_CHAR_COLOR,
			USE_BG_COLOR,
			0,0);
		v_set_text(&err,
			cflame.zoom_out,
			USE_CHAR_COLOR,
			USE_BG_COLOR,
			0,0);
		break;
	case 1:
		v_set_text(&err,
			cflame.zoom_in,
			UNUSE_CHAR_COLOR,
			UNUSE_BG_COLOR,
			0,0);
		v_set_text(&err,
			cflame.zoom_out,
			UNUSE_CHAR_COLOR,
			UNUSE_BG_COLOR,
			0,0);
		break;
	}
	return 0;
}


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

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


int
grab_flame_func()
{
int seq;
VPOINT * from,* to;
	if ( cflame.start_shot == 0 || cflame.last_shot == 0 )
		return 0;
	from = cflame.start_shot;
	to = cflame.last_shot;
	return call_wf_move(*from,*to);
}

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

	index = cflame.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 = cflame.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(GBVIEW_STATUS * sts)
{
GB_POINT from,to;
int i,w,h;
int * index;
int ofs,tar;
int ret;
	if ( cflame.start_shot == 0 || cflame.last_shot == 0 )
		return 0;
	w = cflame.im->vimage.w;
	h = cflame.im->vimage.h;
	_set_index(PIT_PLANE,w,h);
/*
	if ( cflame.ix.type == 0 ) {
		cflame.ix.p.index =
			d_alloc(sizeof(VPOINT)*w*h);
		cflame.ix.type = PIT_PLANE;
	}
	else if ( cflame.ix.type != PIT_XY )
		er_panic("grab_index_func");
*/
	from = v2gb_point(*(VPOINT*)cflame.start_shot);
	to = v2gb_point(*(VPOINT*)cflame.last_shot);

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

int
grab_index_func()
{
GBVIEW_STATUS sts;
	call_wf_status(&sts,CALL_STS_CACHE_NORMAL);
	if ( sts.flame_base_display_map_type == MHT_PP )
		return grab_index_func_globe(&sts);
	else	return grab_index_func_2d();
}

int
rotate_flame_func()
{
int seq;
VPOINT * from,* to;
GB_POINT _from,_to;
	if ( cflame.start_shot == 0 || cflame.last_shot == 0 )
		return 0;
	from = cflame.start_shot;
	to = cflame.last_shot;
	_from.x = from->x;
	_from.y = from->y;
	_to.x = to->x;
	_to.y = to->y;
	return call_wf_rotate(_from,_to);
}

int
rotate_index_func()
{
VPOINT * from,* to;
int i,w,h;
int * index;
int ofs,tar;
GB_POINT _from,_to;
	if ( cflame.start_shot == 0 || cflame.last_shot == 0 )
		return 0;
	w = cflame.im->vimage.w;
	h = cflame.im->vimage.h;
	_set_index(PIT_PLANE,w,h);
/*
	if ( cflame.ix.type == 0 ) {
		cflame.ix.p.index =
			d_alloc(sizeof(VPOINT)*w*h);
		cflame.ix.type = PIT_PLANE;
	}
	else if ( cflame.ix.type != PIT_PLANE )
		er_panic("grab_index_func");
*/
	from = cflame.start_shot;
	to = cflame.last_shot;

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

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

int
zoom_flame_func()
{
REAL1 * from,* to;
	if ( cflame.start_shot == 0 || cflame.last_shot == 0 )
		return 0;
	from = cflame.start_shot;
	to = cflame.last_shot;
	return call_wf_zoom(0,(*to)/(*from));
}

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

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

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

int
get_bg_32(V_MAP_TBL * tbl,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,tbl,buf[i]);
		acc_bg_32(col,tbl,buf[i + (h-1)*w]);
	}
	for ( i = 0 ; i < h ; i ++ ) {
		acc_bg_32(col,tbl,buf[i*w]);
		acc_bg_32(col,tbl,buf[i*w + (w-1)]);
	}
	return make_bg(tbl,col,2*(w+h));
}

void
acc_bg_16(int col[3],V_MAP_TBL *tbl,short a)
{
int c[3];
int i;
	MCOLOR2GB(c[0],c[1],c[2],*tbl,a);
	for ( i = 0 ; i < 3 ; i ++ )
		col[i] += c[i];
}

int
get_bg_16(V_MAP_TBL * tbl,short * 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_16(col,tbl,buf[i]);
		acc_bg_16(col,tbl,buf[i + (h-1)*w]);
	}
	for ( i = 0 ; i < h ; i ++ ) {
		acc_bg_16(col,tbl,buf[i*w]);
		acc_bg_16(col,tbl,buf[i*w + (w-1)]);
	}
	return make_bg(tbl,col,2*(w+h));
}


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


int
get_bg_8(V_MAP_TBL * tbl,char * 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_8(col,tbl,buf[i]);
		acc_bg_8(col,tbl,buf[i + (h-1)*w]);
	}
	for ( i = 0 ; i < h ; i ++ ) {
		acc_bg_8(col,tbl,buf[i*w]);
		acc_bg_8(col,tbl,buf[i*w + (w-1)]);
	}
	return make_bg(tbl,col,2*(w+h));
}

void
convert_image_32_plane()
{
long * from,* to, * _to;
VPOINT * index;
int x,y,w,h,wb;
int xx,yy;
long bg;
V_MAP_TBL tbl;

	tbl = cflame.window->d->gb2m_map;

	from = cflame.ss.buf_32;
	_to = cflame.im->vimage.buf_32;
	index = cflame.ix.p.index;
	w = cflame.im->vimage.w;
	h = cflame.im->vimage.h;

	bg = get_bg_32(&tbl,from,w,h);

	wb = cflame.im->vimage.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 + xx];
			else	*to = bg;
			index ++;
			to ++;
		}
	}
}

void
convert_image_16_plane()
{
short * from,* to,* _to;
VPOINT * index;
int x,y,w,h,wb;
int xx,yy;
short bg;
V_MAP_TBL tbl;

	tbl = cflame.window->d->gb2m_map;

	from = cflame.ss.buf_16;
	_to = cflame.im->vimage.buf_16;
	index = cflame.ix.p.index;
	w = cflame.im->vimage.w;
	h = cflame.im->vimage.h;

	bg = get_bg_16(&tbl,from,w,h);

	wb = cflame.im->vimage.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 + xx];
			else	*to = bg;
			index ++;
			to ++;
		}
	}
}
void
convert_image_8_plane()
{
char * from,* to,* _to;
VPOINT * index;
int x,y,w,h,wb;
int xx,yy;
char bg;
V_MAP_TBL tbl;

	tbl = cflame.window->d->gb2m_map;

	from = cflame.ss.buf_8;
	_to = cflame.im->vimage.buf_8;
	index = cflame.ix.p.index;
	w = cflame.im->vimage.w;
	h = cflame.im->vimage.h;

	bg = get_bg_8(&tbl,from,w,h);

	wb = cflame.im->vimage.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 + xx];
			else	*to = bg;
			index ++;
			to ++;
		}
	}
}

void
convert_image_8_line()
{
char * from,* to, * _to;
int * index_x, * index_y;
int x,y,w,h,wb;
int xx,yy;
char bg;
V_MAP_TBL tbl;

	tbl = cflame.window->d->gb2m_map;

	from = cflame.ss.buf_8;
	_to = cflame.im->vimage.buf_8;
	index_x = cflame.ix.xy.index_x;
	index_y = cflame.ix.xy.index_y;
	w = cflame.im->vimage.w;
	h = cflame.im->vimage.h;

	bg = get_bg_8(&tbl,from,w,h);

	wb = cflame.im->vimage.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 + xx];
			else	*to = bg;
			to ++;
		}
	}
}

void
convert_image_32_line()
{
long * from,* to, * _to;
int * index_x, * index_y;
int x,y,w,h,wb;
int xx,yy;
long bg;
V_MAP_TBL tbl;

	tbl = cflame.window->d->gb2m_map;

	from = cflame.ss.buf_32;
	_to = cflame.im->vimage.buf_32;
	index_x = cflame.ix.xy.index_x;
	index_y = cflame.ix.xy.index_y;
	w = cflame.im->vimage.w;
	h = cflame.im->vimage.h;

	bg = get_bg_32(&tbl,from,w,h);

	wb = cflame.im->vimage.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 + xx];
			else	*to = bg;
			to ++;
		}
	}
}

void
convert_image_16_line()
{
short * from,* to, * _to;
int * index_x, * index_y;
int x,y,w,h,wb;
int xx,yy;
short bg;
V_MAP_TBL tbl;

	tbl = cflame.window->d->gb2m_map;

	from = cflame.ss.buf_16;
	_to = cflame.im->vimage.buf_16;
	index_x = cflame.ix.xy.index_x;
	index_y = cflame.ix.xy.index_y;
	w = cflame.im->vimage.w;
	h = cflame.im->vimage.h;

	bg = get_bg_16(&tbl,from,w,h);

	wb = cflame.im->vimage.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 + xx];
			else	*to = bg;
			to ++;
		}
	}
}

void
convert_image_32()
{
	switch ( cflame.ix.type ) {
	case PIT_PLANE:
		convert_image_32_plane();
		break;
	case PIT_XY:
		convert_image_32_line();
		break;
	default:
		er_panic("_conveert_image_32");
	}
}

void
convert_image_16()
{
	switch ( cflame.ix.type ) {
	case PIT_PLANE:
		convert_image_16_plane();
		break;
	case PIT_XY:
		convert_image_16_line();
		break;
	default:
		er_panic("_conveert_image_16");
	}
}

void
convert_image_8()
{
	switch ( cflame.ix.type ) {
	case PIT_PLANE:
		convert_image_8_plane();
		break;
	case PIT_XY:
		convert_image_8_line();
		break;
	default:
		er_panic("_conveert_image_8");
	}
}

void
convert_image()
{
	if ( cflame.ss.buf_8 )
		convert_image_8();
	else if ( cflame.ss.buf_16 )
		convert_image_16();
	else if ( cflame.ss.buf_32 )
		convert_image_32();
	else	er_panic("convert_image");
}

int
_snapshot_check()
{
	if ( cflame.ss.buf_32 )
		return 32;
	if ( cflame.ss.buf_16 )
		return 16;
	if ( cflame.ss.buf_8 )
		return 8;
	return 0;
}

int
snapshot_check()
{
int ret;
	lock_task(opac_lock);
	ret = _snapshot_check();
	unlock_task(opac_lock,"snapshot_check");
	return ret;
}

void
_opac_move()
{
void * move_param,* last_shot;
void * ptr;
int esize;

	if ( cflame.ms == 0 )
		return;

	(*cflame.ms->param_func)(&move_param);

	if ( cflame.start_shot == 0 ) {
		cflame.start_shot = move_param;
		return;
	}

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

	switch ( _snapshot_check() ) {
	case 32:
		checkin_seq(-1);

		if ( (*cflame.ms->index_func)() == 0 ) {
			convert_image_32();
			if ( last_shot )
				d_f_ree(last_shot);
		}
		else {
			if ( cflame.last_shot )
				d_f_ree(cflame.last_shot);
			cflame.last_shot = last_shot;
		}

		checkout_seq(-1);
		break;
	case 16:
		checkin_seq(-1);

		if ( (*cflame.ms->index_func)() == 0 ) {
			convert_image_16();
			if ( last_shot )
				d_f_ree(last_shot);
		}
		else {
			if ( cflame.last_shot )
				d_f_ree(cflame.last_shot);
			cflame.last_shot = last_shot;
		}

		checkout_seq(-1);
		break;
	case 8:
		checkin_seq(-1);

		if ( (*cflame.ms->index_func)() == 0 ) {
			convert_image_8();
			if ( last_shot )
				d_f_ree(last_shot);
		}
		else {
			if ( cflame.last_shot )
				d_f_ree(cflame.last_shot);
			cflame.last_shot = last_shot;
		}

		checkout_seq(-1);
		break;
	case 0:
		checkin_seq(-1);

		if ( (*cflame.ms->index_func)() == 0 ) {

			if ( last_shot )
				d_f_ree(last_shot);

			lock_task(interface_lock);

			ptr = v_get_and_new_image(&esize,cflame.im);
			switch ( esize ) {
			case 1:
				cflame.ss.buf_8 = ptr;
				break;
			case 2:
				cflame.ss.buf_16 = ptr;
				break;
			case 4:
				cflame.ss.buf_32 = ptr;
				break;
			default:
				er_panic("interface");
			}
			unlock_task(interface_lock,"opac_move");
			convert_image();
		}
		else {
			if ( cflame.last_shot )
				d_f_ree(cflame.last_shot);
			cflame.last_shot = last_shot;
		}

		checkout_seq(-1);

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


void
set_opac_mode();

void
opac_move()
{
	del_tick(set_opac_mode);
	lock_task(opac_lock);
	_opac_move();
	unlock_task(opac_lock,"opac_move");
}


void
__opac_stop()
{

	lock_task(interface_lock);

	if ( cflame.ss.buf_32 ) {
		d_f_ree(cflame.ss.buf_32);
		cflame.ss.buf_32 = 0;
	}
	if ( cflame.ss.buf_16 ) {
		d_f_ree(cflame.ss.buf_16);
		cflame.ss.buf_16 = 0;
	}
	if ( cflame.ss.buf_8 ) {
		d_f_ree(cflame.ss.buf_8);
		cflame.ss.buf_8 = 0;
	}
	switch ( cflame.ix.type ) {
	case PIT_PLANE:
		d_f_ree(cflame.ix.p.index);
		break;
	case PIT_XY:
		d_f_ree(cflame.ix.xy.index_x);
		d_f_ree(cflame.ix.xy.index_y);
		break;
	default:
		er_panic("_opac_stop");
	}
	cflame.ix.type = 0;
	if ( cflame.start_shot )
		d_f_ree(cflame.start_shot);
	if ( cflame.last_shot )
		d_f_ree(cflame.last_shot);
	cflame.start_shot = cflame.last_shot = 0;

	unlock_task(interface_lock,"opac_stop");
}


void
_opac_stop()
{
int seq;
void * mp;

	if ( cflame.ms == 0 )
		return;
	if ( cflame.start_shot == 0 )
		return;
	if ( cflame.ix.type == 0 )
		return;

	_opac_move();

	seq = (*cflame.ms->flame_func)();

	checkin_seq(seq);

	__opac_stop();

	checkout_seq(seq);
	return;

}

void
opac_stop()
{

	del_tick(set_opac_mode);
	lock_task(opac_lock);
	_opac_stop();
	unlock_task(opac_lock,"opac_stop");
}

void
_set_opac_mode(MOVE_SET * ms)
{
int size;
	if ( cflame.ms != ms )
		_opac_stop();
	if ( ms ) {
		cflame.ms = ms;
		(*ms->param_func)(&cflame.start_shot);
	}
	else if ( cflame.ms ) {
		(*cflame.ms->param_func)(&cflame.start_shot);
	}
}

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

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

	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 ( cflame.ss.buf_32 ) {
		buf = cflame.ss.buf_32;
		ow = cflame.im->vimage.w;
		ret = 1;
	}
	else {
		buf = cflame.im->vimage.buf_32;
		ow = cflame.im->vimage.w_border;
		ret = 0;
	}

	tbl = cflame.window->d->gb2m_map;
	bg = GB2MCOLOR(tbl,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	*dp ++ = GB2MCOLOR(tbl,c);
		}
	}

	return ret;
}

int
set_plane_16(GBVIEW_PLANE * p)
{
unsigned short * buf;
int y_src,y_dest,y_max,x,x_ofs;
unsigned long * sp;
unsigned short * dp;
int w,ow;
unsigned long c;
unsigned short bg;
V_MAP_TBL tbl;
int ret;

	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 ( cflame.ss.buf_16 ) {
		buf = cflame.ss.buf_16;
		ow = cflame.im->vimage.w;
		ret = 1;
	}
	else {
		buf = cflame.im->vimage.buf_16;
		ow = cflame.im->vimage.w_border;
		ret = 0;
	}

	tbl = cflame.window->d->gb2m_map;
	bg = GB2MCOLOR(tbl,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	*dp ++ = GB2MCOLOR(tbl,c);
		}
	}

	return ret;
}

int
set_plane_8(GBVIEW_PLANE * p)
{
unsigned char * buf;
int y_src,y_dest,y_max,x,x_ofs;
unsigned long * sp;
unsigned char * dp;
int w,ow;
unsigned long c;
unsigned char bg;
V_MAP_TBL tbl;
int ret;

	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 ( cflame.ss.buf_8 ) {
		buf = cflame.ss.buf_8;
		ow = cflame.im->vimage.w;
		ret = 1;
	}
	else {
		buf = cflame.im->vimage.buf_8;
		ow = cflame.im->vimage.w_border;
		ret = 0;
	}

	tbl = cflame.window->d->gb2m_map;
	bg = GB2MCOLOR(tbl,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	*dp ++ = GB2MCOLOR(tbl,c);
		}
	}

	return ret;
}

int
set_plane(GBVIEW_PLANE * p)
{
int ret;
	lock_task(interface_lock);

	if ( cflame.im->vimage.buf_8 )
		ret = set_plane_8(p);
	else if ( cflame.im->vimage.buf_16 )
		ret = set_plane_16(p);
	else if ( cflame.im->vimage.buf_32 )
		ret = set_plane_32(p);
	else	er_panic("set_plane");
	unlock_task(interface_lock,"set_plane");
	return ret;
}

int
set_plane_trans_8(GBVIEW_PLANE * p)
{
unsigned char * buf;
int y_src,y_dest,y_max,x,x_ofs;
unsigned long * sp;
unsigned char * dp;
int w,ow;
unsigned long c;
unsigned char bg;
V_MAP_TBL tbl;
int ret;


	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 ( cflame.ss.buf_8 ) {
		buf = cflame.ss.buf_8;
		ow = cflame.im->vimage.w;
		ret = 1;
	}
	else {
		buf = cflame.im->vimage.buf_8;
		ow = cflame.im->vimage.w_border;
		ret = 0;
	}

	tbl = cflame.window->d->gb2m_map;
	bg = GB2MCOLOR(tbl,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 = GB2MCOLOR(tbl,c);
			dp ++;
		}
	}

	return ret;
}

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


	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 ( cflame.ss.buf_32 ) {
		buf = cflame.ss.buf_32;
		ow = cflame.im->vimage.w;
		ret = 1;
	}
	else {
		buf = cflame.im->vimage.buf_32;
		ow = cflame.im->vimage.w_border;
		ret = 0;
	}

	tbl = cflame.window->d->gb2m_map;
	bg = GB2MCOLOR(tbl,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 = GB2MCOLOR(tbl,c);
			dp ++;
		}
	}

	return ret;
}

int
set_plane_trans_16(GBVIEW_PLANE * p)
{
unsigned short * buf;
int y_src,y_dest,y_max,x,x_ofs;
unsigned long * sp;
unsigned short * dp;
int w,ow;
unsigned long c;
unsigned short bg;
V_MAP_TBL tbl;
int ret;


	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 ( cflame.ss.buf_16 ) {
		buf = cflame.ss.buf_16;
		ow = cflame.im->vimage.w;
		ret = 1;
	}
	else {
		buf = cflame.im->vimage.buf_16;
		ow = cflame.im->vimage.w_border;
		ret = 0;
	}

	tbl = cflame.window->d->gb2m_map;
	bg = GB2MCOLOR(tbl,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 = GB2MCOLOR(tbl,c);
			dp ++;
		}
	}

	return ret;
}

int
set_plane_trans(GBVIEW_PLANE * p)
{
int ret;
	lock_task(interface_lock);
	if ( cflame.im->vimage.buf_8 )
		ret = set_plane_trans_8(p);
	else if ( cflame.im->vimage.buf_16 )
		ret = set_plane_trans_16(p);
	else if ( cflame.im->vimage.buf_32 )
		ret = set_plane_trans_32(p);
	else er_panic("set_plane");
	unlock_task(interface_lock,"set_plane");
	return ret;
}

void
redraw_handler(int x,int y,int w,int h)
{
VERROR err;
VWINDOW_ATTRIBUTES attr;
int im_w,im_h;
int change;
int hofs;
int i;
GBVIEW_STATUS sts;
GBVIEW_PLANE gbp;
int seq;

	v_get_window_attributes(&err,&attr,cflame.im->header.win);
	change = 0;
	call_wf_status(&sts,CALL_STS_CACHE_NORMAL);

	sts.flags = 0;
	if ( sts.width != attr.w-W_OFS ) {
		sts.width = attr.w-W_OFS;
		if ( sts.width < 1 )
			sts.width = 1;
		sts.flags |= SF_WIDTH;
		change = 1;
	}
	if ( sts.height != attr.h-H_OFS ) {
		sts.height = attr.h-H_OFS;
		if ( sts.height < 1 )
			sts.height = 1;
		sts.flags |= SF_HEIGHT;
		change = 1;
	}

	if ( change ) {

		opac_stop();
		seq = call_wf_set_status(&sts);

		checkin_seq(seq);

		v_set_image(&err,cflame.im,0,0,sts.width,sts.height);
                v_clear_window_content(&err,cflame.im->header.win);

		checkout_seq(seq);

		seq = call_wf_redraw(&gbp,0,0,sts.width,sts.height);

		checkin_seq(seq);
		set_plane(&gbp);
		wf_free_plane(&gbp);
		checkout_seq(seq);

		hofs = Z_TEXT_HPOINT;
		v_move_text(cflame.c_indicate,
			L_MARGIN,sts.height+TEXT_OFS);
		for ( i = 0 ; i < MODE_NOS ; i ++ ) {
			v_move_text(cflame.mode_btn[i],
				sts.width+Z_MARGIN,
				hofs);
			v_text_minrect(&cflame.mode_btn_rect[i],cflame.mode_btn[i]);
			hofs += Z_TEXT_HEIGHT;
		}
		hofs += Z_TEXT_HEIGHT;
		v_move_text(cflame.zoom_in,
			sts.width+Z_MARGIN,
			hofs);
		hofs += Z_TEXT_HEIGHT;
		v_move_text(cflame.zoom_out,
			sts.width+Z_MARGIN,
			hofs);
		hofs = sts.height - Z_BOTTOM_MARGIN;
		v_move_text(cflame.exit_btn,
			sts.width+Z_MARGIN,
			hofs);
		hofs -= 2*Z_TEXT_HEIGHT;
		v_move_text(cflame.web_page,
			sts.width+Z_MARGIN,
			hofs);
		v_text_minrect(&cflame.zoom_in_rect,cflame.zoom_in);
		v_text_minrect(&cflame.zoom_out_rect,cflame.zoom_out);
		v_text_minrect(&cflame.web_page_rect,cflame.web_page);
		v_text_minrect(&cflame.exit_btn_rect,cflame.exit_btn);
	}
	wf_free_status(&sts);
}



void
copy_image_32(VOBJECT * im,int xx,int yy,
	int *rx1,int *ry1,int *rw1,int *rh1,
	int *rx2,int *ry2,int *rw2,int *rh2)
{
int x1,y1,xe,ye,xinc,yinc;
int x2,y2;
int w;
long * buf;
	w = im->vimage.w_border;

	if ( xx < 0 ) {
		x1 = 0;
		xinc = 1;
		xe = im->vimage.w+xx;

		*rx1 = im->vimage.w+xx;
		*ry1 = 0;
		*rw1 = -xx;
		*rh1 = im->vimage.h;
	}
	else {
		x1 = im->vimage.w-1;
		xinc = -1;
		xe = xx-1;

		*rx1 = 0;
		*ry1 = 0;
		*rw1 = xx;
		*rh1 = im->vimage.h;
	}
	if ( yy < 0 ) {
		y1 = 0;
		yinc = 1;
		ye = im->vimage.h+yy;

		*rx2 = 0;
		*ry2 = im->vimage.h+yy;
		*rw2 = im->vimage.w;
		*rh2 = -yy;
	}
	else {
		y1 = im->vimage.h-1;
		yinc = -1;
		ye = yy-1;

		*rx2 = 0;
		*ry2 = 0;
		*rw2 = im->vimage.w;
		*rh2 = yy;
	}
	buf = im->vimage.buf_32;
	for ( y2 = y1 ; y2 != ye ; y2 += yinc )
		for ( x2 = x1 ; x2 != xe ; x2 += xinc ) {
			buf[y2*w+x2]
			= buf[(y2-yy)*w+x2-xx];
		}
}

void
indicate_coordinate(int x,int y)
{
char buffer[500];
VERROR err;
GB_POINT p;
GB_POINT p2;
RESOURCE * res;
int i,c;
MAP_HISTORY * mh;
REAL1 dummy;
WF_ID wfid;
char * ptr;
INDICATE * in;
GBVIEW_STATUS sts;


	call_wf_status(&sts,CALL_STS_CACHE_NORMAL);
	buffer[0] = 0; 
	wfid = sts.current;
	if ( sts.indicate == 0 ) {
		if ( wfid == 0 ) {
			wf_free_status(&sts);
			return;
		}
		sprintf(buffer,
			"%lf dot/%s      ",
			(double)sts.flame_base_resolution,
			n_string(std_cm,sts.flame_base_unit));
		v_set_text(&err,cflame.c_indicate,
			C_NULL,C_NULL,
			l_string(std_cm,buffer),strlen(buffer));
		wf_free_status(&sts);
		return;
	}
	if ( wfid ) {
		wf_free_status(&sts);
		call_wf_indicate(0,x,y,GPB_ON);
		call_wf_status(&sts,CALL_STS_CACHE_NORMAL);
		sprintf(buffer,
			"%lf dot/%s ",
			(double)sts.flame_base_resolution,
			n_string(std_cm,sts.flame_base_unit));
		ptr = &buffer[strlen(buffer)];
		for ( in = sts.indicate;
				in &&
				ptr - buffer < 400 ;
				in = in->next ) {
			if ( in->status == 0 )
				continue;
			if ( in->status & IS_COORDINATE ) {
				sprintf(ptr," %s(%lfm,%lfm)",
					n_string(std_cm,in->url.resource),
					in->result.x,
					in->result.y);
				ptr = &ptr[strlen(ptr)];
			}
			if ( in->status & IS_OBJECT ) {
				sprintf(ptr,"(on %s)",
					n_string(std_cm,get_url_str(
						&in->res_object->h.entry)));
				ptr = &ptr[strlen(ptr)];
			}
		}
		sprintf(ptr,"      ");
	}

	v_set_text(&err,cflame.c_indicate,
		C_NULL,C_NULL,
		l_string(std_cm,buffer),strlen(buffer));

	wf_free_status(&sts);
}

void
click_press_op(int x,int y)
{
GBVIEW_STATUS sts;

	call_wf_indicate(&sts,x,y,GPB_ON);
	if ( sts.flags & SF_REFERENCE ) {
		set_change_page(n_string(std_cm,
			sts.reference),1);
	}
}

void
click_release_op()
{
return;
printf("ck release\n");

}


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



	if ( gbp->h.seq ) {
		checkin_seq(gbp->h.seq);
		set_plane_trans(gbp);



		v_redraw_image(cflame.im);
		checkout_seq(gbp->h.seq);
	}

	if ( (seq = call_wf_purge_select()) == 0 ) {
		return;
	}

	countup_seq(seq);

	call_wf_status(&sts,CALL_STS_CACHE_NORMAL);

	seq = call_wf_redraw(&gbp2,0,0,
		sts.width,sts.height);

	checkin_seq(seq);

	set_plane(&gbp2);
	if ( gbp2.r.r.tl.x != gbp2.r.r.br.x ) {

		v_part_redraw_image(cflame.im,
			gbp2.r.r.tl.x,gbp2.r.r.tl.y,
			gbp2.r.r.br.x - gbp2.r.r.tl.x,
			gbp2.r.r.br.y - gbp2.r.r.tl.y);
	}

	wf_free_plane(&gbp2);
	wf_free_status(&sts);

	checkout_seq(seq);
}

void
click_op(int x,int y)
{
GBVIEW_STATUS sts;
GBVIEW_PLANE gbp;

	if ( snapshot_check() )
		opac_stop();
	if ( call_wf_click(&sts,&gbp,x,y) ) {
		if ( sts.flags & SF_REFERENCE )
			set_change_page(n_string(std_cm,sts.reference),1);
		interface_click_func(ET_CLICK,&gbp);
		wf_free_plane(&gbp);
	}
	if ( sts.flags & SF_REFERENCE )
		set_change_page(n_string(std_cm,sts.reference),1);

	wf_free_status(&sts);
}



void
exit_handler(int subtype)
{
	switch ( subtype ) {
	case VES_BUTTON_PRESS:
		cflame.mode = GBM_PRESS_EXIT_BTN;
		if ( check_event(cflame.im->header.win,
			VE_BUTTON,VES_BUTTON_PRESS) )
			return;
		return;
	case VES_BUTTON_RELEASE:
		cflame.mode = GBM_IDLE;
		disable_rcache();
		exit(0);
	default:
		return;
	}
}


void
image_button_handler(int subtype,int t,int x,int y)
{
GB_POINT d;
int xx,yy;
int rx1,rx2;
int ry1,ry2;
int rw1,rw2;
int rh1,rh2;
GB_POINT rp,from;
GBVIEW_PLANE gbp;
int seq;
GBVIEW_STATUS sts;

set_cpu_msg(1);
	switch ( subtype ) {
	case VES_BUTTON_PRESS:
set_cpu_msg(2);


		cflame.mode = GBM_PRESS_IMAGE;
		cflame.press_x = x;
		cflame.press_y = y;
		cflame.press_time = t;
		click_press_op(x,y);

		switch ( cflame.select_mode ) {
		case MODE_ROTATE:
			set_opac_mode(&ms_rotate);
			break;
		case MODE_GRAB:
			set_opac_mode(&ms_grab);
			break;
		default:
			er_panic("button_handler");
		}
/*
		set_opening_state_query();
*/
		return;
	case VES_BUTTON_RELEASE:
set_cpu_msg(3);

		cflame.mode = GBM_IDLE;
		if ( x < 0 || y < 0 )
			goto next;
		if ( t - cflame.press_time > CLICK_TIME_TOL )
			goto next;
		if ( IABS(x - cflame.press_x) > CLICK_POINT_TOL )
			goto next;
		if ( IABS(y - cflame.press_y) > CLICK_POINT_TOL )
			goto next;
		click_op(x,y);
	next:
		click_release_op();
		cflame.press_x = x;
		cflame.press_y = y;
		set_opac_mode(0);
		break;
	case VES_BUTTON_MOTION:

		if ( cflame.mode == GBM_PRESS_IMAGE &&
				cflame.select_mode == MODE_ROTATE ) {
			if ( check_event(cflame.im->header.win,
				VE_BUTTON,VES_BUTTON_MOTION) )
				return;

			from.x = cflame.press_x;
			from.y = cflame.press_y;
			rp.x = x;
			rp.y = y;

			cflame.press_x = x;
			cflame.press_y = y;
			opac_move();

			checkin_seq(-1);
			v_redraw_image(cflame.im);
			checkout_seq(-1);
		}
		else if ( cflame.mode == GBM_PRESS_IMAGE &&
				cflame.select_mode == MODE_GRAB ) {
			if ( check_event(cflame.im->header.win,
				VE_BUTTON,VES_BUTTON_MOTION) )
				return;



			cflame.press_x = x;
			cflame.press_y = y;
			opac_move();

			checkin_seq(-1);
			v_redraw_image(cflame.im);
			checkout_seq(-1);

		}
		if ( cflame.mode == GBM_IDLE ) {
			if ( check_event(cflame.im->header.win,
				VE_BUTTON,VES_BUTTON_MOTION) )
				return;
			indicate_coordinate(x,y);
			return;
		}
		if ( cflame.mode != GBM_PRESS_IMAGE )
			return;
		if ( check_event(cflame.im->header.win,
			VE_BUTTON,VES_BUTTON_MOTION) )
			return;
		break;
	default:
		return;
	}
set_cpu_msg(9);
}


void
zoom_in(int subtype)
{
WF_ID wfid;
GBVIEW_PLANE gbp;
int seq;
GBVIEW_STATUS sts;
	if ( cflame.select_mode != MODE_GRAB )
		return;
	switch ( subtype ) {
	case VES_BUTTON_PRESS:
		call_wf_status(&sts,CALL_STS_CACHE_NORMAL);
		if ( cflame.ms != &ms_zoom ) {
			cflame.press_zoom = sts.flame_base_resolution;
			set_opac_mode(&ms_zoom);
		}
		cflame.mode = GBM_PRESS_ZOOM_IN;
		if ( check_event(cflame.im->header.win,
			VE_BUTTON,VES_BUTTON_PRESS) ) {
			wf_free_status(&sts);
			return;
		}
		wfid = sts.current;
		wf_free_status(&sts);
		if ( wfid ) {

			cflame.press_zoom *= RESO_PITCH;
			opac_move();

			checkin_seq(-1);
			v_redraw_image(cflame.im);
			checkout_seq(-1);

			new_tick(set_opac_mode,-OPAC_STOP_TIMEOUT,0);

		}
		return;
	case VES_BUTTON_RELEASE:
		cflame.mode = GBM_IDLE;
		return;
	default:
		return;
	}

}

void
zoom_out(int subtype)
{
WF_ID wfid;
GBVIEW_PLANE gbp;
int seq;
GBVIEW_STATUS sts;

	if ( cflame.select_mode != MODE_GRAB )
		return;
	switch ( subtype ) {
	case VES_BUTTON_PRESS:
		call_wf_status(&sts,CALL_STS_CACHE_NORMAL);
		if ( cflame.ms != &ms_zoom ) {
			cflame.press_zoom = sts.flame_base_resolution;
			set_opac_mode(&ms_zoom);
		}
		cflame.mode = GBM_PRESS_ZOOM_OUT;
		if ( check_event(cflame.im->header.win,
			VE_BUTTON,VES_BUTTON_PRESS) ) {
			wf_free_status(&sts);
			return;
		}
		wfid = sts.current;
		wf_free_status(&sts);
		if ( wfid ) {
			cflame.press_zoom /= RESO_PITCH;
			opac_move();

			checkin_seq(-1);
			v_redraw_image(cflame.im);
			checkout_seq(-1);

			new_tick(set_opac_mode,-OPAC_STOP_TIMEOUT,0);
		}
		return;
	case VES_BUTTON_RELEASE:
		cflame.mode = GBM_IDLE;
		return;
	default:
		return;
	}

}

void
change_web_page(int subtype)
{
char * page;
	switch ( subtype ) {
	case VES_BUTTON_PRESS:
		cflame.mode = GBM_PRESS_WEB_PAGE;
		if ( check_event(cflame.im->header.win,
			VE_BUTTON,VES_BUTTON_PRESS) )
			return;
		page = d_alloc(1000);
		sprintf(page,"http://%s:%i/",
			http_hostname,http_port);
		set_change_page(page,1);
		d_f_ree(page);
		return;
	case VES_BUTTON_RELEASE:
		cflame.mode = GBM_IDLE;
		return;
	default:
		return;
	}
}

void
change_interface_mode(int mode)
{
VERROR err;
int i;
int scol,ccol;
	if ( mode == cflame.select_mode )
		return;
	(*mode_func[cflame.select_mode])(1);
	cflame.select_mode = mode;
	for ( i = 0 ; i < MODE_NOS ; i ++ ) {
		if ( cflame.select_mode == i ) {
			scol = MODE_SELECT_BG_COLOR;
			ccol = MODE_CHAR_COLOR;
		}
		else{
			scol = MODE_NOT_SEL_BG_COLOR;
			ccol = MODE_NOT_SEL_CHAR_COLOR;
		}
		v_set_text(&err,
			cflame.mode_btn[i],
			ccol,scol,
			0,0);
	}
	(*mode_func[cflame.select_mode])(0);
}

void
change_mode(int mode,int subtype)
{
	switch ( subtype ) {
	case VES_BUTTON_PRESS:
		cflame.mode = GBM_PRESS_MODE_BTN;
		if ( check_event(cflame.im->header.win,
			VE_BUTTON,VES_BUTTON_PRESS) )
			return;
		change_interface_mode(mode);
		return;
	case VES_BUTTON_RELEASE:
		cflame.mode = GBM_IDLE;
		return;
	default:
		return;
	}
}


void
button_handler(int subtype,int t,int x,int y)
{
VPOINT p;
int i;
static XL_INTERPRETER * xli;

	if ( xli == 0 ) {
		xli = new_xl_interpreter();
		xli->a_type = XLA_SELF;
		setup_i(xli);
	}

	if ( x < 0 || y < 0 )
		goto next;
	if ( x < cflame.im->vimage.w && y < cflame.im->vimage.h ) {
		image_button_handler(subtype,t,x,y);
		goto end;
	}
	p.x = x;
	p.y = y;
	if ( check_inside(cflame.zoom_in_rect,p) ) {
		zoom_in(subtype);
		goto end;
	}
	if ( check_inside(cflame.zoom_out_rect,p) ) {
		zoom_out(subtype);
		goto end;
	}
	if ( check_inside(cflame.web_page_rect,p) ) {
		change_web_page(subtype);
		goto end;
	}
	if ( check_inside(cflame.exit_btn_rect,p) ) {
		exit_handler(subtype);
	}
	for ( i = 0 ; i < MODE_NOS ; i ++ ) {
		if ( check_inside(cflame.mode_btn_rect[i],p) ) {
			change_mode(i,subtype);
			goto end;
		}
	}
next:
	if ( subtype == VES_BUTTON_RELEASE ) {
		if ( cflame.mode == GBM_PRESS_IMAGE )
			image_button_handler(subtype,t,-1,-1);
		cflame.mode = GBM_IDLE;
	}
end:
	{}
}




VDISPLAY *
gb_window()
{
VDISPLAY * d;
VWINDOW * w;
VERROR err;
int i;
int hofs;
int scol;
int ccol;
GBVIEW_STATUS sts;

	call_wf_status(&sts,CALL_STS_CACHE_REFRESH);

	env_display = d = v_open_disp(&err);

	sts.flags = SF_DISPLAY;
	call_wf_set_status(&sts);

	w = cflame.window = v_open_win(&err,d,50,0,
		sts.width+W_OFS,sts.height+H_OFS);
	cflame.im = v_create_image(&err,w,0,0,
		sts.width,sts.height);
	cflame.c_indicate = v_create_text(&err,w,
		COL(0x3ff,0x3ff,0x3ff),0,
		24,VSD_L2R,
		L_MARGIN,sts.height+TEXT_OFS,
		l_string(std_cm,"coordinate"),strlen("coordinate"));
	hofs = Z_TEXT_HPOINT;
	for ( i = 0 ; i < MODE_NOS ; i ++ ) {
		if ( cflame.select_mode == i ) {
			scol = MODE_SELECT_BG_COLOR;
			ccol = MODE_CHAR_COLOR;
		}
		else{
			scol = MODE_NOT_SEL_BG_COLOR;
			ccol = MODE_NOT_SEL_CHAR_COLOR;
		}
		cflame.mode_btn[i] = v_create_text(&err,w,
			ccol,scol,
			24,VSD_L2R,
			sts.width+Z_MARGIN,hofs,
			l_string(std_cm,mode_btn_text[i]),
			strlen(mode_btn_text[i]));
		v_text_minrect(&cflame.mode_btn_rect[i],cflame.mode_btn[i]);
		hofs += Z_TEXT_HEIGHT;
	}
	hofs += Z_TEXT_HEIGHT;
	cflame.zoom_in = v_create_text(&err,w,
		USE_CHAR_COLOR,USE_BG_COLOR,
		24,VSD_L2R,
		sts.width+Z_MARGIN,hofs,
		l_string(std_cm,"Zoom In "),strlen("Zoom In "));
	hofs += Z_TEXT_HEIGHT;
	cflame.zoom_out = v_create_text(&err,w,
		USE_CHAR_COLOR,USE_BG_COLOR,
		24,VSD_L2R,
		sts.width+Z_MARGIN,hofs,
		l_string(std_cm,"Zoom Out"),strlen("Zoom Out"));
	hofs = sts.height - Z_BOTTOM_MARGIN;
	cflame.exit_btn = v_create_text(&err,w,
		USE_CHAR_COLOR,USE_BG_COLOR,
		24,VSD_L2R,
		sts.width+Z_MARGIN,hofs,
		l_string(std_cm,"Exit    "),strlen("Exit    "));
	hofs -= 2*Z_TEXT_HEIGHT;
	cflame.web_page = v_create_text(&err,w,
		USE_CHAR_COLOR,USE_BG_COLOR,
		24,VSD_L2R,
		sts.width+Z_MARGIN,hofs,
		l_string(std_cm,"Web Page"),strlen("Web page"));
	v_text_minrect(&cflame.zoom_in_rect,cflame.zoom_in);
	v_text_minrect(&cflame.zoom_out_rect,cflame.zoom_out);
	v_text_minrect(&cflame.web_page_rect,cflame.web_page);
	v_text_minrect(&cflame.exit_btn_rect,cflame.exit_btn);

	d->handler[VE_REDRAW] = redraw_handler;
	d->handler[VE_BUTTON] = button_handler;

	wf_free_status(&sts);
	return d;
}


void
interface_redraw_func(int type)
{
	lock_task(interface_redraw_lock);
	if ( cflame.redraw_flag == 0 ) {
		cflame.redraw_flag = 1;
		wakeup_task((int)&cflame.redraw_flag);
	}
	unlock_task(interface_redraw_lock,"cosmos_redraw_event");
}

void
interface_infolist_func(int type,GBVIEW_STATUS * sts)
{
INFO_LIST * il;
char * page, * dir;
	page = d_alloc(1000);
	sprintf(page,"http://%s:%i/sys/indicate.cgi?",
		http_hostname,
		http_port);
	dir = &page[strlen(page)];
	for ( il = sts->infolist; il ; il = il->next ) {
		if ( il->obj->h.info_org == 0 )
			continue;
		if ( il->obj->h.info_card == 0 )
			continue;
		if ( il->next )
			sprintf(dir,"%i:%i-",
				il->r->h.no,
				il->code);
		else
			sprintf(dir,"%i:%i",
				il->r->h.no,
				il->code);
		dir += strlen(dir);
	}
	set_change_page(page,1);
	d_f_ree(page);
}

void
interface_info_error_func()
{
char * page;
	page = 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(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(type,sts);
	else if ( sts->flags & SF_ERROR )
		interface_info_error_func();
	else	er_panic("interface_info_func");
}

void
interface_event_func(GBVIEW_FLAME * gf,int type,void * w)
{
	switch ( type ) {
	case ET_REDRAW:
		interface_redraw_func(type);
		break;
	case ET_CLICK:
		interface_click_func(type,w);
		break;
	case ET_INFO:
		interface_info_func(type,w);
		break;
	default:
		er_panic("interface_event_func(1)");
	}
}


void
pixelmap_task(int argc,char ** argv)
{
GBVIEW_STATUS sts;
GBVIEW_PLANE gbp;
XL_INTERPRETER * xli;
int seq;
int setp = 0;

	printf("start ******  pixelmaptask %i\n",get_tid());

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

set_cpu_thr_type(20);

	cflame.redraw_flag = 1;
	for ( ; ; ) {
		lock_task(interface_redraw_lock);
set_cpu_msg(1);
		for ( ; cflame.redraw_flag ; ) {
			if ( cflame.im_out_off )
				break;
set_cpu_msg(2);

			cflame.redraw_flag = 0;
			unlock_task(interface_redraw_lock,"pixelmap_task");
set_cpu_msg(3);

			call_wf_status(&sts,CALL_STS_CACHE_NORMAL);
set_cpu_msg(4);

			seq = call_wf_redraw(&gbp,0,0,sts.width,sts.height);
set_cpu_msg(5);

			checkin_seq(seq);
set_cpu_msg(6);

			if ( seq ) {
set_cpu_msg(7);
				setp = set_plane(&gbp);
				wf_free_plane(&gbp);
				if ( gbp.r.r.tl.x != gbp.r.r.br.x &&
						setp == 0 )
					v_part_redraw_image(cflame.im,
						gbp.r.r.tl.x,gbp.r.r.tl.y,
						gbp.r.r.br.x 
							- gbp.r.r.tl.x,
						gbp.r.r.br.y 
							- gbp.r.r.tl.y);
			}

set_cpu_msg(8);

			checkout_seq(seq);

			wf_free_status(&sts);

set_cpu_msg(9);
			lock_task(interface_redraw_lock);
		}
		sleep_task((int)&cflame.redraw_flag,interface_redraw_lock);
	}
}

void
check_task()
{
	for ( ; ; ) {
		sleep_sec(10);
		gv_cpu_direct();
	}
}




void
event_task(TKEY key)
{
VDISPLAY * d;

	fprintf(stderr,"event_task = %i\n",get_tid());

set_cpu_thr_type(21);

	change_pri(0,PRI_USER_INTERFACE);
	d = gb_window();
	create_task(pixelmap_task,0,PRI_REDRAW);
	v_loop(d);
}


