/**********************************************************************
 
	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	"machine/u_math.h"
#include	"win_flame.h"
#include	"memory_debug.h"
#include	"gbgraph.h"

#define PRI_OFFSET_RATE		20

extern GBVIEW_ENV env;
void ov_default();


void
set_weight(WIN_FLAME * wf)
{
	if ( wf->flags & WFF_LUSTER )
		wf->draw->c.weight = W_E2D_LUSTER;
	else if ( wf->flags & WFF_POLY )
		wf->draw->c.weight = W_E2D_POLY;
	else	wf->draw->c.weight = W_E2D_PLOT;
}

int
e2d_new(
	WIN_FLAME_TABLE * tbl,
	WF_ID *		ret_wfid,
	REAL1		v_reso,
	RESOURCE * 	draw,
	MAP_HISTORY * 	mh,
	GB_POINT	center,
	REAL1		rotate,
	REAL1		resolution)
{
WIN_FLAME * wf, ** wfp;
int i;
GB_RECT	r;
int ret;
int pri;


	if ( (draw->h.flags&RF_INDICATE) == RF_I_OFF )
		return 0;
retry:
	*ret_wfid = 0;
	lock_task(env.wf_lock);
set_t_msg(55);


	if ( env.flame_base && env.flame_base->flags & WFF_FREE ) {
		sleep_task((int)env.flame_base,env.wf_lock);
		goto retry;
	}
	for ( wf = env.flame; wf ; wf = wf->next ) {
		if ( wf->draw != draw )
			continue;
		if ( wf->flags & WFF_FREE ) {
			sleep_task((int)wf,env.wf_lock);
			goto retry;
		}
		wf->flags |= WFF_ACTIVE;
		ret = 0;
		goto end;
	}
	wf = d_alloc(sizeof(*wf),83);
	wf->pri_adj = 0;
	wf->id = _get_new_wfid();
	wf->tbl = tbl;
	wf->sym_i = 0;
	wf->draw = draw;
	wf->mh = copy_mh(mh);
	wf->v_reso = v_reso;
	wf->flags = WFF_ACTIVE|WFF_LUSTER|WFF_DIRTY;
/*
	draw->c.weight = 0;
*/
	wf->pixels = d_alloc(env.win_width * env.win_height * sizeof(long),84);
	for ( i = 0 ; i < env.win_width * env.win_height ; i ++ )
		wf->pixels[i] = C_TRANSPARENT|C_DIRTY;
	if ( env.flame_base == 0  ) {
		env.flame_base = wf;
		env.flame_base_rotate = rotate;
		env.flame_base_resolution = resolution;
		env.flame_base_center = center;
		env.flame_base_display_map.dir = MHD_REVERSE;
		env.flame_base_display_map.type = MHT_LINEAR;
		env.flame_base_display_map.next = 0;
		calc_pitch(1);
	}

	for ( wfp = &env.flame ; *wfp ; wfp = &(*wfp)->next ) {
		if ( (*wfp)->flags & WFF_FREE )
			continue;
		if ( (*wfp)->v_reso > v_reso )
			break;
	}
	wf->next = *wfp;
	*wfp = wf;
	wf->lock = 0;
	wf->lock_list = 0;
	wf->browse = 0;
	wf->aboat_count = 0;

	wf->insert_time = get_xltime();

	_wakeup_wf(wf);
end:
	*ret_wfid = wf->id;
	assert_ls(LSF_ZOOM);
	unlock_task(env.wf_lock,"new_win_flame");
	call_gv_event(RID_INDICATED_COORD,l_string(std_cm,"indicated"));
	call_gv_event(RID_HIDE_COORD,l_string(std_cm,"indicated"));

	return ret;
}


int
e2d_exit(WIN_FLAME * wf)
{
WIN_FLAME ** wfp;
RESOURCE * r;


	if ( !(wf->flags & WFF_FREE) ) {
		return 0;
	}
	if ( env.flame_base == wf ) {
		if ( _wf_set_current(wf,0) )
			assert_ls(LSF_CURRENT);
		else {
			env.flame_base = 0;
		}
	}
	free_mh(wf->mh);
	d_f_ree(wf->pixels);
	wf_free_si(wf);
	for ( wfp = &env.flame ; *wfp != wf ; wfp = &(*wfp)->next );
	if ( *wfp )
		*wfp = wf->next;
	wakeup_task((int)wf);
	wf_free_lock_list(wf);
	d_f_ree(wf);
	_wf_flame_redraw();
	call_gv_event(RID_INDICATED_COORD,l_string(std_cm,"hide"));
	call_gv_event(RID_HIDE_COORD,l_string(std_cm,"hide"));
	wakeup_task((int)&env.flame);
	return 1;
}


void
wf_move_x(WIN_FLAME * wf,int dx,GB_RECT * r)
{
int x,y;
unsigned long * dest, * src;
	if ( dx == 0 )
		return;
	if ( dx > 0 ) {
		for ( y = 0 ; y < env.win_height ; y ++ ) {
			dest = &wf->pixels[(y+1)*env.win_width];
			src = &wf->pixels[(y+1)*env.win_width - dx];
			for ( x = env.win_width-dx ; x > 0 ; x -- )
				*--dest = *--src;
			dest = &wf->pixels[y*env.win_width];
			for ( x = dx ; x > 0 ; x -- )
				*dest++ = C_TRANSPARENT|C_DIRTY;
		}
		r->tl.x = 0;
		r->tl.y = 0;
		r->br.x = dx;
		r->br.y = env.win_height;
	}
	else {
		for ( y = 0 ; y < env.win_height ; y ++ ) {
			dest = &wf->pixels[y*env.win_width];
			src = &wf->pixels[y*env.win_width- dx];
			for ( x = env.win_width+dx ; x > 0 ; x -- )
				*dest ++ = *src ++;
			dest = &wf->pixels[(y+1)*env.win_width + dx];
			for ( x = - dx ; x > 0 ; x -- )
				*dest++ = C_TRANSPARENT| C_DIRTY;
		}
		r->tl.x = env.win_width+dx;
		r->tl.y = 0;
		r->br.x = env.win_width;
		r->br.y = env.win_height;
	}
	wf->mov_x += dx;
}

void
wf_move_y(WIN_FLAME * wf,int dy,GB_RECT * r)
{
int x,y;
unsigned long * dest, * src;
	
	if ( dy == 0 )
		return;
	if ( dy > 0 ) {
		for ( y = env.win_height-1 ; y-dy >= 0 ; y -- ) {
			dest = &wf->pixels[y*env.win_width];
			src = &wf->pixels[(y-dy)*env.win_width];
			for ( x = 0 ; x < env.win_width ; x ++ )
				*dest++ = *src++;
		}
		dest = wf->pixels;
		for ( y = 0 ; y < dy ; y ++ )
			for ( x = 0 ; x < env.win_width ; x ++ )
				*dest++ = C_TRANSPARENT|C_DIRTY;
		r->tl.x = 0;
		r->tl.y = 0;
		r->br.x = env.win_width;
		r->br.y = dy;
	}
	else {
		for ( y = 0 ; y < env.win_height + dy ; y ++ ) {
			src = &wf->pixels[(y-dy)*env.win_width];
			dest = &wf->pixels[y*env.win_width];
			for ( x = 0 ; x < env.win_width ; x ++ )
				*dest++ = *src++;
		}
		dest = &wf->pixels[(env.win_height+dy)*env.win_width];
		for ( y = 0 ; y < - dy ; y ++ )
			for ( x = 0 ; x < env.win_width ; x ++ )
				*dest ++ = C_TRANSPARENT|C_DIRTY;
		r->tl.x = 0;
		r->tl.y = env.win_height+dy;
		r->br.x = env.win_width;
		r->br.y = env.win_height;
	}
	wf->mov_y += dy;
}

int
move_redraw_rect(WIN_FLAME * wf,GB_RECT *r)
{
int min_x,max_x;
int min_y,max_y;
int xx,yy,i,dx,dy;
unsigned long * buf;
GB_POINT * pt_list;
REAL1 * pt_reso;
int length;
MAP_HISTORY * mh;
int w,h;
WIN_FLAME  * _wf;
int lp,lp_x,lp_y;
float a,m;
SURP_SET surp;
int id;

	m = (r->br.x - r->tl.x)*(r->br.y - r->tl.y);
	if ( m > RECT_SIZE*RECT_SIZE )
		m = LOUPH_PITCH;
	else {
	 	m = m*LOUPH_PITCH/(RECT_SIZE*RECT_SIZE);
	}
	a = 2;
	lp = m * sqrt(a) * a;
	if ( lp == 0 )
		lp = 1;
	w = r->br.x - r->tl.x;
	h = r->br.y - r->tl.y;
	pt_list = d_alloc(w*h*sizeof(GB_POINT),85);
	pt_reso = d_alloc(w*h*sizeof(REAL1),86);
	buf = d_alloc(w*h*sizeof(long),87);
	i = 0;
	for ( yy = r->tl.y ; yy < r->br.y ; yy+= lp )
		for ( xx = r->tl.x ; xx < r->br.x ; xx += lp ) {
			pt_list[i].x = xx;
			pt_list[i].y = yy;
			pt_reso[i] = env.flame_base_resolution;
			buf[i] = C_TRANSPARENT;
			i ++;
		}
	length = i;


	mh = add_mh(&env.flame_base_display_map,wf->mh);
change_mh_memtype(mh,1666);

	map_from_flame(mh,pt_list,pt_reso,length);

	set_surp(&surp,r,env.flame_base_resolution);

	map_from_flame(mh,surp.ptr,surp.reso,SURP_NOS);

	id = wf->id;

	_ex_lock();

	unlock_task(env.wf_lock,"move_rect");
	cache_image(wf->id,wf->draw,pt_list,pt_reso,buf,length,r,mh,&surp,0,
		WFF_LUSTER_DIRTY);
	lock_task(env.wf_lock);

	_ex_unlock();
set_t_msg(56);

	_wf = _get_wf_ptr(id);
	if ( _wf != wf )
		goto end;

	i = 0;
	for ( yy = r->tl.y ; yy < r->br.y ; yy+= lp )
		for ( xx = r->tl.x ; xx < r->br.x ; xx += lp ) {
			if ( xx + lp > r->br.x )
				lp_x = r->br.x - xx;
			else	lp_x = lp;
			if ( yy + lp > r->br.y )
				lp_y = r->br.y - yy;
			else	lp_y = lp;
			for ( dx = 0 ; dx < lp_x ; dx ++ )
				for ( dy = 0 ; dy < lp_y ; dy ++ ) {
					if ( pt_reso[i] < 0 ) {
						wf->pixels[xx+dx+
							(yy+dy)*env.win_width]
						|= C_DIRTY;
						continue;
					}
					wf->pixels[xx+dx+(yy+dy)*env.win_width]
						= buf[i]|C_DIRTY;
				}
			i ++;
		}
end:
	d_f_ree(buf);
	d_f_ree(pt_list);
	d_f_ree(pt_reso);
	free_mh(mh);
	return 0;
}


void
wf_move_si(WIN_FLAME * wf,int dx,int dy)
{
GB_RECT r;
SYMBOL_INDICATE ** sip, * si1;
	r.tl.x = r.tl.y = 0;
	r.br.x = env.win_width;
	r.br.y = env.win_height;
	for ( sip = &wf->sym_i ; *sip ; ) {
		si1 = *sip;
		si1->rect.tl.x += dx;
		si1->rect.br.x += dx;
		si1->rect.tl.y += dy;
		si1->rect.br.y += dy;
		if ( cross_rect_rect(&r,&si1->rect) == 1 ) {
			sip = &(*sip)->next;
			continue;
		}
		*sip = si1->next;
		if ( si1->data )
			d_f_ree(si1->data);
		if ( si1->alpha )
			d_f_ree(si1->alpha);
		if ( si1->rect.tl.x == si1->rect.br.x )
			delete_irq(si1->rno,si1->code);

		d_f_ree(si1);
	}
}


int
e2d_move(WIN_FLAME * wf,VPOINT from,VPOINT to,VPOINT * ix)
{
extern int null_wf_spiral;
GB_RECT r1,r2;
int dx,dy;
	dx = to.x - from.x;
	dy = to.y - from.y;
	wf_move_x(wf,dx,&r1);
	wf_move_y(wf,dy,&r2);
	wf_move_si(wf,dx,dy);
	if ( wf->flags & WFF_LUSTER ) {
		if ( dx )
			move_redraw_rect(wf,&r1);
		if ( dy )
			move_redraw_rect(wf,&r2);
	}
	null_wf_spiral = 1;
	if ( wf->flags & WFF_LUSTER )
		wf->flags |= WFF_LUSTER_DIRTY;
	if ( wf->flags & WFF_POLY )
		wf->flags |= WFF_POLY_DIRTY;
	if ( wf->flags & WFF_PLOT )
		wf->flags |= WFF_PLOT_DIRTY;
	return 0;
}


int
e2d_change(
	WIN_FLAME_TABLE * tbl,
	WIN_FLAME * wf)
{
int i;
	switch ( wf->tbl->wf_type ) {
	case WFT_STD:
		break;
	case WFT_PLOT:
		wf->pixels = d_alloc(env.win_width * env.win_height 
				* sizeof(long),84);
		for ( i = 0 ; i < env.win_width * env.win_height ; i ++ )
			wf->pixels[i] = C_TRANSPARENT|C_DIRTY;
		break;
	default:
		er_panic("e2d_change not support");
	}
	set_weight(wf);
	wf->tbl = tbl;
	return 0;
}




void
copy_pixels(WIN_FLAME * wf,unsigned long * buf,REAL1 * reso,GB_RECT * r)
{
int x,y,i,index;
int xx,yy;
unsigned long * dest;
int f;
extern void _wf_set_redraw();

	if ( wf->mov_flag )
		return;
	r->tl.y += wf->mov_y;
	r->tl.x += wf->mov_x;
	r->br.y += wf->mov_y;
	r->br.x += wf->mov_x;
	i = 0;
	insert_redraw_gbr(r);
	f = 0;
	for ( y = r->tl.y ; y < r->br.y ; y ++ )
		for ( x = r->tl.x ; x < r->br.x ; x ++ ) {
			if ( x < 0 || x >= env.win_width ) {
				i ++;
				continue;
			}
			if ( y < 0 || y >= env.win_height ) {
				i ++;
				continue;
			}
			if ( reso[i] < 0 ) {
				i ++;
				continue;
			}
			index = x + y*env.win_width;
			dest = &wf->pixels[index];
			*dest = buf[i]|(*dest&C_DIRTY);
			env.redraw[index] |= RP_REDRAW;
			i ++;
			f = 1;
		}
	if ( f )
		new_tick(_wf_set_redraw,0,0);
}



int
e2d_redraw_rect(WIN_FLAME * wf,GB_RECT *r,int * pri_cnt)
{
int min_x,max_x;
int min_y,max_y;
int xx,yy,i;
unsigned long * buf;
GB_POINT * pt_list;
REAL1 * pt_reso;
int w,h;
MAP_HISTORY * mh;
WIN_FLAME * td, * _wf;
SURP_SET surp;
int id;
int ci_ret;


	if ( r->tl.x < 0 ) {
		if ( r->br.x <= 0 )
			return -1;
		r->tl.x = 0;
	}
	if ( r->tl.x >= env.win_width )
		return -1;
	if ( r->br.x <= 0 )
		return -1;
	if ( r->br.x > env.win_width ) {
		if ( r->tl.x >= env.win_width )
			return -1;
		r->br.x = env.win_width;
	}
	if ( r->tl.y < 0 ) {
		if ( r->br.y <= 0 )
			return -1;
		r->tl.y = 0;
	}
	if ( r->tl.y >= env.win_height )
		return -1;
	if ( r->br.y <= 0 )
		return -1;
	if ( r->br.y > env.win_height ) {
		if ( r->tl.y >= env.win_height )
			return -1;
		r->br.y = env.win_height;
	}
	min_x = r->br.x;
	min_y = r->br.y;
	max_x = r->tl.x;
	max_y = r->tl.y;


	lock_task(env.wf_lock);


	if ( _wf_redraw_pri(wf) < 0 ) {
		unlock_task(env.wf_lock,"wf_redraw_rect");
		return 0;
	}

	if ( _check_exit_flame() ) {
		unlock_task(env.wf_lock,"wf_redraw_rect");
		return -3;
	}

	if ( wf->flags & WFF_RESIZE ) {
		unlock_task(env.wf_lock,"wf_redraw_rect");
		return -2;
	}
	for ( td = wf->next ; td ; td = td->next )
		if ( td->draw->c.ov->h.filter == ov_default )
			break;
	for ( xx = r->tl.x ; xx < r->br.x ; xx ++ )
		for ( yy = r->tl.y ; yy < r->br.y ; yy ++ ) {
			if ( !(wf->pixels[yy*env.win_width + xx]&C_DIRTY) )
				continue;
/*
			if ( td &&
				!(td->pixels[yy*env.win_width + xx]
					& C_TRANSPARENT) )
				continue;
*/
			if ( min_x > xx )
				min_x = xx;
			if ( min_y > yy )
				min_y = yy;
			if ( max_x < xx+1 )
				max_x = xx+1;
			if ( max_y < yy+1 )
				max_y = yy+1;
		}
	if ( max_x < min_x ) {
		unlock_task(env.wf_lock,"wf_redraw_rect");
		return -1;
	}
	r->tl.x = min_x;
	r->tl.y = min_y;
	r->br.x = max_x;
	r->br.y = max_y;
	wf->mov_x = 0;
	wf->mov_y = 0;
	wf->mov_flag = 0;

	w = r->br.x - r->tl.x;
	h = r->br.y - r->tl.y;
	pt_list = d_alloc(w*h*sizeof(GB_POINT),88);
	pt_reso = d_alloc(w*h*sizeof(REAL1),89);
	buf = d_alloc(w*h*sizeof(long),90);
	i = 0;



	for ( yy = r->tl.y ; yy < r->br.y ; yy++ )
		for ( xx = r->tl.x ; xx < r->br.x ; xx ++ ) {
			pt_list[i].x = xx;
			pt_list[i].y = yy;
			if ( !(wf->pixels[yy*env.win_width + xx]&
					C_DIRTY) ) {
				pt_reso[i] = -1;
				i ++;
				continue;
			}
			wf->pixels[yy*env.win_width + xx]
				&= ~C_DIRTY;
			pt_reso[i] = env.flame_base_resolution;
			buf[i] = C_TRANSPARENT;
			i ++;	
		}	


	mh = add_mh(&env.flame_base_display_map,wf->mh);

	if ( wf->flags & WFF_LUSTER )
		map_from_flame(mh,pt_list,pt_reso,w*h);


	set_surp(&surp,r,env.flame_base_resolution);
	map_from_flame(mh,surp.ptr,surp.reso,SURP_NOS);
	id = wf->id;
	unlock_task(env.wf_lock,"wf_redraw_rect");


	ci_ret = cache_image(wf->id,wf->draw,pt_list,pt_reso,buf,
		w*h,r,mh,&surp,1,
		WFF_PLOT_DIRTY|WFF_LUSTER_DIRTY);


	lock_task(env.wf_lock);
set_t_msg(58);
	_wf = _get_wf_ptr(id);
	if ( _wf != wf )
		goto end;

	if ( !(ci_ret & WFF_DRAW) )
		(*pri_cnt) ++;

	if ( wf->flags & WFF_RESIZE ) {
		d_f_ree(buf);
		d_f_ree(pt_list);
		d_f_ree(pt_reso);
		free_mh(mh);
		unlock_task(env.wf_lock,"wf_redoraw_rect");
		return -2;
	}
	copy_pixels(wf,buf,pt_reso,r);
	if ( wf->mov_flag )
		wf_free_si(wf);
	else	regulate_si(wf);

end:
	unlock_task(env.wf_lock,"wf_redoraw_rect");
	d_f_ree(buf);
	d_f_ree(pt_list);
	d_f_ree(pt_reso);
	free_mh(mh);
	return 0;
}



extern int interface_flag;

int spiral_count;

typedef struct redraw_pixel {
	int		w;
	int		h;
	int		st_w;
	int		st_h;
	int		rdm;
	int		delta[4];
} REDRAW_PIXEL;

REDRAW_PIXEL rp;

void
set_redraw_pixel()
{
double unit;
	unit = sqrt(((double)DL_PITCH)*DL_PITCH/
		    (env.win_width*env.win_height));
	rp.w = unit*env.win_width;
	rp.h = unit*env.win_height;
	rp.st_w = env.win_width/2 - rp.w/2;
	rp.st_h = env.win_height/2 - rp.h/2;
}

int
inc_xy(int * x,int * y)
{
	if ( (*x) == 0 && (*y) == 0 )
		goto home;
	if ( (*y) < 0 && -(*y) >= (*x) && (*x) > (*y) ) {
		(*x) --;
		return 0;
	}
	if ( (*x) < 0 && (*x) <= (*y) && (*y) < -(*x) ) {
		(*y) ++;
		return 0;
	}
	if ( (*y) > 0 && -(*y) <= (*x) && (*x) < (*y) ) {
		(*x) ++;
		return 0;
	}
	/* if ( x > 0 && -x >= y && y > x ) */
	(*y) --;
	if ( (*x) == -(*y) )
		goto home;
	return 0;
home:
	(*x) ++;
	(*y) --;
	return 1;
}

int
_e2d_redraw(WIN_FLAME * wf)
{
int xx,yy;
GB_RECT rr;
int t,l,r,b;
int dx,dy;
int ret;
int sc;
int pri_cnt;


restart:
	lock_task(env.wf_lock);
set_t_msg(59);
	sc = 0;
	wf->flags &= ~WFF_RESIZE;
	set_redraw_pixel();
	unlock_task(env.wf_lock,"load_spiral");
	xx = yy = 0;
	t = l = r = b = 0;
	ret = 0;
	pri_cnt = 0;
	for ( ; ; ) {
		if ( rp.st_h + yy*rp.h < 0 )
			t = 1;
		if ( rp.st_h + yy*rp.h >= env.win_height )
			b = 1;
		if ( rp.st_w + xx*rp.w < 0 )
			l = 1;
		if ( rp.st_w + xx*rp.w >= env.win_width )
			r = 1;
		rr.tl.x = rp.st_w + xx*rp.w;
		rr.tl.y = rp.st_h + yy*rp.h;
		rr.br.x = rr.tl.x + rp.w;
		rr.br.y = rr.tl.y + rp.h;
/*
printf("** %i(%x) ** xx %i %i %i %i %i %i\n",get_tid(),wf->flags,
xx,yy,t,b,l,r);
*/

		switch ( e2d_redraw_rect(wf,&rr,&pri_cnt) ) {
		case 0:
			ret = 1;
		case -1:
			break;
		case -2:
			goto restart;
		case -3:
			ret = 2;
			goto end;
		default:
			er_panic("aaa");
		}
		if ( wf->flags & WFF_FREE ) {
			ret = 0;
			goto end;
		}
		if ( inc_xy(&xx,&yy) ) {
			if ( t && b && l && r )
				break;
		}
		sc ++;
	}
	spiral_count = sc;
end:
	if ( spiral_count )
		_set_pri_adj(wf,pri_cnt*PRI_OFFSET_RATE/spiral_count);
	else	_set_pri_adj(wf,pri_cnt);

	return ret;
}

int
e2d_redraw(WIN_FLAME * wf)
{
int ret;
int flags;
	ret = 0;

	lock_task(env.wf_lock);
set_t_msg(60);
	set_weight(wf);
	flags = wf->flags;
	if ( wf->flags & (WFF_POLY_DIRTY|WFF_LUSTER_DIRTY) ) {
		wf->flags &= ~(WFF_POLY_DIRTY|WFF_LUSTER_DIRTY);
		unlock_task(env.wf_lock,"e2d_redraw");
		if ( _e2d_redraw(wf) == 2 ) {
			ret = 2;
			wf->flags |= flags &
				(WFF_POLY_DIRTY|WFF_LUSTER_DIRTY);
		}
		else	ret = 1;
	}
	else	unlock_task(env.wf_lock,"e2d_redraw");
	lock_task(env.wf_lock);
set_t_msg(61);
	if ( wf->flags & WFF_PLOT_DIRTY ) {
		wf->flags &= ~(WFF_PLOT_DIRTY|WFF_RESIZE);
		if ( _wf_redraw_pri(wf) < 0 ) {
			ret = 0;
			unlock_task(env.wf_lock,"e2d_redraw");
		}
		else {
			unlock_task(env.wf_lock,"e2d_redraw");
			if ( _e2d_p_redraw(wf) == 2 ) {
				ret = 2;
				wf->flags |= flags &
					(WFF_PLOT_DIRTY|WFF_RESIZE);
			}
			else	ret = 1;
		}
	}
	else	unlock_task(env.wf_lock,"e2d_redraw");
	return ret;
}

int
e2d_dirty(WIN_FLAME * wf,GB_RECT * r,int flags,int mode)
{
int i;
int x,y;
VRECT rr;
unsigned long * p;
	if ( r == 0 ) {
		for ( i = 0; i < env.win_width*env.win_height ; i ++ )
			wf->pixels[i] |= C_DIRTY;
	}
	else {
		if ( r->tl.x < 0 )
			rr.tl.x = 0;
		else	rr.tl.x = r->tl.x;
		if ( r->tl.y < 0 )
			rr.tl.y = 0;
		else	rr.tl.y = r->tl.y;
		if ( r->br.x >= env.win_width )
			rr.br.x = env.win_width;
		else	rr.br.x = r->br.x;
		if ( r->br.y >= env.win_height )
			rr.br.y = env.win_height;
		else	rr.br.y = r->br.y;

		for ( y = rr.tl.y ; y < rr.br.y ; y ++ ) {
			p = &wf->pixels[y*env.win_width + rr.tl.x];
			for ( x = rr.tl.x ; x < rr.br.x ; x ++ , p ++ )
				*p |= C_DIRTY;
		}
	}
/*
	wf->rd_mode = mode;
*/
	wf->flags |= flags & WFF_DIRTY;
	_wakeup_wf(wf);
	return 0;
}

int
e2d_overlay(WIN_FLAME * wf,OV_ARG * a)
{
	a->src = wf->pixels;
	a->s_x = a->d_x;
	a->s_y = a->d_y;
	a->s_w = a->d_w;
	a->s_h = a->d_h;
	(*wf->draw->c.ov->h.filter)
			(wf->draw->c.ov,a);
	return 0;
}

int
e2d_zoom(WIN_FLAME * wf,int w,int h,int * ix_x,int * ix_y)
{
extern int null_wf_spiral;
int i;

	wf_free_si(wf);
	wf_im_zoom_proc(wf->pixels,w,h,ix_x,ix_y);
	for ( i = 0 ; i < env.win_height*env.win_width ; i ++ )
		wf->pixels[i] |= C_DIRTY;
	wf->flags |= WFF_DIRTY;
	return 0;
}

int
e2d_resize(WIN_FLAME * wf)
{
int w,h;
int i,x,y,dx,dy;
int w2,h2;
	w = env.win_width;
	h = env.win_height;

	wf->pixels = d_re_alloc(wf->pixels,w*h*sizeof(long));
	for ( i = 0 ; i < w*h ; i ++ )
		wf->pixels[i] = C_DIRTY|C_TRANSPARENT;
	if ( wf->flags & WFF_LUSTER )
		wf->flags |= WFF_LUSTER_DIRTY;
	if ( wf->flags & WFF_POLY )
		wf->flags |= WFF_POLY_DIRTY;
	if ( wf->flags & WFF_PLOT )
		wf->flags |= WFF_PLOT_DIRTY;
	return 0;
}


int
e2d_rotate(WIN_FLAME * wf,VPOINT * ix)
{
unsigned long * plane, * pp;
int i;
unsigned long * _rotate_plane(
	unsigned long * plane,
	VPOINT * index);

	plane = _rotate_plane(wf->pixels,ix);
	pp = plane;
	for ( i = 0 ; i < env.win_width * env.win_height ; i ++ )
		*pp ++ |= C_DIRTY;
	d_f_ree(wf->pixels);
	wf->pixels = plane;
	wf_free_si(wf);
	if ( wf->flags & WFF_LUSTER )
		wf->flags |= WFF_LUSTER_DIRTY;
	if ( wf->flags & WFF_POLY )
		wf->flags |= WFF_POLY_DIRTY;
	if ( wf->flags & WFF_PLOT )
		wf->flags |= WFF_PLOT_DIRTY;
	return 0;
}

