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



#define IRQ_MAX		20

extern GBVIEW_ENV env;
extern RESOURCE ** res_entry_hash_table;

void indicate_info_task();

SEM indicate_lock,irq_lock;
SEM iom_lock;
int irq_cnt;
int indicate_cnt;
NESTED_LOCK * indicate_nlock;

void
init_indicate()
{
	indicate_lock = new_lock(LL_INDICATE);
	irq_lock = new_lock(LL_IRQ);
	iom_lock = new_lock(LL_ONMAP);
	indicate_nlock = new_nlock();
	create_task(indicate_info_task,0,PRI_FETCH_STRONG);
}





void
gc_indicate()
{
INFO_LIST * il;
	for ( il = env.infolist ; il ; il = il->next )
		gc_gb_sexp(il->info);
}



INDICATE *
_search_indicate(URL * u)
{
INDICATE * in;
	for ( in = env.indicate ;
		in &&
		url_cmp(&in->url,u);
		in = in->next );
	return in;
}

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

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


void
insert_indicate(URL * u)
{

	nlock_task(indicate_nlock);
	_insert_indicate(u);
	unnlock_task(indicate_nlock);

	return;
}


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

INDICATE *
copy_indicate()
{
INDICATE * ret;
	nlock_task(indicate_nlock);
	ret = _copy_indicate();
	unnlock_task(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(int flags,URL * u)
{
INDICATE * in;
	nlock_task(indicate_nlock);
	if ( flags ) {
		in = _insert_indicate(u);
		in->flags |= flags&(IF_COORDINATE|IF_OBJECT);
	}
	else {
		_delete_indicate(u);
	}
	unnlock_task(indicate_nlock);
}


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

void
clear_info()
{
	lock_task(indicate_lock);
	_clear_info();
	unlock_task(indicate_lock,"clear_info");
}

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

INFO_LIST *
copy_infolist()
{
INFO_LIST * ret;
	lock_task(indicate_lock);
	ret = _copy_infolist();
	unlock_task(indicate_lock,"copy_infolist");
	return ret;
}

void
free_infolist(INFO_LIST * il)
{
INFO_LIST * il1;
	for ( ; il ; ) {
		il1 = il;
		il = il->next;
		d_f_ree(il1);
	}
}

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

	lock_task(indicate_lock);
	if ( (o->h.flags&OF_INFO_STS) == OF_INFO_FETCH &&
			 o->h.info_org == 0 )
		goto end;
	il = d_alloc(sizeof(*il),47);
	il->obj = o;
	il->flags = o->h.flags&(~OF_INFO_STS);
	il->code = o->h.code;
	il->r = r;
	il->func = 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 = env.infolist;
	env.infolist = il;
end:
	unlock_task(indicate_lock,"indicate_info_card");
}

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;
}


void
_click_event_tick(GBVIEW_STATUS * sts)
{
	if ( env.event )
		(*env.event)(ET_INFO,sts);
	wf_free_status(sts);
	d_f_ree(sts);
}

void
click_info_url(L_CHAR * url)
{
GBVIEW_STATUS * sts;
	sts = d_alloc(sizeof(*sts),14);
	wf_init_status(sts);
	sts->flags = SF_REFERENCE;
	sts->reference = ll_copy_str(url,15);
	new_tick(_click_event_tick,0,(int)sts);
}

void
click_infolist()
{
GBVIEW_STATUS * sts;
	sts = d_alloc(sizeof(*sts),14);
	wf_init_status(sts);
	sts->flags = SF_INFOLIST;
	sts->infolist = _copy_infolist();
	new_tick(_click_event_tick,0,(int)sts);
}

void
click_info_error()
{
GBVIEW_STATUS * sts;
	sts = d_alloc(sizeof(*sts),125);
	wf_init_status(sts);
	sts->flags = SF_ERROR;
	new_tick(_click_event_tick,0,(int)sts);
}


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


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




void
insert_irq(RESOURCE * r,int code,int cmd,WF_ID wfid)
{
INFO_REQ_QUEUE * ir;
	lock_task(irq_lock);
	ir = d_alloc(sizeof(*ir),235);
	ir->code = code;
	ir->cmd = cmd;
if ( wfid == 0 )
printf("??????????????? insert_irq\n");
	ir->wfid = wfid;
	ir->next = r->draw_gb.ir_queue;
	r->draw_gb.ir_queue = ir;
	irq_cnt ++;
	unlock_task(irq_lock,"insert_irq");
}

void
delete_irq(int rno,int code)
{
INFO_REQ_QUEUE * ir;
RESOURCE * r;
OBJ * o;
	lock_task(irq_lock);
	r = search_resource_by_no(rno);
	if ( r == 0 )
		return;
	for ( ir = r->draw_gb.ir_queue;
		ir ; ir = ir->next ) {
		if ( ir->code == code ) {
			ir->cmd = 0;
			break;
		}
	}
	unlock_task(irq_lock,"delete_irq");
	o = search_obj(r,code);
	if ( o == 0 )
		return;
}


int
invoke_indicate(void (* func)())
{
INFO_LIST * il;
int f;
	lock_task(indicate_lock);
	f = 0;
	for ( il = env.infolist ; il ; il = il->next ) {
		if ( (il->flags&OF_INFO_STS) != OF_INFO_FETCH ) {
			il->info = 0;
			il->func = func;
			insert_irq(il->r,il->code,IRQ_INDICATE_CARD,0);
			wakeup_task((int)init_indicate);
			f = -1;
		}
	}
	if ( f )
		goto end;
	ready_indicate();
end:
	unlock_task(indicate_lock,"invoke_indicate");
	return f;
}

void
request_onmap_info(RESOURCE * r,OBJ * o,WF_ID wfid)
{
	lock_task(indicate_lock);
	if ( (o->h.flags&OF_INFO_STS) == OF_INFO_NOCHECK ) {
		o->h.flags &= ~OF_INFO_STS;
		o->h.flags |= OF_INFO_PROC;
		insert_irq(r,o->h.code,IRQ_INDICATE_ONMAP,wfid);
		wakeup_task((int)init_indicate);
	}
	unlock_task(indicate_lock,"req_onmap_info");
}


void
_indicate_onmap(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(r,o,wfid);
		rect.tl = rect.br = ind_ptr;
		wf_insert_si(
			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(
				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;
/*
if ( r->h.no == 196617 ){
printf("onmap = %i %i ",
r->h.no,
o->h.code>>8);
print_sexp(s_stdout,o->h.info_onmap,0);
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(
			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(
			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(
			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;
change_memtype(pe->data,1508);
		wf_insert_si(
			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(int draw_flag,
	WF_ID wfid,RESOURCE * r,OBJ * o,GB_POINT ind_ptr)
{
	lock_task(iom_lock);
	_indicate_onmap(draw_flag,wfid,r,o,ind_ptr);
	unlock_task(iom_lock,"indicate_onmap");
}

void
insert_indicate_info(RESOURCE * r,int code,int flags,XL_SEXP * data)
{
INFO_LIST* il;
	lock_task(indicate_lock);
	il = env.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)();
		break;
	}
	unlock_task(indicate_lock,"insert_indicate_info");
}

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(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,123);

	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;

			lock_task(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(0,wfid,r,o,ptr);
				ind = 1;
			}
			unlock_task(iom_lock,"setup_info");
		}
		insert_indicate_info(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(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;

		lock_task(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(0,wfid,r,o,ptr);
		}
		unlock_task(iom_lock,"setup_info");
	}
	insert_indicate_info(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));
}


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

	lock_task(indicate_lock);
	lock_task(irq_lock);
	if ( r->draw_gb.ir_queue == 0 ) {
		unlock_task(irq_lock,"check_irq");
		unlock_task(indicate_lock,"check_irq");
		return 0;
	}
	ir2 = ir1 = r->draw_gb.ir_queue;
	gc_push(0,0,"check_irq");
	query = 0;
	req = 0;
	for ( cnt = 0 ; ir1 && cnt < IRQ_MAX ; cnt ++ ) {
		irq_cnt --;
		ir2 = ir1;
		ir1 = ir1->next;
		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;
			}
		}
		wfid = ir2->wfid;
		d_f_ree(ir2);
	}
	r->draw_gb.ir_queue = ir1;
	unlock_task(irq_lock,"check_irq");
	unlock_task(indicate_lock,"check_irq");
	if ( req == 0 )
		return 0;

	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);
		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;
	}
	if ( setup_info(wfid,r,ret) ) {
		_wf_set_redraw();
	}
end:
	gc_pop(0,0);
	return er;
}


void
indicate_info_task()
{
XL_INTERPRETER * xli;
RESOURCE * r;
int ses;
int i;
int f;

printf("indicate task ****  %i\n",get_tid());

set_cpu_thr_type(5);


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

	for ( ; ; ) {
		lock_task(indicate_lock);
		if ( irq_cnt == 0 ) {
/*
printf("indicate sleep %i\n",get_tid());
*/
			sleep_task((int)init_indicate,indicate_lock);
/*
printf("indicate wakeup %i\n",get_tid());
*/
		}
		else {
			unlock_task(indicate_lock,"indicate_info_task");
		}
		for ( i = 0 ; i < RES_HASH_SIZE ; i ++ ) {
			r = res_entry_hash_table[i];
			for ( ; r ; r = r->h.entry_next ) {
				if ( r->h.type != RT_DRAW_GB )
					continue;
				check_irq(ses,r);
			}
		}
	}
}


