/**********************************************************************
 
	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>

#include "v/VgbIndicate.h"
#include "v/vobj_utils.h"

extern "C" {
#include 	"xl.h"
#include	"xlerror.h"

VImage *
get_image_from_lchar(XL_SEXP ** retp,XLISP_ENV * env,L_CHAR *,L_CHAR * _img_field);
void copy_im(VgbIndicateImage * im1,VgbIndicateImage * im2);
char * VgbIndicate_get_in_from_sf(
	VgbIndicateStatus * sts,int * flags,XLISP_ENV * env,L_CHAR * filepath,
			XL_SYM_FIELD * sf);
char * VgbIndicate_get_m_from_sf(
	VgbIndicateMeter * sts,int * flags,XLISP_ENV * env,XL_SYM_FIELD * sf);
XL_SEXP * vobj_VgbIndicate(XLISP_ENV *env, XL_SEXP *arg, XLISP_ENV *a, XL_SYM_FIELD *sf);


void
copy_im(VgbIndicateImage * im1,VgbIndicateImage * im2)
{
	if ( im2->img ) {
		if ( im1->img )
			v_image_unref(im1->img);
		im1->img = im2->img;
	}
	if ( im2->name )
		im1->name = im2->name;
	if ( im2->levels )
		im1->levels = im2->levels;
	if ( im2->pitch )
		im1->pitch = im2->pitch;
	if ( im2->elr.t != 0 || im2->elr.b != 0 || 
			im2->elr.l != 0 || im2->elr.r != 0 )
		im1->elr = im2->elr;
}

char *
VgbIndicate_get_in_from_sf(
	VgbIndicateStatus * sts,int * flags,XLISP_ENV * env,L_CHAR * filepath,
			XL_SYM_FIELD * sf)
{
char * d;
char * pt;
int ix1,ix2;
XL_SEXP * ret;
VgbIndicateImage im;
int i;
	memset(sts,0,sizeof(*sts));
	*flags = 0;
	for ( ; sf ; sf = sf->next ) {
		d = n_string(std_cm,sf->name);
		if ( memcmp(d,"indicate.ary",12) )
			continue;
		pt = get_num(&ix1,&d[12]);
		switch ( *pt ) {
		case 0:
			ix2 = ix1;
			goto end;
		case '.':
			ix2 = ix1;
			goto sufix;
		case '-':
			break;
		default:
			continue;
		}
		pt = get_num(&ix2,pt+1);
		switch ( *pt ) {
		case 0:
			goto end;
		case '.':
			goto sufix;
		default:
			continue;
		}
	sufix:
		memset(&im,0,sizeof(im));
		if ( strcmp(pt,".raw") == 0 ) {
			im.img = get_image_from_lchar(&ret,env,filepath,sf->data);
			if ( get_type(ret) == XLT_ERROR )
				return "image error";
		}
		else if ( strcmp(pt,".name") == 0 ) {
			im.name = sf->data;
		}
		else if ( strcmp(pt,".levels") == 0 ) {
			im.levels = atoi(n_string(std_cm,sf->data));
		}
		else if ( strcmp(pt,".pitch") == 0 ) {
			im.pitch = atoi(n_string(std_cm,sf->data));
		}
		else if ( strcmp(pt,".elr") == 0 ) {
			im.elr = get_elr(n_string(std_cm,sf->data),im.img);
		}
		else	continue;
		if ( ix1 >= IND_ARY_LEN )
			ix1 = IND_ARY_LEN-1;
		if ( ix2 >= IND_ARY_LEN )
			ix2 = IND_ARY_LEN-1;
		if ( ix1 < ix2 )
			for ( i = ix1 ; i <= ix2 ; i ++ ) {
				copy_im(&sts->ary[i],&im);
				*flags |= 1<<i;
			}
		else	for ( i = ix2 ; i <= ix1 ; i ++ ) {
				copy_im(&sts->ary[i],&im);
				*flags |= 1<<i;
			}
	end:
		;
	}
	return 0;
}

char *
VgbIndicate_get_m_from_sf(
	VgbIndicateMeter * sts,int * flags,XLISP_ENV * env,XL_SYM_FIELD * sf)
{
char * d;
char * pt;
int ix1,ix2;
int mt;
int i;
int f;
	memset(sts,0,sizeof(*sts));
	*flags = 0;
	for ( ; sf ; sf = sf->next ) {
		d = n_string(std_cm,sf->name);
		if ( memcmp(d,"indicate.ary",12) )
			continue;
		pt = get_num(&ix1,&d[12]);
		switch ( *pt ) {
		case 0:
			ix2 = ix1;
			goto end;
		case '.':
			ix2 = ix1;
			goto sufix;
		case '-':
			break;
		default:
			continue;
		}
		pt = get_num(&ix2,pt+1);
		switch ( *pt ) {
		case 0:
			goto end;
		case '.':
			goto sufix;
		default:
			continue;
		}
	sufix:
		if ( strcmp(pt,".set") == 0 ) {
			mt = atoi(n_string(std_cm,sf->data));
			f = 1<<i;
		}
		else if ( strcmp(pt,".delta") == 0 ) {
			mt = atoi(n_string(std_cm,sf->data));
			f = 1<<(i+IND_ARY_LEN);
		}
		else	continue;
		if ( ix1 >= IND_ARY_LEN )
			ix1 = IND_ARY_LEN-1;
		if ( ix2 >= IND_ARY_LEN )
			ix2 = IND_ARY_LEN-1;
		if ( ix1 < ix2 )
			for ( i = ix1 ; i <= ix2 ; i ++ ) {
				sts->ary[i] = mt;
				*flags |= f;
			}
		else	for ( i = ix2 ; i <= ix1 ; i ++ ) {
				sts->ary[i] = mt;
				*flags |= f;
			}
	end:
		;
	}
	return 0;
}

XL_SEXP *
vobj_VgbIndicate(XLISP_ENV *env, XL_SEXP *arg, XLISP_ENV *a, XL_SYM_FIELD *sf)
{
VExError ex_er;
VObjectStatus _sts;
VgbIndicateStatus in_sts;
VgbIndicateMeter m_sts;
int in_flags,m_flags;
char * param_ret;
XL_SEXP * p;
VObjectAppStatusAry app[3];
VgbIndicate * obj;

	param_ret = VgbIndicate_get_in_from_sf(&in_sts,&in_flags,env,
				arg->h.file->name,sf);
	if ( param_ret )
		goto param_err;
	param_ret = VgbIndicate_get_m_from_sf(&m_sts,&m_flags,env,sf);
	if ( param_ret )
		goto param_err;
	app[0].sts = (void*)&in_sts;
	app[0].flags = in_flags;
	app[1].sts = (void*)&m_sts;
	app[1].flags = m_flags;
	app[2].sts = 0;
	app[2].flags = 0;
	p = get_refered_object<VgbIndicate>(&obj,env,arg,sf,
			VO_GIND,"VgbIndicate",
			&_sts,0,app);
	if ( get_type(p) == XLT_ERROR )
		return p;
	if ( get_type(p) == XLT_INTEGER )
		return vobj_get_id_list(p->integer.data, 0, sf,0);

	ex_er = obj->set_indicate_status(&in_sts,in_flags);
	if ( ex_er.code != V_ER_NO_ERR )
		goto err2;
	ex_er = obj->set_indicate_meter(&m_sts,m_flags);
	if ( ex_er.code != V_ER_NO_ERR )
		goto err2;
	return 0;
err2:
	obj->destroy();
	return vobj_get_error(ex_er, arg);
param_err:
	return get_error(
		arg->h.file,
		arg->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"VgbIndicate"),
		List(n_get_string("invalid param of attribute ::"),
			n_get_string(param_ret),
			-1));
}

void
init_vobj_VgbIndicate(XLISP_ENV *env)
{
	set_env(env,l_string(std_cm,"VgbIndicate"),
		get_func_prim((XL_SEXP*(*)())vobj_VgbIndicate,FO_NORMAL,0,1,1));
}


} // extern "C"
