/**********************************************************************
 
	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/VxlTreeView.h"
#include "v/vobj_utils.h"

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

VImage *
get_image_from_lchar(XL_SEXP ** retp,XLISP_ENV * env,L_CHAR *,L_CHAR * _img_field);
int get_treeview_flags(char ** pret,
	VxlTreeViewStatus * sts,XLISP_ENV * env,XL_SEXP * arg,XL_SYM_FIELD * sf);
XL_SEXP * vobj_VxlTreeView(XLISP_ENV *env, XL_SEXP *arg, XLISP_ENV *a, XL_SYM_FIELD *sf);


int
get_treeview_flags(char ** pret,VxlTreeViewStatus * sts,XLISP_ENV * env,XL_SEXP * arg,XL_SYM_FIELD * sf)
{
L_CHAR * d;
int ret;
XL_SEXP * _ret;
	ret = 0;
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.Dir"));
	if ( d ) {
		if ( l_strcmp(d,l_string(std_cm,"VirticalLeftToRight")) == 0 )
			sts->dir = VSD_V_L2R;
		else if ( l_strcmp(d,l_string(std_cm,"VirticalRightToLeft")) == 0 )
			sts->dir = VSD_V_R2L;
		else if ( l_strcmp(d,l_string(std_cm,"HorizontalLeftToRight")) == 0 )
			sts->dir = VSD_H_L2R;
		else if ( l_strcmp(d,l_string(std_cm,"HorizontalRightToLeft")) == 0 )
			sts->dir = VSD_H_R2L;
		else {
			*pret = "xltreeview.Dir";
			return 0;
		}
		ret |= VSF_XL_TREEVIEW_DIR;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.LineNos"));
	if ( d ) {
		sts->line_nos = atoi(n_string(std_cm,d));
		ret |= VSF_XL_TREEVIEW_LINE_NOS;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.Img.raw"));
	if ( d ) {
		sts->img = get_image_from_lchar(&_ret,env,arg->h.file->name,d);
		if ( get_type(_ret) == XLT_ERROR ) {
			*pret = "xltreeview.Img.raw";
			return 0;
		}
		ret |= VSF_XL_TREEVIEW_IMG;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.Img.elr0"));
	if ( d ) {
		sts->elr[0] = get_elr(n_string(std_cm,d),sts->img);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.Img.elr1"));
	if ( d ) {
		sts->elr[1] = get_elr(n_string(std_cm,d),sts->img);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.Img.elr2"));
	if ( d ) {
		sts->elr[2] = get_elr(n_string(std_cm,d),sts->img);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.Img.elr"));
	if ( d ) {
		get_elr_ary(sts->elr,n_string(std_cm,d),sts->img);
	}
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.focus"));
	if ( d ) {
		sts->focus_handler = 0;
		ret |= VSF_XL_TREEVIEW_FOCUS;
	}
	d = get_sf_attribute(sf,l_string(std_cm,"xltreeview.scroll"));
	if ( d ) {
		ret |= VSF_XL_TREEVIEW_SCROLL;
	}
	*pret = 0;
	return ret;
}

XL_SEXP *
vobj_VxlTreeView(XLISP_ENV *env, XL_SEXP *arg, XLISP_ENV *a, XL_SYM_FIELD *sf)
{
VExError ex_er;
VObjectStatus sts;
VxlTreeView * obj;
VxlTreeViewStatus t_sts;
char * param_ret;
VObjectAppStatusAry ar[2];
XL_SEXP * _ref;
XL_SEXP * item,* sym;
XL_SEXP * ret,* ret2;
VObject * child;
XL_SEXP * _id;

	ar[0].sts = (void*)&t_sts;
	ar[1].sts = 0;
	ar[1].flags = 0;

	ar[0].flags = get_treeview_flags(&param_ret,&t_sts,env,arg,sf);
	if ( param_ret )
		goto param_err;

	_ref = get_refered_object<VxlTreeView>(&obj,env,arg,sf,VO_XTRV,"VxlTreeView",
		&sts,0,(void*)ar);
	if ( get_type(_ref) == XLT_ERROR )
		goto end;

	ret2 = 0;
	obj->macro_base_parent()->get_status(&sts,VSF_ID);
	for ( arg = cdr(arg) ; get_type(arg) == XLT_PAIR ; arg = cdr(arg) ) {
		item = car(arg);
		if ( get_type(item) != XLT_PAIR )
			continue;
		sym = car(item);
		if ( get_type(sym) != XLT_SYMBOL )
			continue;
		if ( l_strcmp(sym->symbol.data,l_string(std_cm,"Tree")) == 0 ) {
			ret = vobj_eval_child(sts.id, env, item);
			if ( get_type(ret) == XLT_ERROR )
				return ret;
			_id = get_el(car(ret),1);
			child = VObject::get_object_by_id(_id->integer.data);
			obj->attach_child(child,-1);
			ret2 = append(ret,ret2);
		}
		else {
			ret = vobj_eval_child(sts.id, env, 
					List(n_get_symbol("VxlTreeView"),
						item,
						-1));
			if ( get_type(ret) == XLT_ERROR )
				return ret;
			_id = get_el(car(ret),1);
			child = VObject::get_object_by_id(_id->integer.data);
			obj->attach_line(child,-1);
			ret2 = append(ret,ret2);
		}
	}
	

	if ( get_type(_ref) == XLT_INTEGER ) {
		_ref = vobj_get_id_list(_ref->integer.data, ret2, sf,OIF_INTERNAL);
	}
	else {
		ex_er = obj->set_xltreeview_status(&t_sts,ar[0].flags);
		if ( ex_er.code != V_ER_NO_ERR )
			goto err1;
		_ref = 0;
	}
end:
	return _ref;
	obj->destroy();
err1:
	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,"VxlTreeView"),
		List(n_get_string("invalid param of attribute ::"),
			n_get_string(param_ret),
			-1));
}

void
init_vobj_VxlTreeView(XLISP_ENV *env)
{
	set_env(env,l_string(std_cm,"VxlTreeView"),
		get_func_prim((XL_SEXP*(*)())vobj_VxlTreeView,FO_NORMAL,0,1,-1));
}


} // extern "C"
