/**********************************************************************
 
	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	"pdb.h"
#include	"xl.h"
#include	"gbview.h"
#include	"memory_debug.h"
#include	"memory_routine.h"


DRAW_MATRIX * dm_cache;
RESOURCE * dm_resource;


DRAW_MATRIX *
get_dm(RESOURCE * r,POINT_LIST * p)
{
GB_RECT rr;
DRAW_MATRIX * ret;
	if ( dm_cache ) {
		if ( r != dm_resource )
			goto load;
		if ( dm_cache->level != p->lod_max )
			goto load;
		rr.tl.x = (dm_cache->ofs.x*DM_DIM)*
			dm_resource->draw_gb.pitch_list
				[dm_cache->level-1].x
				+ dm_resource->draw_gb.matrix_ofs.x;
		rr.tl.y = (dm_cache->ofs.y*DM_DIM)*
			dm_resource->draw_gb.pitch_list
				[dm_cache->level-1].y
				+ dm_resource->draw_gb.matrix_ofs.y;
		rr.br.x = (dm_cache->ofs.x*DM_DIM + 2)*
			dm_resource->draw_gb.pitch_list
				[dm_cache->level-1].x
				+ dm_resource->draw_gb.matrix_ofs.x;
		rr.br.y = (dm_cache->ofs.y*DM_DIM + 2)*
			dm_resource->draw_gb.pitch_list
				[dm_cache->level-1].y
				+ dm_resource->draw_gb.matrix_ofs.y;
		if ( inside_rect(&rr,p->pt) == 0 )
			goto load;
		return dm_cache;
	}
load:
	dm_cache = get_dm_of_position(r,p->lod_max,p->pt);


	dm_resource = r;
	return dm_cache;
}

int
insert_point(RESOURCE * r,OBJ * obj,RING_TYPE * ring,int num,REAL1 p1,REAL1 p2,
	int lod_min,int lod_max,GB_POINT * prev,GB_POINT * next,
	unsigned int code)
{
POINT_LIST * p;
POINT_LIST * pp, * pp1;
int ret;
DRAW_MATRIX * dm;

	ret = 0;
	for ( pp = R_NEXT(POINT_LIST*,ring);
			pp != (POINT_LIST*)ring;
			pp = R_NEXT(POINT_LIST*,&pp->h)) {
		if ( (pp->no&PP_LNO) == (num&PP_LNO) ) {
			pp->pt.x = p1;
			pp->pt.y = p2;
			pp->lod_min = lod_min;
			pp->lod_max = lod_max;

			if ( prev ) {
				pp1 = R_PREV(POINT_LIST*,&pp->h);
				if ( pp1 != (POINT_LIST*)ring ) {
					*prev = pp1->pt;
					ret |= 1;
				}
			}
			if ( next ) {
				pp1 = R_NEXT(POINT_LIST*,&pp->h);
				if ( pp1 != (POINT_LIST*)ring ) {
					*next = pp1->pt;
					ret |= 2;
				}
			}
			return ret;
		}
		if ( (pp->no&PP_LNO) > (num&PP_LNO) )
			break;
	}
	touch_obj_mem(sizeof(*p));
	p = d_alloc(sizeof(*p));
	p->pt.x = p1;
	p->pt.y = p2;
	p->no = num;
	p->lod_min = lod_min;
	p->lod_max = lod_max;
	p->obj = obj;

	switch ( r->draw_gb.type ) {
	case DGT_LOAD:
		p->dm_next = 0;
		break;
	case DGT_PDB:
		dm = get_dm(r,p);
		if ( dm ) {
			p->dm_next = dm->dm_point_list;
			dm->dm_point_list = p;
		}
		break;
	default:
		er_panic("insert_point(1)");
	}
	pp1 = R_PREV(POINT_LIST*,&pp->h);
	INSERT_RING((RING_TYPE*)pp1,&p->h);
	if ( prev ) {
		if ( pp1 != (POINT_LIST*)ring ) {
			*prev = pp1->pt;
			ret |= 1;
		}
	}
	if ( next ) {
		if ( pp != (POINT_LIST*)ring ) {
			*next = pp->pt;
			ret |= 2;
		}
	}
	return ret;
}
