#include "..\xcommon.h"
#include "..\chs_ultd\feigenbm.h"
#include <math.h>
#include <tos.h>
#include <string.h>

int errno;				/* damit der linker nicht motzt;
							sonst in pc_start deklariert */

extern	XCHAOS xfch;		/* die definition kommt weiter unten */
int		fgbm_nr;			/* nummer der routine in chaos */

COMMON	*common;			/* zeiger fr die routinen von chaos */

/*------------------------------------------------------------------------------
		initialisierungsroutine,
			mu nach linken am anfang des text-segmentes stehen,
			d.h. im quelltext ganz vorne
------------------------------------------------------------------------------*/
XCHAOS *ret_chaos(COMMON *com)
{
	common=com;				/* merke com */
	return &xfch;				/* gib eigene routinen zurck */
}

/*------------------------------------------------------------------------------

	parameterstrukturen

------------------------------------------------------------------------------*/
/*
		bildparameter
*/
typedef struct
{
	int flag;				/* 0 quer, 1 hoch */

	int n1;				/* iterationen vor plot */
	int n2;				/* iterationen fr plot */
	int dn;				/* iterationen zwischen zwei plot's */

	long time;			/* rechenzeit */

	double r_min;			/* definition des rechteckes */
	double r_max;
	double y_min;
	double y_max;

	double y0;			/* startwert fr iteration */

} FEIGENBAUM;

/*
		bild(er)parameter fr neu bilder
*/
typedef struct
{
	FEIGENBAUM start;		/* parameter des ersten bildes */
	FEIGENBAUM end;		/* parameter des letzten bildes */
	int change[8];			/* interpolationstypen */
	FEIGENBAUM act;		/* speicherplatz fr parameter des aktuellen bildes */
} FGBM_PAR;

/*
		einstellungen
*/
typedef struct
{
	int set;
	FEIGENBAUM start;
	FEIGENBAUM end;
	int change[8];
	int size;
	int anzahl;
	int color;
	char name[10];
} FGBM_SET;


/*------------------------------------------------------------------------------

	globale variable

------------------------------------------------------------------------------*/
static OBJECT *fg_par_ad,*fg_show_ad,*icons;	/* dialogboxen */
FGBM_SET fgbm_set;						/* einstellungen */

/*------------------------------------------------------------------------------

		parameter einlesen

------------------------------------------------------------------------------*/
/*
		schreibe standartvoreinstellungen nach set
*/
static void def_fgparam(FGBM_SET *set)
{
int i;
static FEIGENBAUM def_start={0,100,100,1,0l,
						2.0,4.0,0.0,1.0,0.5};
	set->start=def_start;
	set->end=def_start;

	for ( i=0; i<8; i++ )
		set->change[i]=1;

	set->anzahl=1;		/* 1 bild */
	set->size=S_BIG;	/* groe bilder */
	set->color=0;		/* normal */
	strcpy(set->name,"FGBAUM");
}

/*
		indizes der dialogbox-elemente
*/
		/* interpolations-typen */
static char *ch_txt[]={"-","0","+"};
		/* button fr interpolation */
static int fb_ch[]={FB_RMIN,FB_RMAX,FB_XMIN,FB_XMAX,FB_X0,FB_N1,FB_N2,FB_DN};
		/* tedinfo's der start-parameter */
static int fb_1[]={FB_RMIN1,FB_RMAX1,FB_XMIN1,FB_XMAX1,FB_X0_1,FB_N1_1,FB_N2_1,FB_DN_1};
		/* tedinfo's der end-parameter */
static int fb_2[]={FB_RMIN2,FB_RMAX2,FB_XMIN2,FB_XMAX2,FB_X0_2,FB_N1_2,FB_N2_2,FB_DN_2};

/*
		belege dialogbox vor
*/
static void set_fgparam(FGBM_SET *set,FGBM_PAR *fgbm)
{
int i;

	if ( !set->set )	/* keine einstellungen? -> standartvoreinstellungen */
		def_fgparam(set);

	strcpy(objc_tedstr(fg_par_ad,FB_NAME),set->name);			/* objektname */
	common->sprintf(objc_tedstr(fg_par_ad,FB_ANZ),"%4d",set->anzahl);	/* anzahl */
	objc_unselect(fg_par_ad,FB_SMALL);						/* gre */
	objc_unselect(fg_par_ad,FB_MED);
	objc_unselect(fg_par_ad,FB_BIG);
	objc_select(fg_par_ad,FB_SMALL+set->size);

											/* parameter links */
	common->write_dbl(objc_tedstr(fg_par_ad,FB_RMIN1),set->start.r_min,15,11);
	common->write_dbl(objc_tedstr(fg_par_ad,FB_RMAX1),set->start.r_max,15,11);
	common->write_dbl(objc_tedstr(fg_par_ad,FB_XMIN1),set->start.y_min,15,11);
	common->write_dbl(objc_tedstr(fg_par_ad,FB_XMAX1),set->start.y_max,15,11);
	common->write_dbl(objc_tedstr(fg_par_ad,FB_X0_1),set->start.y0,15,11);
	common->sprintf(objc_tedstr(fg_par_ad,FB_N1_1),"%4d",set->start.n1);
	common->sprintf(objc_tedstr(fg_par_ad,FB_N2_1),"%4d",set->start.n2);
	common->sprintf(objc_tedstr(fg_par_ad,FB_DN_1),"%3d",set->start.dn);

											/* parameter rechts */
	common->write_dbl(objc_tedstr(fg_par_ad,FB_RMIN2),set->end.r_min,15,11);
	common->write_dbl(objc_tedstr(fg_par_ad,FB_RMAX2),set->end.r_max,15,11);
	common->write_dbl(objc_tedstr(fg_par_ad,FB_XMIN2),set->end.y_min,15,11);
	common->write_dbl(objc_tedstr(fg_par_ad,FB_XMAX2),set->end.y_max,15,11);
	common->write_dbl(objc_tedstr(fg_par_ad,FB_X0_2),set->end.y0,15,11);
	common->sprintf(objc_tedstr(fg_par_ad,FB_N1_2),"%4d",set->end.n1);
	common->sprintf(objc_tedstr(fg_par_ad,FB_N2_2),"%4d",set->end.n2);
	common->sprintf(objc_tedstr(fg_par_ad,FB_DN_2),"%3d",set->end.dn);

											/* interpolationstypen */
	for( i=0; i<8; i++ ) {
		objc_spec(fg_par_ad,fb_ch[i])=ch_txt[set->change[i]];
		fgbm->change[i]=set->change[i];
	}

											/* bildtyp: normal/quer */
	objc_select(fg_par_ad,FB_NRM+set->start.flag);
	objc_unselect(fg_par_ad,FB_QUR-set->start.flag);

											/* darstellung (normal/invers) */
	objc_unselect(fg_par_ad,FB_INV+set->color);
	objc_select(fg_par_ad,FB_NORM-set->color);
}

/*
		parameter aus dialogbox auslesen
*/
static int get_fgparam(FGBM_PAR *param,X_PARAM *x_param)
{
	x_param->xor_offset=0;								/* kein xor offset, xor bringt eh nichts */

	strcpy(x_param->name,objc_tedstr(fg_par_ad,FB_NAME));		/* name */
	common->sscanf(objc_tedstr(fg_par_ad,FB_ANZ),"%d",&x_param->anzahl);/* anzahl */
	if ( objc_selected(fg_par_ad,FB_SMALL) )				/* gre */
		x_param->size=S_SMALL;
	else if ( objc_selected(fg_par_ad,FB_MED) )
		x_param->size=S_MID;
	else
		x_param->size=S_BIG;
												/* startparameter */
	common->sscanf(objc_tedstr(fg_par_ad,FB_RMIN1),"%lf",&param->start.r_min);
	common->sscanf(objc_tedstr(fg_par_ad,FB_RMAX1),"%lf",&param->start.r_max);
	if ( param->start.r_min>param->start.r_max )
		return FB_RMIN1;
	common->sscanf(objc_tedstr(fg_par_ad,FB_XMIN1),"%lf",&param->start.y_min);
	common->sscanf(objc_tedstr(fg_par_ad,FB_XMAX1),"%lf",&param->start.y_max);
	if ( param->start.y_min>param->start.y_max )
		return FB_XMIN1;
	common->sscanf(objc_tedstr(fg_par_ad,FB_X0_1),"%lf",&param->start.y0);
	common->sscanf(objc_tedstr(fg_par_ad,FB_N1_1),"%d",&param->start.n1);
	common->sscanf(objc_tedstr(fg_par_ad,FB_N2_1),"%d",&param->start.n2);
	common->sscanf(objc_tedstr(fg_par_ad,FB_DN_1),"%d",&param->start.dn);

												/* endparameter */
	common->sscanf(objc_tedstr(fg_par_ad,FB_RMIN2),"%lf",&param->end.r_min);
	common->sscanf(objc_tedstr(fg_par_ad,FB_RMAX2),"%lf",&param->end.r_max);
	if ( x_param->anzahl>1 && param->end.r_min>param->end.r_max )
		return FB_RMIN2;
	common->sscanf(objc_tedstr(fg_par_ad,FB_XMIN2),"%lf",&param->end.y_min);
	common->sscanf(objc_tedstr(fg_par_ad,FB_XMAX2),"%lf",&param->end.y_max);
	if ( x_param->anzahl>1 && param->end.y_min>param->end.y_max )
		return FB_XMIN2;
	common->sscanf(objc_tedstr(fg_par_ad,FB_X0_2),"%lf",&param->end.y0);
	common->sscanf(objc_tedstr(fg_par_ad,FB_N1_2),"%d",&param->end.n1);
	common->sscanf(objc_tedstr(fg_par_ad,FB_N2_2),"%d",&param->end.n2);
	common->sscanf(objc_tedstr(fg_par_ad,FB_DN_2),"%d",&param->end.dn);

	/* interpolationstypen stehen schon in param->change[] ! */

	if ( objc_selected(fg_par_ad,FB_QUR) )					/* bildtyp */
		param->start.flag=1;
	else
		param->start.flag=0;

	if ( objc_selected(fg_par_ad,FB_INV) )					/* farbe */
		x_param->color=1;
	else
		x_param->color=0;

	param->start.time=0l;								/* zeit auf null setzen */

	return 0;
}

/*
		parameter / block aus objekt
*/
int get_fgbm_objc(int side)
	/* side	FB_GET1 = linke, FB_GET2 = rechte parameterspalte */
	/* 		FB_BLK1,         FB_BLK2 -> block */
{
int *objcs;
FR_OBJC *object;
FEIGENBAUM *fgbm;
double x_min,x_max,y_min,y_max;

	if ( side==FB_GET1 || side==FB_GET2 )
		object=common->get_objc(fgbm_nr);
	else {
		object=common->get_block(fgbm_nr,&x_min,&x_max,&y_min,&y_max);
	}
	if ( object==0l )
		return 0;
	if ( object==(FR_OBJC*)-1l )
		return 1;

	if ( side==FB_GET1 || side==FB_BLK1 )
		objcs=fb_1;
	else
		objcs=fb_2;

	fgbm=(FEIGENBAUM*)object->par->data;

	objc_unselect(fg_par_ad,FB_SMALL);
	objc_unselect(fg_par_ad,FB_MED);
	objc_unselect(fg_par_ad,FB_BIG);
	objc_select(fg_par_ad,FB_SMALL+object->size);

	if ( side==FB_GET1 || side==FB_GET2 ) {
		common->write_dbl(objc_tedstr(fg_par_ad,objcs[0]),fgbm->r_min,15,11);
		common->write_dbl(objc_tedstr(fg_par_ad,objcs[1]),fgbm->r_max,15,11);
		common->write_dbl(objc_tedstr(fg_par_ad,objcs[2]),fgbm->y_min,15,11);
		common->write_dbl(objc_tedstr(fg_par_ad,objcs[3]),fgbm->y_max,15,11);
	}
	else {
		if ( fgbm->flag==0 ) {
			common->write_dbl(objc_tedstr(fg_par_ad,objcs[0]),x_min,15,11);
			common->write_dbl(objc_tedstr(fg_par_ad,objcs[1]),x_max,15,11);
			common->write_dbl(objc_tedstr(fg_par_ad,objcs[2]),y_min,15,11);
			common->write_dbl(objc_tedstr(fg_par_ad,objcs[3]),y_max,15,11);
		}
		else {
			common->write_dbl(objc_tedstr(fg_par_ad,objcs[0]),y_min,15,11);
			common->write_dbl(objc_tedstr(fg_par_ad,objcs[1]),y_max,15,11);
			common->write_dbl(objc_tedstr(fg_par_ad,objcs[2]),x_min,15,11);
			common->write_dbl(objc_tedstr(fg_par_ad,objcs[3]),x_max,15,11);
		}
	}
	common->write_dbl(objc_tedstr(fg_par_ad,objcs[4]),fgbm->y0,15,11);
	common->sprintf(objc_tedstr(fg_par_ad,objcs[5]),"%4d",fgbm->n1);
	common->sprintf(objc_tedstr(fg_par_ad,objcs[6]),"%4d",fgbm->n2);
	common->sprintf(objc_tedstr(fg_par_ad,objcs[7]),"%3d",fgbm->dn);

	objc_select(fg_par_ad,FB_NRM+fgbm->flag);
	objc_unselect(fg_par_ad,FB_QUR-fgbm->flag);
	objc_unselect(fg_par_ad,FB_INV+object->color);
	objc_select(fg_par_ad,FB_NORM-object->color);

	return 1;
}

/*
		parameter eingeben
*/
static int fg_param(FGBM_PAR *param,X_PARAM *x_param)
{
int dia,ret,dflag;
int i;

	set_fgparam(&fgbm_set,param);		/* schreibe voreinstellungen in dialog */

	common->draw_objc(fg_par_ad,0l);	/* dialog zeichnen, hintergrund nicht retten */

	dia=FB_ANZ;					/* object, in das der CURSOR gesetzt werden soll */
	while ( 1 ) {
		ret=form_do(fg_par_ad,dia);
		if ( ret&0x8000 )
			{ ret&=0x7fff;	dflag=1; }	/* doppelklick */
		else
			dflag=0;

		if ( ret==FB_CLR ) {			/* alle eintrge lschen */
			for ( i=0; i<sizeof(fb_1)/sizeof(fb_1[0]); i++ ) {
				*objc_tedstr(fg_par_ad,fb_1[i])=0;
				*objc_tedstr(fg_par_ad,fb_2[i])=0;
				objc_spec(fg_par_ad,fb_ch[i])=ch_txt[1];
				param->change[i]=1;
			}
			common->draw_objc(fg_par_ad,0l);	/* dialog neuzeichnen */
		}
		else if ( ret==FB_SET ) {			/* standartvoreinstellung laden */
		  FGBM_SET xset;
		  	xset.set=0;
			set_fgparam(&xset,param);		/* in dialog entragen */
			common->draw_objc(fg_par_ad,0l);	/* dialog neuzeichnen */
		}
		else if ( ret==FB_COPY ) {			/* linke seite zur rechten kopieren */
			for ( i=0; i<sizeof(fb_1)/sizeof(fb_1[0]); i++ ) {
				strcpy(objc_tedstr(fg_par_ad,fb_2[i]),objc_tedstr(fg_par_ad,fb_1[i]));
				objc_draw(fg_par_ad,fb_2[i],0,0,0,640,400);
			}
		}
		else if ( ret==FB_CLR1 || ret==FB_CLR2 ) {	/* links/rechts lschen */
		  int *h;
		  	if ( ret==FB_CLR1 )
		  		h=fb_1;
		  	else
		  		h=fb_2;
			for ( i=0; i<sizeof(fb_1)/sizeof(fb_1[0]); i++,h++ ) {
				*objc_tedstr(fg_par_ad,*h)=0;
				objc_draw(fg_par_ad,*h,0,0,0,640,400);
			}
		}
		else if ( ret==FB_GET1 || ret==FB_BLK1 || ret==FB_GET2 || ret==FB_BLK2 ) {
											/* parameter / block einlesen */
			get_fgbm_objc(ret);
			common->draw_objc(fg_par_ad,0l);		/* neuzeichnen */
		}
		else if ( ret==FB_ABBR ) {				/* abbruch */
			objc_unselect(fg_par_ad,FB_ABBR);
			return 0;
		}
		else if ( ret==FB_OK ) {					/* ok */
			objc_set_normal(fg_par_ad,FB_OK);	/* wird gleich angezeigt */
			dia=get_fgparam(param,x_param);	/* parameter einlesen */
			if ( dia )				/* fehler */
				continue;
			return 1;
		}
		else {							/* interpolationstyp */
		  int nr;
			for ( nr=0; nr<8; nr++ )
				if ( ret==fb_ch[nr] )
					break;
			if ( nr!=8 ) {
				if ( dflag )				/* doppelklick -> auf 0 */
					param->change[nr]=1;
				else {
					param->change[nr]++;
					if ( param->change[nr]==3 )
						param->change[nr]=0;
				}
				objc_spec(fg_par_ad,ret)=ch_txt[param->change[nr]];
				objc_draw(fg_par_ad,ret,0,0,0,640,400);
			}
		}
	}
}

/*
		voreinstellungen einlesen
*/
static void x_fg_param(void)
{
FGBM_PAR param;
X_PARAM x_param;
int i;

	if ( fg_param(&param,&x_param) ) {	/* parameter einlesen */
		fgbm_set.start=param.start;	/* nach fgbm_set kopieren */
		fgbm_set.end=param.end;
		for ( i=0; i<8; i++ )
			fgbm_set.change[i]=param.change[i];
		fgbm_set.size=x_param.size;
		fgbm_set.anzahl=x_param.anzahl;
		fgbm_set.color=x_param.color;
		strcpy(fgbm_set.name,x_param.name);
		fgbm_set.set=1;
	}
}

/*
		bild-parameter aus bild(er)-parametern erzeugen
*/
static FEIGENBAUM *fg_par(FGBM_PAR *in,int nr,int anz)
{
	anz--;	/* (die interpolations-routinen brauchen nicht anzahl sondern grt-mgliche nummer (also anzahl-1) */
	in->act=in->start;	/* erst mal alle parameter kopieren (so kann man nichts vergessen) */
					/* dann interpolieren wo ntig */
	in->act.r_min=common->ipol(in->start.r_min,in->end.r_min,nr,anz,in->change[0]);
	in->act.r_max=common->ipol(in->start.r_max,in->end.r_max,nr,anz,in->change[1]);
	in->act.y_min=common->ipol(in->start.y_min,in->end.y_min,nr,anz,in->change[2]);
	in->act.y_max=common->ipol(in->start.y_max,in->end.y_max,nr,anz,in->change[3]);
	in->act.y0=common->ipol(in->start.y0,in->end.y0,nr,anz,in->change[4]);
	in->act.n1=(int)common->ipol((double)in->start.n1,(double)in->end.n1,nr,anz,in->change[5]);
	in->act.n2=(int)common->ipol((double)in->start.n2,(double)in->end.n2,nr,anz,in->change[6]);
	in->act.dn=(int)common->ipol((double)in->start.dn,(double)in->end.dn,nr,anz,in->change[7]);
	return &in->act;
}

/*------------------------------------------------------------------------------

	anzeigeroutinen (parameter/info)

------------------------------------------------------------------------------*/
/*
		parameter anzeigen
*/
static int fg_spar(FR_OBJC *object,long *puffer)
{
FEIGENBAUM *fgbm;
int ret;

	fgbm=(FEIGENBAUM*)object->par->data;

			/* schreibe parameter in dialogbox */
	strcpy(objc_tedstr(fg_show_ad,FS_NAME),object->name);
	objc_unselect(fg_show_ad,FS_SMALL);
	objc_unselect(fg_show_ad,FS_MID);
	objc_unselect(fg_show_ad,FS_BIG);
	objc_select(fg_show_ad,FS_SMALL+object->size);
	common->write_dbl(objc_spec(fg_show_ad,FS_RMIN),fgbm->r_min,15,11);
	common->write_dbl(objc_spec(fg_show_ad,FS_RMAX),fgbm->r_max,15,11);
	common->write_dbl(objc_spec(fg_show_ad,FS_XMIN),fgbm->y_min,15,11);
	common->write_dbl(objc_spec(fg_show_ad,FS_XMAX),fgbm->y_max,15,11);
	common->write_dbl(objc_spec(fg_show_ad,FS_X0),fgbm->y0,15,11);
	common->sprintf(objc_spec(fg_show_ad,FS_N1),"%4d",fgbm->n1);
	common->sprintf(objc_spec(fg_show_ad,FS_N2),"%4d",fgbm->n2);
	common->sprintf(objc_spec(fg_show_ad,FS_DN),"%3d",fgbm->dn);
	objc_unselect(fg_show_ad,FS_INV+object->color);
	objc_select(fg_show_ad,FS_NORM-object->color);

			/* zeige dialog an */
	common->draw_objc(fg_show_ad,puffer);
	ret=form_do(fg_show_ad,FS_NAME)&0x7FFF;
	objc_unselect(fg_show_ad,ret);
	common->undraw_objc(puffer);
	if ( ret==FS_OK ) {	/* lese namen und farbe aus */
		strcpy(object->name,objc_tedstr(fg_show_ad,FS_NAME));
		object->color=objc_selected(fg_show_ad,FS_NORM)?0:1;
		return 1;	/* daten mgl. gendert! */
	}
	return 0;		/* nichts gendert */
}

/*
		info zurckgeben
*/
static void fg_xinfo(FR_OBJC *object,PIC_INFO *info)
{
FEIGENBAUM *fgbm;
int lines;

	fgbm=(FEIGENBAUM*)object->par->data;
	info->time=fgbm->time/200.0;			/* rechenzeit */
	if ( fgbm->flag==0 ) {
		lines=common->fr_dx[object->size];
		if ( object->lastline>0  )
			lines=object->lastline-common->fr_x0[object->size];
	}
	else {
		lines=common->fr_dy[object->size];
		if ( object->lastline>0  )
			lines=-object->lastline+common->fr_y0[object->size]+common->fr_dy[object->size];
	}
	info->iter=(fgbm->n1+fgbm->n2)*(long)lines;	/* iterationen */
	info->points=lines*fgbm->n2/fgbm->dn;		/* punkte */
}

/*
		routine zum zeichnen des diagrammes
*/
static int fg_draw(FR_OBJC *object,FEIGENBAUM *fgbm,void *puffer)
{
double r,y,dr,dy;
int rr,yy,i;
int y_off;
int min_r,max_r;
long key=0l;

	fgbm->time-=common->gettime();
	if ( fgbm->flag==0 ) {		/* normal */
		min_r=common->fr_x0[object->size];
		max_r=common->fr_x0[object->size]+common->fr_dx[object->size]+1;
		y_off=common->fr_y0[object->size]+common->fr_dy[object->size];

		dr=(fgbm->r_max-fgbm->r_min)/(common->fr_dx[object->size]+1);
		dy=(common->fr_dy[object->size]+1)/(fgbm->y_max-fgbm->y_min);
		if ( object->lastline )
			rr=object->lastline;
		else
			rr=min_r;

		for ( r=fgbm->r_min+dr*(rr-min_r); rr<max_r; rr++,r+=dr ) {
			y=fgbm->y0;
			for ( i=0; i<fgbm->n1; i++ )
				y=r*y*(1-y);
			for ( i=0; i<fgbm->n2; i++ ) {
				y=r*y*(1-y);
				if ( i%fgbm->dn==0 && y>=fgbm->y_min && y<fgbm->y_max ) {
					yy=(y-fgbm->y_min)*dy;
					common->plot_pixel(rr,y_off-yy,(void*)common->scr);
				}
			}
			do {
				key=Crawio(0xFF);
			} while ( (char)key!=0 && (char)key!=27 );
			if ( (char)key==27)
				break;
		}
		if ( rr==max_r )
			object->lastline=-1;
		else
			object->lastline=rr;
	}
	else {					/* quer */
		min_r=common->fr_y0[object->size];
		max_r=common->fr_y0[object->size]+common->fr_dy[object->size];
		y_off=common->fr_x0[object->size];

		dr=(fgbm->r_max-fgbm->r_min)/(common->fr_dy[object->size]+1);
		dy=(common->fr_dx[object->size]+1)/(fgbm->y_max-fgbm->y_min);
		if ( object->lastline )
			rr=object->lastline;
		else
			rr=max_r;

		for ( r=fgbm->r_min+dr*(max_r-rr); rr>=min_r; rr--,r+=dr ) {
			y=fgbm->y0;
			for ( i=0; i<fgbm->n1; i++ )
				y=r*y*(1-y);
			for ( i=0; i<fgbm->n2; i++ ) {
				y=r*y*(1-y);
				if ( i%fgbm->dn==0 && y>=fgbm->y_min && y<fgbm->y_max ) {
					yy=(y-fgbm->y_min)*dy;
					common->plot_pixel(y_off+yy,rr,(void*)common->scr);
				}
			}
			do {
				key=Crawio(0xFF);
			} while ( (char)key!=0 && (char)key!=27 );
			if ( (char)key==27)
				break;
		}
		if ( rr==max_r )
			object->lastline=-1;
		else
			object->lastline=rr;
	}
	fgbm->time+=common->gettime();

	return( (int)(key>>24) );
}

/*
		gib block zurck
*/
static void fg_ob_block(FR_OBJC *object,double *x_min,double *x_max,double *y_min,double *y_max)
{
FEIGENBAUM *fgbm;

	fgbm=(FEIGENBAUM*)object->par->data;
	if ( fgbm->flag==0 ) {
		*x_min=fgbm->r_min;
		*x_max=fgbm->r_max;
		*y_min=fgbm->y_min;
		*y_max=fgbm->y_max;
	}
	else {
		*x_min=fgbm->y_min;
		*x_max=fgbm->y_max;
		*y_min=fgbm->r_min;
		*y_max=fgbm->r_max;
	}
}

/*
		drucke parameter
*/
static void fg_dr_par(FR_OBJC *object)
{
char string[128];
char h1[32],h2[32],h3[32];
FEIGENBAUM *fgbm;

	fgbm=(FEIGENBAUM*)object->par->data;

	common->write_dbl(h1,fgbm->r_min,14,8);
	common->write_dbl(h2,fgbm->r_max,14,8);
	common->sprintf(string,"Parameter   r: %-14s - %-14s\n",h1,h2,h3);
	common->dr_string(string);	/* ausgabe an drucker (inc. CR/LF) */

	common->write_dbl(h1,fgbm->y_min,14,8);
	common->write_dbl(h2,fgbm->y_max,14,8);
	common->write_dbl(h3,fgbm->y0,14,8);
	common->sprintf(string,"Funktionswert: %-14s - %-14s, Startwert %-14s\n",h1,h2,h3);
	common->dr_string(string);

	common->sprintf(string,"Iterationen  : %6d vor, %6d bei Plot (Schrittweite %d)",fgbm->n1,fgbm->n2,fgbm->dn);
	common->dr_string(string);

	*string=0;
	common->dr_string(string);	/* leerzeile */
}

/*
		initialisiere routinen
*/
static int fg_init(int nr)
{
int i;
extern CHAOS fch;
extern OBJECT *icons_ad;

	fgbm_nr=nr;						/* nummer merken (fr get_objc/get_block) */

	i=rsrc_load("chs_ultd\\feigenbm.rsc");	/* resourcedatei aus ordner chs_ultd */
	if ( !i )
		return 1;
	if ( !rsrc_gaddr(R_TREE,ICONS,&icons) ||
		!rsrc_gaddr(R_TREE,FG_PAR,&fg_par_ad) ||
		!rsrc_gaddr(R_TREE,FG_SPAR,&fg_show_ad) )
			return 1;
	fch.icon=icons[ICON_FB].ob_spec.iconblk;
	fch.xicon=icons[ICON_FB1].ob_spec.iconblk;
	return 0;
}

#pragma warn -sus

int flag=1;
CHAOS fch={
"TMMWFGBM",		/*	id	*/
"Feigenbaum-Diag.",	/*	menue	*/
"Th. Morus Walter","V1.0, 1.9.1992","Feigenbaum Diagramme",
				/*	name, version, text	*/
0l, 0l,			/*	icon, xicon	*/
sizeof(FGBM_SET), &fgbm_set,
				/*	set_len, set	*/
sizeof(FEIGENBAUM), sizeof(FGBM_PAR), 0l, 0l, 0,
				/*	par_len, make_len, neu_len, neu_par, neu_flag	*/
0,				/*	last_flag	*/

fg_init,			/*	do_init		*/
fg_param,			/*	get_param		*/
fg_par,			/*	get_picpar	*/
x_fg_param,		/*	set_param		*/
0l,				/*	extended		*/
0l,				/*	get_neu_param	*/
0l,				/*	make_neu_param	*/
0l,				/*	make_vier		*/
fg_draw,			/*	do_draw		*/
0l,				/*	dont_draw		*/
fg_spar,			/*	show_par		*/
0l,				/*	show_info		*/
fg_xinfo,			/*	get_info		*/
fg_ob_block,		/*	get_objcblk	*/
fg_ob_block,		/*	get_xobjcblk	*/
0l,				/*	get_pkt		*/
0l,				/*	show_pktinfo	*/
fg_dr_par,		/*	dr_param		*/
0l,				/*	cnv_load		*/
0l,0l,0l,0l,0l,0l,0l,0l	/* reserved */
};

XCHAOS xfch={"CHSultd5",
		1,	/* nur eine routine */
		&flag,	/* nur sw */
		&fch
};

