/**********************************************************************
 
	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	"xlerror.h"
#include	"memory_debug.h"
#include	"xl.h"
#include	"xl2pdb_p.h"
#include	"avt.h"



XL_SEXP * xl_polygon2d();
AVT_NODE * pdb_avt;
AVT_NODE * pdb_same_name_avt;

extern int pdb_p_list_nos;
extern PDB_POLYGON2D * pdb_p_list;

void gc_pdb_p_list()
{
	PDB_POLYGON2D *p;
	for(p=pdb_p_list; p; p = p->next){
		if(p->info)
			gc_gb_sexp(p->info);
	}
}

int
cmp_sn(PDB_POLYGON2D * p1,PDB_POLYGON2D * p2)
{
int ret;
	return l_strcmp(p1->name,p2->name);
}

void
insert_sn_avt(PDB_POLYGON2D * p)
{
AVT_NODE * n;

	n = d_alloc(sizeof(*n),235);
	n->data = p;
	avt_insert(&pdb_same_name_avt,n,cmp_sn);

}

PDB_POLYGON2D *
search_sn_avt(L_CHAR * name)
{
PDB_POLYGON2D p;
AVT_NODE * a;
	p.name = name;
	a = avt_search(pdb_same_name_avt,&p,cmp_sn);
	if ( a == 0 )
		return 0;
	return a->data;
}

int
cmp_pdb_p(PDB_POLYGON2D * p1,PDB_POLYGON2D * p2)
{
int ret;
	ret = l_strcmp(p1->name,p2->name);
	if ( ret )
		return ret;
	return l_strcmp(p1->subname,p2->subname);
}

void
insert_pdb_avt(PDB_POLYGON2D * p)
{
AVT_NODE * n;
	n = d_alloc(sizeof(*n),23);
	n->data = p;
	avt_insert(&pdb_avt,n,cmp_pdb_p);
}

PDB_POLYGON2D *
search_pdb_avt(L_CHAR * name,L_CHAR * subname)
{
PDB_POLYGON2D p;
AVT_NODE * a;
	if ( subname == 0 )
		subname = l_string(std_cm,"0");
	p.name = name;
	p.subname = subname;
	a = avt_search(pdb_avt,&p,cmp_pdb_p);
	if ( a == 0 )
		return 0;
	return a->data;
}

void
init_polygon2d(XLISP_ENV * env)
{
	set_env(env,l_string(std_cm,"polygon2d"),
		get_func_prim(xl_polygon2d,FO_APPLICATIVE,0,1,1));
}

PDB_POLYGON2D *
get_polygon(XL_SEXP ** retp,XL_SYM_FIELD * sf,XL_FILE * file,int line)
{
PDB_POLYGON2D * p;
L_CHAR * name;
L_CHAR * subname;

	name = 0;
	subname = 0;
	*retp = 0;
	for ( ; sf ; sf = sf->next ) {
		if ( l_strcmp(sf->name,l_string(std_cm,"name")) == 0 )
			name = sf->data;
		else if ( l_strcmp(sf->name,l_string(std_cm,"subname"))
				== 0 )
			subname = sf->name;
	}
	if ( name == 0 )  {
		*retp = get_error(
			file,
			line,
			XLE_PROTO_INV_PARAM,
			l_string(std_cm,"polygon2d"),
				List(n_get_string("required name attribute"),
					-1));
		return 0;
	}
	if ( subname == 0 )
		subname = l_string(std_cm,"0");
	return search_pdb_avt(name,subname);
}

XL_SEXP *
xl_polygon2d(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
L_CHAR * name;
L_CHAR * subname;
int type;
int depth;
PDB_POLYGON2D * p;
char * e_param;
PDB_POLYGON2D * p2;

	depth = 0;
	type = PDT_OPEN;
	name = 0;
	subname = 0;
	for ( ; sf ; sf = sf->next ) {
		if ( l_strcmp(sf->name,l_string(std_cm,"name")) == 0 )
			name = sf->data;
		else if ( l_strcmp(sf->name,l_string(std_cm,"subname")) == 0 )
			subname = sf->data;
		else if ( l_strcmp(sf->name,l_string(std_cm,"depth")) == 0 )
			sscanf(n_string(std_cm,sf->data),"%i",&depth);
		else if ( l_strcmp(sf->name,l_string(std_cm,"type")) == 0 ) {
			if ( l_strcmp(sf->data,l_string(std_cm,"open"))
					== 0 )
				type = PDT_OPEN;
			else if ( l_strcmp(sf->data,l_string(std_cm,"close"))
					== 0 )
				type = PDT_CLOSE;
			else {
				e_param = "attribute type";
				goto invalid_param;
			}
		}
		else {
			e_param = "attribute name";
			goto invalid_param;
		}
	}
	if ( name == 0 ) {
		e_param = "name";
		goto invalid_param2;
	}
	if ( search_pdb_avt(name,subname) )
		goto duplicate;
	p = d_alloc(sizeof(*p),3);
	p->name = ll_copy_str(name,123);
	if ( subname )
		p->subname = ll_copy_str(subname,123);
	else	p->subname = nl_copy_str(std_cm,"0");
	p->code = 0;
	p->depth = depth;
	p->type = type;
	p->point = 0;
	p->info = 0;
	p->info_ofs = 0;
	p->padding.r = p->padding.g = p->padding.b = 
		p->padding.t = 0;
	p->line.r = p->line.g = p->line.b =
		p->line.t = 0;
	p->minrect.tl.x = p->minrect.tl.y = 0;
	p->minrect.br.x = p->minrect.br.y = -1;
	p->next = pdb_p_list;
	pdb_p_list = p;
	pdb_p_list_nos ++;
	insert_pdb_avt(p);
	p2 = search_sn_avt(p->name);
	if ( p2 == 0 ) {
		p->samename = 0;
		insert_sn_avt(p);
	}
	else {
		p->samename = p2->samename;
		p2->samename = p;
	}
	return 0;
duplicate:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_DUP_DEFINITION,
		l_string(std_cm,"polygon2d"),
			List(n_get_string("duplicated polygon"),
				get_string(name),
				get_string(subname),
				-1));
invalid_param:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"polygon2d"),
			List(n_get_string("ivalid parameter"),
				n_get_string(e_param),
				-1));
invalid_param2:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"polygon2d"),
			List(n_get_string("ivalid parameter (attribute name)"),
				n_get_string(e_param),
				-1));
}


void remove_poly_from_pdb_p_avt(PDB_POLYGON2D *poly){
	avt_delete(&pdb_avt, poly, cmp_pdb_p);
	avt_delete(&pdb_same_name_avt, poly, cmp_sn);
}

