/**********************************************************************
 
	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	"memory_debug.h"
#include	"utils.h"
#include	"win_flame.h"
#include	"xl.h"
#include	"xlerror.h"
#include	"lock_level.h"
#include	"pri_level.h"
#include	"queue.h"

/*
typedef struct indicate_t {
	Q_HEADER		h;
	RESOURCE *		r;
} INDICATE_T;
*/

#define IRQ_MAX		20

extern RESOURCE ** res_entry_hash_table;
extern SEM irq_lock,in_lock,iom_lock;

void indicate_info_task();


void
gf_init_indicate(GBVIEW_FLAME * gf)
{
	ch_lock_init(&gf->indicate_lock);
/*
	memset(&gf->req_indicate,0,sizeof(SYS_QUEUE));
	gf->req_indicate.flags = QF_FIFO;
	gf->req_indicate.gc_func = 0;
	gf->req_indicate.gc_get = 0;
	gf->req_indicate.key_func = indicate_info_task;
	gf->req_indicate.pri = PRI_FETCH_STRONG;
	gf->req_indicate.work = gf;
	setup_queue(&gf->req_indicate);
*/
}


void
xx_wf_indicate_lock(GBVIEW_FLAME * gf,char * file,int line)
{
	ch_lock(&gf->indicate_lock,file,line);
}

#define wf_indicate_lock(gf)	xx_wf_indicate_lock(gf,__FILE__,__LINE__)
void
wf_indicate_unlock(GBVIEW_FLAME * gf)
{
	ch_unlock(&gf->indicate_lock);
}

void
wf_irq_lock(GBVIEW_FLAME * gf)
{
	lock_task(irq_lock);
}

void
wf_irq_unlock(GBVIEW_FLAME * gf)
{
	unlock_task(irq_lock,"wf_irq_unlock");
}

void
wf_iom_lock()
{
	lock_task(iom_lock);
}

void
wf_iom_unlock()
{
	unlock_task(iom_lock,"iom");
}

void
gc_indicate_func(GBVIEW_FLAME * gf)
{
INFO_LIST * il;
	for ( il = gf->infolist ; il ; il = il->next )
		gc_gb_sexp(il->info);
}

void
gc_indicate()
{
GBVIEW_FLAME * gf;
extern GBVIEW_FLAME * gbview_flame_list;
	for ( gf = gbview_flame_list ; gf ; gf = gf->next )
		gc_indicate_func(gf);
}

void
gc_indicate_lock()
{
GBVIEW_FLAME * gf;
extern GBVIEW_FLAME * gbview_flame_list;
extern SEM gbview_flame_lock;
	if ( gbview_flame_lock == 0 )
		return;
	lock_task(gbview_flame_lock);
	for ( gf = gbview_flame_list ; gf ; gf = gf->next ) {
		_ch_lock(&gf->indicate_lock,__FILE__,__LINE__);
	}
}

void
gc_indicate_unlock()
{
GBVIEW_FLAME * gf;
extern GBVIEW_FLAME * gbview_flame_list;
extern SEM gbview_flame_lock;
	if ( gbview_flame_lock == 0 )
		return;
	for ( gf = gbview_flame_list ; gf ; gf = gf->next ) {
		_ch_unlock(&gf->indicate_lock);
	}
	unlock_task(gbview_flame_lock,"gc_indicate_unlock");
}

INDICATE *
_search_indicate(GBVIEW_FLAME * gf,URL * u)
{
INDICATE * in;
	for ( in = gf->indicate ;
		in &&
		url_cmp_str(&in->url,u);
		in = in->next );
	return in;
}

void
_delete_indicate(GBVIEW_FLAME * gf,URL * u)
{
INDICATE ** inp,* in;
	for ( inp = &gf->indicate ; *inp ; inp = &(*inp)->next )
		if ( url_cmp_str(&(*inp)->url,u) == 0 ) {
			in = *inp;
			*inp = in->next;
			free_url(&in->url);
			d_f_ree(in);
			return;
		}
}

INDICATE *
_insert_indicate(GBVIEW_FLAME * gf,URL * u)
{
INDICATE * in, ** inp;
	in = _search_indicate(gf,u);
	if ( in == 0 ) {
		in = d_alloc(sizeof(*in));
		copy_url(&in->url,u);
		in->status = 0;
		in->next = 0;
		in->flags = 0;
		for ( inp = &gf->indicate ; *inp ; inp = &(*inp)->next );
		*inp = in;
	}
	return in;
}

/*
void
insert_indicate(GBVIEW_FLAME * gf,URL * u)
{

	nlock_task(gf->indicate_nlock);
	_insert_indicate(gf,u);
	unnlock_task(gf->indicate_nlock);

	return;
}
*/

INDICATE *
_copy_indicate(GBVIEW_FLAME * gf)
{
INDICATE * ret, * in, * in1;
	ret = 0;
	for ( in = gf->indicate ; in ; in = in->next ) {
		in1 = d_alloc(sizeof(*in1));
		*in1 = *in;
		copy_url(&in1->url,&in->url);
		in1->next = ret;
		ret = in1;
	}
	return ret;
}

/*
INDICATE *
copy_indicate(GBVIEW_FLAME * gf)
{
INDICATE * ret;
	nlock_task(gf->indicate_nlock);
	ret = _copy_indicate(gf);
	unnlock_task(gf->indicate_nlock);
	return ret;
}
*/

void
free_indicate(INDICATE * in)
{
INDICATE * in1;
	for ( ; in ; ) {
		in1 = in->next;
		free_url(&in->url);
		d_f_ree(in);
		in = in1;
	}
}


void
set_pointer_indicate(GBVIEW_FLAME * gf,int flags,URL * u)
{
INDICATE * in;
	if ( gf->status & GVFM_ZONBIE )
		return;
	lock_task(in_lock);
	if ( flags ) {
		in = _insert_indicate(gf,u);
		in->flags |= flags&(IF_COORDINATE|IF_OBJECT);
	}
	else {
		_delete_indicate(gf,u);
	}
	unlock_task(in_lock,"set_pointer_indicate");
}


void
_clear_info(GBVIEW_FLAME * gf)
{
INFO_LIST * il_1, *il_2;
	il_1 = gf->infolist;
	gf->infolist = 0;
	for ( ; il_1 ; ) {
		il_2 = il_1;
		il_1 = il_1->next;
		d_f_ree(il_2);
	}
}

void
clear_info(GBVIEW_FLAME * gf)
{
	wf_indicate_lock(gf);
	_clear_info(gf);
	wf_indicate_unlock(gf);
}

INFO_LIST *
_copy_infolist(GBVIEW_FLAME * gf)
{
INFO_LIST * il_1,*il_2,* ret;
	ret = 0;
	for ( il_1 = gf->infolist ; il_1 ; il_1 = il_1->next ) {
		il_2 = d_alloc(sizeof(*il_2));
		*il_2 = *il_1;
		il_2->next = ret;
		ret = il_2;
	}
	return ret;
}

INFO_LIST *
copy_infolist(GBVIEW_FLAME * gf)
{
INFO_LIST * ret;
	wf_indicate_lock(gf);
	ret = _copy_infolist(gf);
	wf_indicate_unlock(gf);
	return ret;
}

void
free_infolist(INFO_LIST * il)
{
INFO_LIST * il1;
	for ( ; il ; ) {
		il1 = il;
		il = il->next;
		d_f_ree(il1);
	}
}
/*
void
free_req_indicate(SYS_QUEUE * que)
{
INDICATE_T * n;
	for ( ; ; ) {
		n = delete_queue(que,0,0,0);
		if ( n == 0 )
			break;
		if ( n->h.key )
			d_f_ree(n->h.key);
		d_f_ree(n);
	}	
}
*/

void
indicate_info_card(GBVIEW_FLAME * gf,RESOURCE * r,OBJ * o)
{
INFO_LIST * il;

	wf_indicate_lock(gf);
	if ( (o->h.flags&OF_INFO_STS) == OF_INFO_FETCH &&
			 o->h.info_org == 0 )
		goto end;
	il = d_alloc(sizeof(*il));
	il->obj = o;
	il->flags = o->h.flags&(~OF_INFO_STS);
	il->code = o->h.code;
	il->r = r;
	il->func = 0;
	il->func_work = 0;
	switch ( (o->h.flags & OF_INFO_STS)  ) {
	case OF_INFO_FETCH:
		il->info = o->h.info_card;
		il->flags |= OF_INFO_FETCH;
		break;
	case OF_INFO_NOCHECK:
		il->info = 0;
		il->flags |= OF_INFO_PROC;
		o->h.flags &= ~OF_INFO_STS;
		o->h.flags |= OF_INFO_PROC;
		break;
	case OF_INFO_PROC:
		il->info = 0;
		il->flags |= OF_INFO_PROC;
		break;
	}
	il->next = gf->infolist;
	gf->infolist = il;
end:
	wf_indicate_unlock(gf);
}

L_CHAR *
get_info_url(XL_SEXP * info)
{
XL_SEXP * cmd;
XL_SYM_FIELD * sf;
	if ( get_type(info) != XLT_PAIR )
		return 0;
	cmd = car(info);
	if ( get_type(cmd) != XLT_SYMBOL )
		return 0;
	for (sf = cmd->symbol.field ; sf ; sf = sf->next ) {
		if ( l_strcmp(sf->name,l_string(std_cm,"uri")) == 0 ||
			l_strcmp(sf->name,l_string(std_cm,"url")) == 0 )
			return sf->data;
	}
	return 0;
}

typedef struct gf_status {
	GBVIEW_FLAME * 		gf;
	GBVIEW_STATUS		sts;
} GF_STATUS;

void
_click_event_tick(GF_STATUS * gfs)
{
	if ( gfs->gf->event )
		(*gfs->gf->event)(gfs->gf,ET_INFO,&gfs->sts);
	wf_free_status(&gfs->sts);
	d_f_ree(gfs);
}

void
click_info_url(GBVIEW_FLAME * gf,L_CHAR * url)
{
GF_STATUS * gfs;
	gfs = d_alloc(sizeof(*gfs));
	gfs->gf = gf;
	wf_init_status(&gfs->sts);
	gfs->sts.flags = SF_REFERENCE;
	gfs->sts.reference = ll_copy_str(url);
	new_tick(_click_event_tick,0,(int)gfs);
}

void
click_infolist(GBVIEW_FLAME * gf)
{
GF_STATUS * gfs;
	gfs = d_alloc(sizeof(*gfs));
	gfs->gf = gf;
	wf_init_status(&gfs->sts);
	gfs->sts.flags = SF_INFOLIST;
	gfs->sts.infolist = _copy_infolist(gf);
	new_tick(_click_event_tick,0,(int)gfs);
}

void
click_info_error(GBVIEW_FLAME * gf)
{
GF_STATUS * gfs;
	gfs = d_alloc(sizeof(*gfs));
	gfs->gf = gf;
	wf_init_status(&gfs->sts);
	gfs->sts.flags = SF_ERROR;
	new_tick(_click_event_tick,0,(int)&gfs);
}


void
ready_indicate(GBVIEW_FLAME * gf)
{
INFO_LIST * il;
XL_SEXP * s;
int i;
XL_SEXP * ss;
L_CHAR * url;


	if ( gf->infolist == 0 )
		return; 
	il = gf->infolist;
	i = 0;
	for ( ; il ; il = il->next ) {
		if ( (il->flags&OF_INFO_STS) != OF_INFO_FETCH ) {
			return;
		}
		i ++;
	}
	for ( il = gf->infolist; il ; il = il->next ) {
		if ( (il->flags&OF_INFO_SCHEME) == OF_INFO_URI ) {
			if ( get_type(il->info) != XLT_PAIR ) {
				click_info_error(gf);
				goto end;
			}
			ss = get_el(il->info,1);
			if ( get_type(ss) != XLT_STRING ) {
				click_info_error(gf);
				goto end;
			}
			click_info_url(gf,ss->string.data);
			goto end;
		}
		url = get_info_url(il->obj->h.info_org);
		if ( url ) {
			click_info_url(gf,url);
			goto end;
		}
	}
	click_infolist(gf);
end:
	_clear_info(gf);
}

void
free_info_req_queue(INFO_REQ_QUEUE * q)
{
	d_f_ree(q->h.key);
	d_f_ree(q);
}


void
insert_irq(GBVIEW_FLAME * gf,RESOURCE * r,int code,int cmd,WF_ID wfid)
{
INFO_REQ_QUEUE * ir;
char irq[20];
	ir = new_queue_node(sizeof(*ir));
	ir->code = code;
	ir->cmd = cmd;
if ( wfid == 0 )
printf("??????????????? insert_irq\n");
	ir->wfid = wfid;
	ir->gf = gf;
	ir->r = r;
	sprintf(irq,"gf%x",gf);
	ir->h.key = nl_copy_str(std_cm,irq);
	insert_queue(&r->draw_gb.ir_que,ir,0);
}


int
ir_cmp_code(INFO_REQ_QUEUE * q,int * code)
{
	if ( q->code == *code )
		return 0;
	return -1;
}

void
delete_irq(int rno,int code)
{
INFO_REQ_QUEUE * ir;
RESOURCE * r;
OBJ * o;
	r = search_resource_by_no(rno);
	if ( r == 0 )
		return;
	ir = delete_queue(&r->draw_gb.ir_que,ir_cmp_code,&code,0);
	if ( ir == 0 )
		return;
	free_info_req_queue(ir);
	o = search_obj(r,code);
	if ( o == 0 )
		return;
	if ( (o->h.flags&OF_INFO_STS) ==
			OF_INFO_PROC ) {
		o->h.flags &= ~OF_INFO_STS;
		o->h.flags |= OF_INFO_NOCHECK;
	}
}


int
invoke_indicate(GBVIEW_FLAME * gf,void (* func)(),void * func_work)
{
INFO_LIST * il;
int f;
	wf_indicate_lock(gf);
	f = 0;
	for ( il = gf->infolist ; il ; il = il->next ) {
		if ( (il->flags&OF_INFO_STS) != OF_INFO_FETCH ) {
			il->info = 0;
			il->func = func;
			il->func_work = func_work;
			insert_irq(gf,il->r,il->code,IRQ_INDICATE_CARD,0);
			f = -1;
		}
	}
	if ( f )
		goto end;
	ready_indicate(gf);
end:
	wf_indicate_unlock(gf);
	return f;
}

void
request_onmap_info(GBVIEW_FLAME * gf,RESOURCE * r,OBJ * o,WF_ID wfid)
{
	wf_indicate_lock(gf);
	if ( (o->h.flags&OF_INFO_STS) == OF_INFO_NOCHECK ) {
		o->h.flags &= ~OF_INFO_STS;
		o->h.flags |= OF_INFO_PROC;
		insert_irq(gf,r,o->h.code,IRQ_INDICATE_ONMAP,wfid);
	}
	wf_indicate_unlock(gf);
}


void
_indicate_onmap(GBVIEW_FLAME * gf,int draw_flag,
	WF_ID wfid,RESOURCE * r,OBJ * o,GB_POINT ind_ptr)
{
GB_RECT rect;
int i;
int width,height;
int size;
PIC pic;
PIC_ELEMENT * pe;
int sub;

	switch ( (o->h.flags & OF_INFO_STS) ) {
	case OF_INFO_NOCHECK:
		if ( r->h.entry.server == 0 ) {
			o->h.flags &= ~OF_INFO_STS;
			o->h.flags |= OF_INFO_FETCH;
			goto fetch;
		}
		request_onmap_info(gf,r,o,wfid);
		rect.tl = rect.br = ind_ptr;
		wf_insert_si(
			gf,
			ISI_INSERT,
			wfid,
			r->h.no,
			(o->h.code&MAIN_CODE)|INFO_SUBCODE,
			0,
			&rect,
			0,
			0,
			0,
			0);
		return;
	case OF_INFO_PROC:
		return;
	case OF_INFO_FETCH:
	fetch:
		if ( o->h.info_org == 0 )
			return;
		if ( wf_insert_si(
				gf,
				ISI_INFO,
				wfid,
				r->h.no,
				(o->h.code&MAIN_CODE)|INFO_SUBCODE,
				0,
				&rect,
				0,
				0,
				0,
				0) == 1 ) {
			if ( rect.tl.x == rect.br.x ) {
				ind_ptr = rect.tl;
				break;
			}
			return;
		}
		else if ( draw_flag == 1 )
			break;
		else	return;
	default:
		er_panic("indicate_onmap(1)");
	}

	switch ( (o->h.flags & OF_INFO_SCHEME) ) {
	case OF_INFO_ERROR:
/*
		fprintf(stderr,"indicate_onmap error\n");
*/
		break;;
	default:
		break;
	}
	if ( o->h.info_onmap == 0 )
		return;
	if ( o->h.onmap_resolution &&
			o->h.onmap_resolution > o->h.req_resolution )
		return;
/*
ss_printf("onmap = %i %i ",
r->h.no,
o->h.code>>8);
print_sexp(s_stdout,o->h.info_onmap,0);
ss_printf("\n");
*/
	pic = get_onmap_string_pic(o->h.info_onmap);
	if ( pic.list == 0 ){
		o->h.info_onmap = 0;
		free_pic(pic);
		return;
	}
	ind_ptr.x = (int)ind_ptr.x;
	ind_ptr.y = (int)ind_ptr.y;
	rect.tl.x = ind_ptr.x + pic.rect.tl.x;
	rect.tl.y = ind_ptr.y + pic.rect.tl.y;
	rect.br.x = ind_ptr.x + pic.rect.br.x;
	rect.br.y = ind_ptr.y + pic.rect.br.y;
	width = pic.rect.br.x - pic.rect.tl.x;
	height = pic.rect.br.y - pic.rect.tl.y;
	if ( wf_space_check_si(
			gf,
			wfid,r->h.no,(o->h.code&MAIN_CODE)|INFO_SUBCODE,
				0,&rect,10) == 0 )
		goto ok;
	rect.tl.y -= height;
	rect.br.y -= height;
	ind_ptr.y -= height;
	if ( wf_space_check_si(
			gf,
			wfid,r->h.no,(o->h.code&MAIN_CODE)|INFO_SUBCODE,
				0,&rect,10) == 0 )
		goto ok;
	rect.tl.y += 2*height;
	rect.br.y += 2*height;
	ind_ptr.y += 2*height;
	if ( wf_space_check_si(
			gf,
			wfid,r->h.no,(o->h.code&MAIN_CODE)|INFO_SUBCODE,
				0,&rect,10) == 0 )
		goto ok;
	free_pic(pic);
	return;
ok:
	sub = 0;
	for ( pe = pic.list ; pe ; pe = pe->next ) {
	int flags;
		rect.tl.x = pe->p.r.tl.x + ind_ptr.x;
		rect.br.x = pe->p.r.br.x + ind_ptr.x;
		rect.tl.y = pe->p.r.tl.y + ind_ptr.y;
		rect.br.y = pe->p.r.br.y + ind_ptr.y;
		if ( pe->flags & PLF_ANCOR )
			flags = SIF_ANCOR;
		else	flags = 0;
		wf_insert_si(
			gf,
			ISI_INSERT,
			wfid,
			r->h.no,
			(o->h.code&MAIN_CODE)|INFO_SUBCODE,
			sub++,
			&rect,
			pe->data,
			pe->alpha,
			flags,
			pe->ref);
		pe->data = 0;
		pe->alpha = 0;
	}
	free_pic(pic);
}

void
indicate_onmap(GBVIEW_FLAME * gf,int draw_flag,
	WF_ID wfid,RESOURCE * r,OBJ * o,GB_POINT ind_ptr)
{
	wf_iom_lock();
	_indicate_onmap(gf,draw_flag,wfid,r,o,ind_ptr);
	wf_iom_unlock();
}

void
insert_indicate_info(GBVIEW_FLAME * gf,
	RESOURCE * r,int code,int flags,XL_SEXP * data)
{
INFO_LIST* il;
	wf_indicate_lock(gf);
	il = gf->infolist;
	for ( ; il ; il = il->next ) {
		if ( il->r != r )
			continue;
		if ( il->code != code )
			continue;
		il->info = data;
		il->flags = (flags&(~OF_INFO_STS))|OF_INFO_FETCH;
		if ( il->func )
			(*il->func)(il->func_work);
		break;
	}
	wf_indicate_unlock(gf);
}

void
formating_info(RESOURCE * r,OBJ * o)
{
XL_SEXP * u, * anc;
XL_SEXP * sym;

	switch ( (o->h.flags&OF_INFO_SCHEME) ) {
	case OF_INFO_URI:
		u = get_el(o->h.info_org,1);
		if ( get_type(u) != XLT_STRING ) {
			o->h.flags &= ~OF_INFO_SCHEME;
			o->h.flags |= OF_INFO_ERROR;
			o->h.info_card =
				n_get_string("format-error URI");
		}
		anc = get_symbol(l_string(std_cm,"A"));
		set_attribute(anc,
			l_string(std_cm,"HREF"),
			u->string.data);
		o->h.info_card = List(anc,u,-1);
		break;
	case OF_INFO_XML:
	case OF_INFO_NULL:
		o->h.info_card = get_card_info(r,o->h.info_org);
		o->h.info_onmap = get_onmap_info(
			r,
			o->h.info_org,
			&o->h.onmap_resolution);
		if ( get_type(o->h.info_onmap) == XLT_ERROR ) {
			fflush(stdout);
			s_printf(s_stdout,"ERROR onmap format ");
			print_sexp(s_stdout,o->h.info_onmap,0);
			s_printf(s_stdout,"\n");
		}
		if ( get_type(o->h.info_card) == XLT_ERROR ) {
			fflush(stdout);
			s_printf(s_stdout,"ERROR card format ");
			print_sexp(s_stdout,o->h.info_card,0);
			s_printf(s_stdout,"\n");
		}
		break;
	case OF_INFO_HTML:
	default:
		o->h.info_card = o->h.info_org;
		o->h.info_onmap = 0;
		break;
	}
	o->h.name = 0;
	if ( get_type(o->h.info_org) != XLT_PAIR )
		return;
	sym = car(o->h.info_org);
	if ( get_type(sym) != XLT_SYMBOL )
		return;
	o->h.name = get_sf_attribute(sym->symbol.field,
		l_string(std_cm,"name"));
}

int
setup_info(GBVIEW_FLAME * gf,WF_ID wfid,RESOURCE * r,XL_SEXP * info)
{
XL_SEXP * s, * t, * u, * v;
XL_SYM_FIELD * sf;
L_CHAR * sts;
int code;
int flags;
XL_SEXP * info_org;
OBJ * o;
XL_SEXP * card_data;
int ind;
char * err_buf;
	ind = 0;
	err_buf = d_alloc(100);

	for ( ; get_type(info) == XLT_PAIR ; info = cdr(info) ) {
		s = car(info);
		if ( get_type(s) != XLT_PAIR )
			continue;
		t = car(s);
		if ( get_type(t) != XLT_SYMBOL )
			continue;
		if ( l_strcmp(t->symbol.data,l_string(std_cm,"i")) )
			continue;
		sts = 0;
		for ( sf = t->symbol.field ; sf ; sf = sf->next ) {
			if ( l_strcmp(sf->name,l_string(std_cm,"sts"))
					== 0 ) {
				sts = sf->data;
			}
			else if ( l_strcmp(sf->name,l_string(std_cm,"code"))
					== 0 ) {
				sscanf(n_string(std_cm,sf->data),
					"%i",&code);
			}
		}
		if ( sts == 0 ) {
			flags = OF_INFO_ERROR;
			sprintf(err_buf,"unknown-error %i\n",code);
			info_org = n_get_string(err_buf);
		}
		else if ( l_strcmp(sts,l_string(std_cm,"ok")) ) {
			flags = OF_INFO_ERROR;
			info_org = get_string(sts);
		}
		else {

			info_org = 0;
			for ( s = cdr(s) ; get_type(s) == XLT_PAIR;
					s = cdr(s) ) {
				u = car(s);
				if ( get_type(u) != XLT_PAIR )
					continue;
				v = car(u);
				if ( get_type(v) != XLT_SYMBOL )
					continue;
				if ( l_strcmp(v->symbol.data,
					l_string(std_cm,"information")) )
					continue;
				info_org = u;
				break;
			}
			if ( info_org == 0 ) {
				flags = OF_INFO_ERROR;
				sprintf(err_buf,"format-error(no-info) %i",
						code);
				info_org = n_get_string
					(err_buf);
			}
			else {
				for ( sf = v->symbol.field ; sf;
					sf = sf->next ) {

					if ( l_strcmp(
						sf->name,
						l_string(std_cm,"scheme"))
						== 0 )
						break;
				}
				if ( sf == 0 ) {
					flags = OF_INFO_ERROR;
					sprintf(err_buf,
						"format-error(scheme) %i",
						code);
					info_org = n_get_string
						(err_buf);
				
				}
				else if ( l_strcmp(sf->data,
					l_string(std_cm,"null")) == 0 ) {
					flags = OF_INFO_NULL;
				}
				else if ( l_strcmp(sf->data,
					l_string(std_cm,"uri")) == 0 ) {
					flags = OF_INFO_URI;
				}
				else if ( l_strcmp(sf->data,
					l_string(std_cm,"html")) == 0 ) {
					flags = OF_INFO_HTML;
				}
				else {
					flags = OF_INFO_XML;
				}
			}
		}
		o = search_obj(r,code);
		if ( o == 0 ) {
			flags = OF_INFO_ERROR;
			sprintf(err_buf,"no-object %i",code);
			card_data = n_get_string
				(err_buf);
		}
		else {
			r->draw_gb.flags |= DGF_INFO;
			o->h.flags &= ~OF_INFO_SCHEME;
			o->h.flags |= flags&(~OF_INFO_STS);
			o->h.info_org = info_org;
			formating_info(r,o);
			card_data = o->h.info_card;

			wf_iom_lock();
			o->h.flags &= ~OF_INFO_STS;
			o->h.flags |= OF_INFO_FETCH;
			if ( o->h.flags & OF_ONMAP_REQ ) {
			GB_POINT ptr;
				o->h.flags &= ~OF_ONMAP_REQ;
				ptr.x = ptr.y = 0;
				_indicate_onmap(gf,0,wfid,r,o,ptr);
				ind = 1;
			}
			wf_iom_unlock();
		}
		insert_indicate_info(gf,r,code,flags,card_data);
	}
/*
	lock_task(indicate_lock);
	ready_indicate();
	unlock_task(indicate_lock,"setup_info");
*/
	d_f_ree(err_buf);
	return ind;
}

XL_SEXP *
setup_info_cmd(GBVIEW_FLAME * gf,WF_ID wfid,RESOURCE * r,int code,XL_SEXP * info)
{
XL_SEXP  * v;
XL_SYM_FIELD * sf;
int flags;
XL_SEXP * info_org;
OBJ * o;
XL_SEXP * card_data;


	info_org = info;
	v = car(info);
	for ( sf = v->symbol.field ; sf;
		sf = sf->next ) {
			if ( l_strcmp(
			sf->name,
			l_string(std_cm,"scheme"))
			== 0 )
			break;
	}
	if ( sf == 0 ) {
		flags = OF_INFO_ERROR;
		goto scheme_error;
	}
	else if ( l_strcmp(sf->data,
		l_string(std_cm,"null")) == 0 ) {
		flags = OF_INFO_NULL;
	}
	else if ( l_strcmp(sf->data,
		l_string(std_cm,"uri")) == 0 ) {
		flags = OF_INFO_URI;
	}
	else if ( l_strcmp(sf->data,
		l_string(std_cm,"html")) == 0 ) {
		flags = OF_INFO_HTML;
	}
	else {
		flags = OF_INFO_XML;
	}

	o = search_obj(r,code);
	if ( o == 0 ) {
		flags = OF_INFO_ERROR;
		goto no_obj;
	}
	else {
		o->h.flags &= ~OF_INFO_SCHEME;
		o->h.flags |= flags&(~OF_INFO_STS);
		o->h.info_org = info_org;
		formating_info(r,o);
		card_data = o->h.info_card;

		wf_iom_lock();
		o->h.flags &= ~OF_INFO_STS;
		o->h.flags |= OF_INFO_FETCH;
		if ( o->h.flags & OF_ONMAP_REQ ) {
		GB_POINT ptr;
			o->h.flags &= ~OF_ONMAP_REQ;
			ptr.x = ptr.y = 0;
			if ( wfid )
				_indicate_onmap(gf,0,wfid,r,o,ptr);
		}
		wf_iom_unlock();
	}
	if ( gf )
		insert_indicate_info(gf,r,code,flags,card_data);
/*
	lock_task(indicate_lock);
	ready_indicate();
	unlock_task(indicate_lock,"setup_info");
*/
	return 0;
scheme_error:
	return get_error(
		info->h.file,
		info->h.line,
		XLE_PROTO_INV_PARAM,
		l_string(std_cm,"information"),
		list(n_get_string("attribute(scheme) is required"),0));
no_obj:
	return get_error(
		info->h.file,
		info->h.line,
		XLE_PROTO_UNDEF_NAME,
		l_string(std_cm,"information"),
		List(n_get_string("no object code = "),
			get_integer(code,0),
			-1));
}

typedef struct check_irq_t {
	GBVIEW_FLAME * 	gf;
	WF_ID		wfid;
} CHECK_IRQ_T;

int
cmp_check_irq(SYS_QUEUE * q,INFO_REQ_QUEUE * ir,CHECK_IRQ_T *w)
{
	if ( ir->gf != w->gf )
		return -1;
	if ( w->wfid == 0 )
		return 0;
	if ( ir->wfid == w->wfid )
		return 0;
	return -1;
}


int
check_irq(int ses,GBVIEW_FLAME * gf,RESOURCE * r)
{
XL_SEXP * query, * code;
INFO_REQ_QUEUE * ir2;
XL_SEXP * ret,* all;
int er;
XL_SEXP * gvr;
char buf[32];
int i;
WF_ID wfid;
int cnt;
int req;
OBJ * o;
L_CHAR * f;
int setup_ret;
CHECK_IRQ_T w;
int wait_flag;

	wf_lock(gf);
	ZONBIE_CHECK(gf,wf_unlock,1)
	wf_unlock(gf);
	gc_push(0,0,"check_irq");
	query = 0;
	req = 0;
	w.gf = gf;
	w.wfid = 0;

	wait_flag = -5;
	for ( cnt = 0 ; cnt < IRQ_MAX ; cnt ++ ) {
		ir2 = delete_queue(&r->draw_gb.ir_que,cmp_check_irq,&w,
					wait_flag);
		wait_flag = 0;
		if ( ir2 == 0 )
			break;
		if ( ir2->cmd ) {
			code = get_integer(ir2->code,0);
			query = cons(code,query);
			req ++;
		}
		else {
			o = search_obj(r,ir2->code);
			if ( o && (o->h.flags&OF_INFO_STS) ==
					OF_INFO_PROC ) {
				o->h.flags &= ~OF_INFO_STS;
				o->h.flags |= OF_INFO_NOCHECK;
			}
		}
		w.wfid = wfid = ir2->wfid;
		free_info_req_queue(ir2);
	}
	if ( req == 0 ) {
		gc_pop(0,0);
		return 1;
	}

	query = cons(
		get_string(f=get_url_filepath(&r->h.target)),
		query);
	d_f_ree(f);
	query = cons(
		get_symbol(l_string(std_cm,"GetInfo")),
		query);
	er = 0;
	set_inc_status(r,RS_LOAD);
/*
nprintf("ind 1 (%i) %i %i\n",get_tid(),os_test1,os_test2);
print_tno("ind");
os_test2 = 1;
*/
	ret = remote_session(
		gblisp_top_env0,
		ses,
		&r->h.target,
		l_string(std_cm,"gbpdbp"),
		l_string(std_cm,"user"),
		l_string(std_cm,"Get"),
		List(query,-1),
		0,0,0);
/*
printf("ind 2 %i %i\n",os_test1,os_test2);
os_test2 = 0;
*/
	switch ( get_type(ret) ) {
	case XLT_ERROR:
		fprintf(stderr,"pdbp getinfo error ");
		print_sexp(s_stderr,ret,0);

		set_inc_status_error(r,ret);

		fprintf(stderr,"\n");
		er = -1;
		break;
	case XLT_PAIR:
		set_inc_status(r,RS_IDLE);
		for ( all = ret ; get_type(all) == XLT_PAIR ; all = cdr(all) );
		break;
	case XLT_NULL:
		set_inc_status(r,RS_IDLE);
		er = -2;
		goto end;
	default:

		set_inc_status_error(r,
			get_error(
				0,
				0,
				XLE_SEMANTICS_TYPE_MISSMATCH,
				l_string(std_cm,"Get(pdbp)"),
			n_get_string("server return invalid type data")));

		fprintf(stderr,"pdbp GetInfo: type missmatch return\n");
		print_sexp(s_stderr,ret,PF_RAW_DISABLE);
		fprintf(stderr,"\n");
		er = -1;
		goto end;
	}
	lock_pdb_lock(r,0);
	setup_ret = setup_info(gf,wfid,r,ret);
	unlock_pdb_lock(r);
	if ( setup_ret )
		_wf_set_redraw(gf);
end:
	gc_pop(0,0);
	return er;
}

typedef struct indicate_info_task_check_t {
	GBVIEW_FLAME *		gf;
	L_CHAR *		key;
} INDICATE_INFO_TASK_CHECK_T;

int
indicate_info_task_check(
	SYS_QUEUE * q,
	INFO_REQ_QUEUE * ir,
	INDICATE_INFO_TASK_CHECK_T * w)
{
	if ( w->gf )
		return -1;
	if ( l_strcmp(ir->h.key,w->key) )
		return -1;
	w->gf = ir->gf;
	return 0;
}


void
indicate_info_task(TKEY d)
{
XL_INTERPRETER * xli;
int ses;
int i;
int f;
L_CHAR * key;
GBVIEW_FLAME * gf;
SYS_QUEUE * que;
RESOURCE * r;
INDICATE_INFO_TASK_CHECK_T w;

set_cpu_thr_type(5);


	que = (SYS_QUEUE*)GET_TKEY(d);
	key = touch_qkey(que);
	r = que->work;
	w.gf = 0;
	w.key = key;
	check_queue(que,indicate_info_task_check,&w);
	if ( w.gf == 0 )
		goto end;
	gf = w.gf;

	xli = new_xl_interpreter();
	xli->a_type = XLA_SELF;
	setup_i(xli);
	ses = open_session(SEST_OPTIMIZE);

	for ( ; ; ) {
		if ( check_irq(ses,gf,r) == 1 )
			break;
	}

	close_session(ses);
	close_self_interpreter();
end:
	release_qkey(que,key);
}


