#define GRAPHDEF
#include "graph.h"
int freedataset(int i);
int free_temp(void);
int set_sizelength(void);
extern int trace_on;
extern int this_line;
static int xxgrid[5];
    double koffsetx=0,koffsety=0,khei=0;	/* key variables */
    char kpos[30];
    int knobox=0;				/* end key vraibles */
    char *letstr[20];
    int nlet;
int draw_graph(void);
begin_graph(int *pln,int32 *pcode, int *cp)
{
    static int ct,i,ncol,ntmp,np,*m,t,d;
    static int iid1,iid2,d2,st;
    double *px,*py,ox,oy;
    static int xset,erflg,gosret;
    FILE *fptr;

    nlet = 0;
    koffsetx=0; koffsety=0; khei=0;	/* key variables */
    kpos[0] = 0;
    knobox=0;				/* end key vraibles */
	freeafont();  /* get some more memory, we might need it */
	g_hscale = .7;
	g_vscale = .7;

	nlet = 0;
    erflg = true;
	for (i=1;i<5;i++) { xxgrid[i] = 0; vinit_axis(i);}
	graph_init();
	/* ! set up some more constants (defaults)*/
	g_get_usersize(&g_xsize,&g_ysize);
	set_sizelength();

    dp[0] = myallocz(sizeof(*dp[1]));  /* dataset for default settings */
   dp[0]->lwidth = -1;
    begin_init();
    this_line -= 2;
    for (;;) {

	srclin[0] = 0;
	st = begin_token(&pcode,cp,pln,srclin,(char *) tk,&ntk,outbuff);
	if (trace_on) gprint("Graph   | %s %d \n",srclin,st);
	if (trace_on) {
		for (i=1;i<=ntk;i++) gprint("{%s} ",tk[i]);
		gprint("\n");
	}
	this_line++;
	if (!st) {draw_graph(); return;}
	ct = 1;
	while (ct<=ntk)  {
	if (strcmp(tk[ct],"BAR")==0)  goto do_bar;
	if (strcmp(tk[ct],"DATA")==0)  goto do_data;
	kw("DATA") 	goto do_data;
	kw("EXTRACT") 	goto do_extract;
	kw("FILL") 	goto do_fill;
	kw("HSCALE") 	goto do_hscale;
	kw("LET") 	goto do_letsave;
	kw("NOBOX") 	goto do_nobox;
	kw("NOBORDER") 	goto do_nobox;
	kw("SIZE") 	goto do_size;
	kw("KEY") 	goto do_key;
	kw("VSCALE") 	goto do_vscale;
	kw("FULLSIZE") 	goto do_fullsize;
/*	kw("YNEGATE") 	goto do_ynegate;*/
	kw("TITLE") 	goto do_main_title;
	kw("!") 	goto do_next_line;
	xset = 0;
	if (strstr(tk[ct],"AXIS")!=NULL)   		xset = 1;
	else if (strstr(tk[ct],"LABELS")!=NULL) 	xset = 2;
	else if (strstr(tk[ct],"SIDE")!=NULL) 		xset = 3;
	else if (strstr(tk[ct],"SUBTICKS")!=NULL) 	xset = 5;
	else if (strstr(tk[ct],"TICKS")!=NULL) 		xset = 4;
	if (xset>0) goto do_axisset;
	if (strstr(tk[ct],"NAMES")!=NULL) 		goto do_names;
	if (strstr(tk[ct],"PLACES")!=NULL) 		goto do_places;
	if (strstr(tk[ct],"TITLE")!=NULL) 		goto do_title;
	if (*tk[ct]=='D') 				goto do_datasets;
	gprint("Unrecognised graph sub command {%s} %d \n ",tk[ct],ct);
	goto do_next_line;
do_next_token:;
	}
do_next_line:
	erflg = true;
	if (!begin_next_line(pcode,cp)) {draw_graph(); return;}
    }

/* ----------------------------------------------------------------*/
/* this disgusting piece of code is due to no     gosub/return   */
/* (a few months later)... and my own ignorance of C */
do_axisset:
	t = axis_type(tk[1]);
	erflg = true;
	gosret = 1;
	switch (xset) {
	  case 1:
		gosret = 2;
		goto do_axis;
doax2:
		erflg = false;
		goto do_labels;
doax3:
		goto do_side;
doax4:
	goto do_ticks;
	  case 2:
		goto do_labels;
	  case 3:
		goto do_side;
	  case 4:
		goto do_ticks;
	  case 5:
		goto do_subticks;
	}
end_axisset:
	if (t>2) goto do_next_line;
	erflg = false;
	t = t + 2;
	erflg = false;
	gosret = 0;
	switch (xset) {
	  case 1:
		gosret = 3;
		goto do_axis;
doax5:		goto do_labels;
doax6:		goto do_side;
doax7:		goto do_ticks;
	  case 2:
		goto do_labels;
	  case 3:
		goto do_side;
	  case 4:
		goto do_ticks;
	  case 5:
		goto do_subticks;
	}
goto do_next_line;
/* ----------------------------------------------------------------*/
do_bar:
	/* bar d1,d2,d3 from d4,d5,d6 color red,green,blue fill grey,blue,green
		dist exp, width exp, LSTYLE 3,445,1
		3dbar .5 .5 top black,black,black side red,green,blue  notop */
{
	int ng,fi,di;
	char *ss,tmpcol[40];
	g_nbar++;
	br[g_nbar] = myallocz(sizeof(*br[1]));
	br[g_nbar]->ngrp = 0;
	ct = 2;
	ss = strtok(tk[ct],",");
	while (ss!=NULL) {
	  if (*ss=='D') {
		ng = (br[g_nbar]->ngrp)++;
		d =  atoi(ss+1);
		if (d==0 || d>99) gprint("Error in bar command {%s}  token number %d \n",tk[ct],ct);
		br[g_nbar]->to[ng] = d;
 	  }
	  ss = strtok(0,",");
	}

	for (i=1;i<=ng;i++) {
		br[g_nbar]->color[i] = g_get_grey(0.0);
		br[g_nbar]->fill[i] = g_get_grey(1.0-ng/(i));
		br[g_nbar]->from[i] = 0;
		g_get_line_width(&br[g_nbar]->lwidth[i]);
		strcpy(br[g_nbar]->lstyle[i] ,"1\0");
	}

	ct++;
	while (ct<=ntk)  {
		kw("DIST") 	br[g_nbar]->dist = next_exp;
	   else kw("WIDTH") 	br[g_nbar]->width = next_exp;
	   else kw("3D") {
		br[g_nbar]->x3d = next_exp;
		br[g_nbar]->y3d = next_exp;
	   }
	   else kw("NOTOP") 	br[g_nbar]->notop = true;
	   else kw("LSTYLE") 	next_str((char *) br[g_nbar]->lstyle);
	   else kw("FROM") {
		fi = 0;
		ct +=1;
		ss = strtok(tk[ct],",");
		while (ss!=NULL) {
		  if (*ss=='D') {
			di =  atoi(ss+1);
			br[g_nbar]->from[fi++] = di;
		  }
		  ss = strtok(0,",");
		}
	   }
	   else kw("COLOR") {
		fi = 0;ct += 1;
		ss = strtok(tk[ct],",");
		while (ss!=NULL) {
		  br[g_nbar]->color[fi++] = pass_color(ss);
		  ss = strtok(0,",");
		}
	   }
	   else kw("SIDE") {
		fi = 0;ct += 1;
		ss = strtok(tk[ct],",");
		while (ss!=NULL) {
		  br[g_nbar]->side[fi++] = pass_color(ss);
		  ss = strtok(0,",");
		}
	   }
	   else kw("TOP") {
		fi = 0;ct += 1;
		ss = strtok(tk[ct],",");
		while (ss!=NULL) {
		  br[g_nbar]->top[fi++] = pass_color(ss);
		  ss = strtok(0,",");
		}
	   }
	   else kw("FILL") {
		fi = 0; ct++;
		ss = strtok(tk[ct],",");
		while (ss!=NULL) {
			if (strchr(ss,'$')!=NULL) {
			{ 	int idx,typ;
				var_find(ss,&idx,&typ) ;
				if (idx>=0) var_getstr(idx,tmpcol);
				br[g_nbar]->fill[fi++] = pass_color(tmpcol);
			}} else {
				  br[g_nbar]->fill[fi++] = pass_color(ss);
			}
		  ss = strtok(0,",");
		}
	   }
	   else gprint("Unrecognised GRAPH BAR sub command {%s} %d \n "
		,tk[ct],ct);
	  ct++;
	}
}
goto do_next_line;
/*----------------------------------------------------------------*/
/* fill x1,d2 color green xmin 1 xmax 2 ymin 1 ymax 2   */
/* fill d1,x2 color green xmin 1 xmax 2 ymin 1 ymax 2   */
/* fill d1,d2 color green xmin 1 xmax 2 ymin 1 ymax 2   */
/* fill d1 color green xmin 1 xmax 2 ymin 1 ymax 2      */
do_fill:
{
	char *ss,s1[40],s2[40];
	fd[++nfd] = myallocz(sizeof(*fd[1]));
	ct = 2;
	strcpy(s1,strtok(tk[ct],","));
	ss = strtok(0,",");
	if (ss==NULL) strcpy(s2,""); else {
		strcpy(s2,ss);
		strtok(0,",");
	}

	if (strcmp(s1,"X1")==0) {
		fd[nfd]->type = 1;
		d = atoi(s2+1);
		if (d==0) { gprint("Not a valid fill option {%s} wanted FILL X1,D1 \n",tk[ct]); goto end_fill_read; }
		fd[nfd]->da = d;
	} else if (strcmp(s2,"X2")==0) {
		fd[nfd]->type = 2;
		d = atoi(s1+1);
		if (d==0) { gprint("Not a valid fill option {%s} wanted FILL D2,X2 \n",tk[ct]); goto end_fill_read; }
		fd[nfd]->da = d;
	} else if (strcmp(s2,"")!=0) {
		fd[nfd]->type = 3;
		d = atoi(s1+1);
		d2 = atoi(s2+1);
		if (d==0 || d2==0) { gprint("Expecting FILL D1,D2  found {%s}\n",tk[ct]); goto end_fill_read; }
		fd[nfd]->da = d;
		fd[nfd]->db = d2;
	} else if (*s1=='D') {
		fd[nfd]->type = 4;
		d = atoi(s1+1);
		if (d==0) { gprint("Expecting FILL d1 found {%s} \n",tk[ct]); goto end_fill_read; }
		fd[nfd]->da = d;
	} else {
		gprint("Invalid fill option, wanted d1,d2 or x1,d1 or d1,x2 or d1 \n");
		goto end_fill_read;
	}
	ct++;

	fd[nfd]->color = g_get_grey(1.0-nfd*.1);
	fd[nfd]->xmin = -LARGE_NUM;
	fd[nfd]->xmax = LARGE_NUM;
	fd[nfd]->ymin = -LARGE_NUM;
	fd[nfd]->ymax = LARGE_NUM;

	while (ct<=ntk)  {
		kw("COLOR") 	{ct++; fd[nfd]->color = pass_color(tk[ct]);}
	   else kw("XMIN") 	fd[nfd]->xmin = next_exp;
	   else kw("XMAX") 	fd[nfd]->xmax = next_exp;
	   else kw("YMIN") 	fd[nfd]->ymin = next_exp;
	   else kw("YMAX") 	fd[nfd]->ymax = next_exp;
	   else gprint("Unrecognised GRAPH FILL sub command {%s} %d (Note: CGLE syntax change\n  Expected COLOR,XMIN,XMAX,YMIN,YMAX \n "
		,tk[ct],ct);
	   ct++;
	}
}
end_fill_read:;
goto do_next_line;
/*----------------------------------------------------------------*/
do_key:
	ct = 2;
	while (ct<=ntk)  {
		kw("POS") 	next_str(kpos);
	   else kw("POSITION") 	next_str(kpos);
	   else kw("HEI") 	khei = next_exp;
	   else kw("NOBOX") 	knobox = true;
	   else kw("OFFSET") 	{koffsetx = next_exp;koffsety = next_exp;}
	   else gprint("Unrecognised GRAPH KEY sub command {%s} %d \nExpected  KEY POS BL,TL,BR,TR HEI .6 NOBOX OFFSET 2 3 \n"
		,tk[ct],ct);
	   ct++;
	}
goto do_next_line;
/*----------------------------------------------------------------*/
/* data a.dat				*/
/* data a.dat d2 d5			*/
/* data a.dat d1=c1,c3  d2=c5,c1	*/
do_data:
{
	static char data_d[60],data_x[60],data_y[60];
	int nm=0,expect_col=0,extract=0,xi,yi,dn,j,nncol=0,allind;
	char *s1,buff1[30];
	char infile[80];
	ntmp = 0;
	allind = 0;
	for (i=1;i<59;i++) {	/* default mapping if no dataset names given */
		data_d[i] = freedataset(i);
		data_x[i] = 1;
		data_y[i] = i+1;
	}
	while (ct<=ntk)  { if (strstr(tk[ct],"=")!=NULL) extract = true; ct++; }
	ct = 3;
	if (extract==true) {
	 while (ct<=ntk)  {
		if (*tk[ct]=='D') {
			nm++;
			strncpy(buff1,tk[ct],29);
			s1 = strtok(buff1,"=");
			if (s1!=NULL) data_d[nm] = atoi(s1+1);
			if (s1==NULL || data_d[nm]==0) gprint("Expecting Dn=Ca,Cb (no spaces) {%s}\n",tk[ct]);
			s1 = strtok(NULL,",");
			if (s1!=NULL) data_x[nm] = atoi(s1+1);
			s1 = strtok(NULL,",");
			if (*s1=='*') {
				allind = data_d[nm];
			} else {
			 if (s1!=NULL) data_y[nm] = atoi(s1+1);
			 if (s1==NULL || data_x[nm]==0 || data_y[nm]==0) {
				gprint("Expecting Dn=Ca,Cb   (no spaces) {%s}\n",tk[ct]);
				goto do_next_line;
			 }
			 if (data_x[nm]>expect_col) expect_col = data_x[nm];
			 if (data_y[nm]>expect_col) expect_col = data_y[nm];
		 	}
		} else {
			if (*tk[ct] != 0) gprint("Expecting Dn=Ca,Cb   (no spaces) {%s}\n",tk[ct]);
		}
	   	ct++;
	 }
	} else {
	 while (ct<=ntk)  {
		if (*tk[ct]==' ') ct++;
		if (*tk[ct]=='D') {
			nm++;
			data_d[nm] = atoi(tk[ct]+1);
			data_x[nm] = 1;
			data_y[nm] = nm+1;
		} else gprint("Warning, found {%s}, expecting   data a.dat d1 d2 d3 \n",tk[ct]);
	   	ct++;
	  }
	}
	if (expect_col==0 && nm>0) expect_col = nm+1;
	if (allind>0) expect_col = 0;

/*
	dbg for (i=1;i<5;i++) {
		gprint("MAPPING %d =  %d %d %d\n",i,data_d[i],data_x[i],data_y[i] );
	}
*/
	ct = 2;
	strcpy(infile,tk[2]);
	if (strchr(infile,'$')!=NULL) {
		{ int idx,typ;
		var_find(infile,&idx,&typ) ;
		if (idx>=0) var_getstr(idx,infile);
	}}
	strlwr(infile);
	fptr = fopen(infile,"r");
	if (fptr==NULL) {
		gprint("Unable to open data file {%s} \n",infile);
		perror("Reason");
		goto do_next_line;
	}
	for (;!(feof(fptr));) {
/* 		if (*tk[ct]==' ') ct++; */
		inbuff[0]=0;
		fgets(inbuff,200,fptr);
		if (strlen(inbuff)>198) gprint("Lines in data file too long, split file");
		if (inbuff[0]=='"') continue;
		alloc_temp(ntmp);
		if (tmpf == NULL) {
		  gprint("Too many points in {%s}, reduce points, split file or use VAX CGLE \n",infile);
		  break;
		}
		token_data(inbuff,tk,&ntk,tkbuff);
		ncol = 0;
		for (i=1;i<=ntk;i++) {
			ncol++;
			if (strcmp(tk[i],"*")==0)   {
				tmpmiss[++ntmp] = true;
			}
			else if (strcmp(tk[i],"-")==0) {
				  tmpmiss[++ntmp] = true;
			}
			else if (strcmp(tk[i],".")==0) {
				  tmpmiss[++ntmp] = true;
			}
			else {
				tmpf[++ntmp] = atof(tk[i]);
				tmpmiss[ntmp] = false;
			}
		}
		if (nncol == 0) nncol = ncol;
		if (ncol != nncol) if (ncol>0) {
			if (allind==0) gprint("MUST FIX *** Inconsistent columns in {%s} %d %d \n",infile,ncol,nncol);
		}
		if (nm==0 && ncol>1) nm = ncol-1;
	}
	fclose(fptr);
	if (expect_col>0) if (expect_col>nncol) {
		gprint("Warning, expecting %d columns in data file {%s} found %d \n"
			,expect_col,infile,ncol);
	}
	if (nncol>0) np = ntmp/nncol;
	if (allind>0) { /* if data file contains y values only, y1, y2 ,y3...*/
		dn = allind;
		np = ntmp;
		if (dn>ndata) ndata = dn;
		if (dp[dn]==NULL) {
			dp[dn] = myallocz(sizeof(*dp[dn]));
			copy_default(dn);
		}
		np++;
		dp[dn]->xv = myallocz(sizeof(*px)*np);
		dp[dn]->yv = myallocz(sizeof(*px)*np);
		dp[dn]->miss = myallocz(sizeof(*m)*np);
		np--;
		px = dp[dn]->xv;
		py = dp[dn]->yv;
		m = dp[dn]->miss;

	 	for (i=1;i<=np;i++) {
			*(px++) = i;
			*(py++) = tmpf[i];
			*(m++) = tmpmiss[i];
			setrange(*(px-1),*(py-1),*(m-1));
		}
		dp[dn]->np = np;
		goto do_next_line;
	}
	for (j=1;j<=nm;j++) {
		dn = data_d[j];
		xi = data_x[j];
		yi = data_y[j];
		if (dn>ndata) ndata = dn;
		if (dp[dn]==NULL) {
			dp[dn] = myallocz(sizeof(*dp[dn]));
			if (dp[dn]==NULL) gprint("Memory allocation error, graph dataset \n");
			copy_default(dn);
		}
		np++;
		dp[dn]->xv = myallocz(sizeof(*px)*np);
		dp[dn]->yv = myallocz(sizeof(*px)*np);
		dp[dn]->miss = myallocz(sizeof(*m)*np);
		np--;
		px = dp[dn]->xv;
		py = dp[dn]->yv;
		m = dp[dn]->miss;

	 	for (i=1;i<=np;i++) {
			*(px++) = tmpf[i*nncol-nncol+xi];
			*(py++) = tmpf[i*nncol-nncol+yi];
			*(m++) = (tmpmiss[i*nncol-nncol+xi]==true)
				|| (tmpmiss[i*nncol-nncol+yi]==true);
			setrange(*(px-1),*(py-1),*(m-1));
			dbg gprint("(xym    %f %f %d \n",*(px-1),*(py-1),*(m-1));
		}
		dp[dn]->np = np;
	}
}
goto do_next_line;
/*----------------------------------------------------------------*/
do_extract:

goto do_next_line;
/*----------------------------------------------------------------*/
do_hscale:
	g_hscale = next_exp;
goto do_next_line;
/*----------------------------------------------------------------*/
do_letsave:
	letstr[++nlet] = myalloc(strlen(srclin)+1);
	strcpy(letstr[nlet],srclin);
goto do_next_line;
/*----------------------------------------------------------------*/
do_nobox:
	g_nobox = true;
goto do_next_line;
/*----------------------------------------------------------------*/
do_size:
	g_xsize = next_exp;
	g_ysize = next_exp;
	/* ! set up some more constants */
	set_sizelength();
goto do_next_line;
/*----------------------------------------------------------------*/
do_vscale:
	g_vscale = next_exp;
goto do_next_line;
/*----------------------------------------------------------------*/
do_fullsize:
	g_vscale = 1;
	g_hscale = 1;
	g_nobox = true;
goto do_next_line;
/*----------------------------------------------------------------*/
/* a.r. 
do_ynegate:
	g_ynegate = true;
goto do_next_line;
*/
/*----------------------------------------------------------------*/
do_axis:
	ct = 2;
/* 	t = axis_type(tk[1]); */
	while (ct<=ntk)  {
		kw("BASE") xx[t].base = next_exp;
 	   else kw("COLOR") xx[t].color = next_exp;
	   else kw("DSUBTICKS") xx[t].dsubticks = next_exp;
	   else kw("DTICKS") xx[t].dticks = next_exp;
	   else kw("DPOINTS") xx[t].decimal = next_exp;
	   else kw("SHIFT") xx[t].shift = next_exp;
	   else kw("GRID") xxgrid[t] = true;
	   else kw("NEGATE") {
	   	xx[t].negate = true;		/* a.r. */
	   	if (t == 1 || t == 2)
	   		data_negate[t] = true;
	   	/*g_ynegate = true;*/
	   	}
	   else kw("FONT") xx[t].label_font = next_font;
	   else kw("LOG") xx[t].log = true;
	   else kw("LSTYLE") 	next_str(xx[t].side_lstyle);
	   else kw("LWIDTH") 	xx[t].side_lwidth = next_exp;
	   else kw("MIN") {
		xx[t].min = next_exp;
		xx[t].minset = true;
	   }
	   else kw("MAX") {
		xx[t].max = next_exp;
		xx[t].maxset = true;
	   }
	   else kw("HEI") 	xx[t].label_hei = next_exp;
	   else kw("NOLAST") 	xx[t].nolast = true;
	   else kw("LAST") 	xx[t].nolast = false;
	   else kw("FIRST") 	xx[t].nofirst = false;
	   else kw("NOFIRST") 	xx[t].nofirst = true;
	   else kw("NSUBTICKS") xx[t].nsubticks = next_exp;
	   else kw("NTICKS") 	xx[t].nticks = next_exp;
	   else kw("ON") 	xx[t].off = false;
	   else kw("OFF") 	xx[t].off = true;
	   else gprint("Unrecognised GRAPH %%AXIS sub command {%s} %d\n",tk[ct],ct);
	   ct++;
	}

if (gosret==2) goto doax2;	/* in axis 	*/
if (gosret==3) goto doax5;	/* in axis 	*/
if (gosret==1) goto end_axisset;  /* in axis,label,side,tick,subtick */
goto do_next_line;
/*----------------------------------------------------------------*/
do_names:
	t = axis_type(tk[1]);
	ct = 1;
	while (ct<ntk)  {
		next_quote(strbuf);
		i = ++xx[t].nnam;
		xx[t].names[i] = myallocz(strlen(strbuf)+1);
		strcpy(xx[t].names[i],strbuf);
	}

goto do_next_line;
/*----------------------------------------------------------------*/
do_places:	/* x2places, or xplaces, or yplaces or y2places */
	t = axis_type(tk[1]);
	ct = 1;
	while (ct<ntk)  {
		xx[t].places[++xx[t].nplaces] = next_exp;
	}
goto do_next_line;
/*----------------------------------------------------------------*/
do_main_title:
	/* should change position and size of main title */
	t = 3;
	xx[t].title = myallocz(40);
	ct = 1;
	next_vquote(xx[t].title);
	ct = 3;
	xx[t].title_dist = g_fontsz*.7;
	xx[t].title_hei = g_fontsz*1.5;
	while (ct<=ntk)  {
	         kw("HEI")     xx[t].title_hei = next_exp;
	    else kw("OFF")     xx[t].title_off = true;
	    else kw("COLOR")   xx[t].title_color = next_color;
	    else kw("FONT")    xx[t].title_font = next_font;
	    else kw("DIST")    xx[t].title_dist = next_exp;
	    else gprint("Expecting TITLE sub command, found {%s} pos %d\n",tk[ct],ct);
	    ct++;
	}
goto do_next_line;
/*----------------------------------------------------------------*/
do_title:
	t = axis_type(tk[1]);
	ct = 1;
	next_vquote(xx[t].title);
	ct = 3;
	while (ct<=ntk)  {
	         kw("HEI")     xx[t].title_hei = next_exp;
	    else kw("OFF")     xx[t].title_off = true;
	    else kw("ROT")     xx[t].title_rot = true;
	    else kw("ROTATE")     xx[t].title_rot = true;
	    else kw("COLOR")   xx[t].title_color = next_color;
	    else kw("FONT")    xx[t].title_font = next_font;
	    else kw("DIST")    xx[t].title_dist = next_exp;
	    else gprint("Expecting axis TITLE sub command, found {%s} pos %d\n",tk[ct],ct);
	    ct++;
	}
goto do_next_line;
/*----------------------------------------------------------------*/
do_labels:
	ct = 2;
/* 	t = axis_type(tk[1]); */
	while (ct<=ntk)  {
		if (*tk[ct]==' ') ct++;
	         kw("HEI")     xx[t].label_hei = next_exp;
	    else kw("OFF")     xx[t].label_off = true;
	    else kw("ON")     xx[t].label_off = false;
	    else kw("COLOR")   xx[t].label_color = next_color;
	    else kw("FONT")    xx[t].label_font = next_font;
	    else kw("DIST")    xx[t].label_dist = next_exp;
	    else ifer gprint("Expecting LABELS sub command, found {%s} pos %d \n",tk[ct],ct);
	    ct++;
	}
if (gosret==2) goto doax3;	/* in label 	*/
if (gosret==3) goto doax6;	/* in label 	*/
if (gosret==1) goto end_axisset;  /* in axis,label,side,tick,subtick */
goto do_next_line;
/*----------------------------------------------------------------*/
do_side:
	ct = 2;
/* 	t = axis_type(tk[1]); */
	while (ct<=ntk)  {
		 if (*tk[ct]==' ') ct++;
	         kw("OFF")     xx[t].side_off = true;
	    else kw("ON")   xx[t].side_off = false;
	    else kw("COLOR")   xx[t].side_color = next_color;
	    else kw("LWIDTH")  xx[t].side_lwidth = next_exp;
	    else kw("LSTYLE")  next_str(xx[t].side_lstyle);
	    else ifer gprint("Expecting SIDE sub command, found {%s} pos %d \n",tk[ct],ct);
	    ct++;
	}
if (gosret==2) goto doax4;	/* in side  	*/
if (gosret==3) goto doax7;	/* in side  	*/
if (gosret==1) goto end_axisset;  /* in axis,label,side,tick,subtick */
goto do_next_line;
/*----------------------------------------------------------------*/
do_ticks:
	ct = 2;
/* 	t = axis_type(tk[1]); */
	while (ct<=ntk)  {
	    if (*tk[ct]==' ') ct++;
	         kw("LENGTH")  xx[t].ticks_length = next_exp;
	    else kw("OFF")     {xx[t].ticks_off = true;
				xx[t].subticks_off = true;}
	    else kw("ON")     {xx[t].ticks_off = false;
				xx[t].subticks_off = false;}
	    else kw("COLOR")   {xx[t].ticks_color = next_color;
				xx[t].subticks_color = xx[t].ticks_color;}
	    else kw("LWIDTH")  xx[t].ticks_lwidth = next_exp;
	    else kw("LSTYLE")  next_str(xx[t].ticks_lstyle);
	    else ifer gprint("Expecting TICKS sub command, found {%s} pos %d \n",tk[ct],ct);
	    ct++;
	}
if (gosret==1 || gosret==2) goto end_axisset; /* in axis,label,side,tick,subtick */
goto do_next_line;
/*----------------------------------------------------------------*/
do_subticks:
	ct = 2;
/* 	t = axis_type(tk[1]); */
	while (ct<=ntk)  {
	    if (*tk[ct]==' ') ct++;
	         kw("LENGTH") 	xx[t].subticks_length = next_exp;
	    else kw("OFF")   	xx[t].subticks_off = true;
	    else kw("ON")   	xx[t].subticks_off = false;
	    else kw("COLOR")   	xx[t].subticks_color = next_color;
	    else kw("LWIDTH")  	xx[t].subticks_lwidth = next_exp;
	    else kw("LSTYLE")  	next_str(xx[t].subticks_lstyle);
	    else ifer gprint("Expecting SUBTICKS sub command, found {%s} pos %d \n",tk[ct],ct);
	    ct++;
	}
if (gosret==1 || gosret==2) goto end_axisset; /* in axis,label,side,tick,subtick */
goto do_next_line;
/* ----------------------------------------------------------------*/
do_datasets:
	d = atoi(tk[1]+1); /* dataset number (right$(k$,2))  (0=dn) */
	iid1 = d;
	iid2 = d;
	if (d==0) iid2 = 100;
	if (d!=0) if (dp[d]==NULL) {
		dp[d] = myallocz(sizeof(*dp[ndata]));
		if (dp[d]==NULL) gprint("Memory allocation error, graph dataset \n");
		copy_default(d);
		if (ndata<d) ndata=d;
	}
	for (d=iid1;d<=iid2;d++) {
		if (dp[d]!=NULL) do_dataset(d);
	iid1=iid1;
	}
goto do_next_line;
/*------------------------------------------------------------------*/
/******			Mmmmm !! 				*****/
/*------------------------------------------------------------------*/
}
int zzzz(char *s);
zzzz(char *s)
{
/*	double zz;
/*
/*	g_get_line_width(&zz);
  */
	dbg gprint("graph module %s done line %d \n",s,done_line);

}
draw_graph()
{
	int i,freedata=false;
	double ox,oy;
	done_line = false;
	/* ! Ok we've decoded the commands. now draw the thing. */
	if (g_xsize*g_ysize==0) {
		g_xsize = 10; g_ysize = 10;
		g_get_usersize(&g_xsize,&g_ysize);
	}

	zzzz("begin");
	/* do LETS now */
	for (i=1;i<=nlet;i++) {
		do_let(letstr[i]);
	}
	preview_big();
	/* do_smooth();  dealt with by draw_line()  */
	window_set();
	/* gosub scale_data scale if xmin, ymin xmax ymax for each dataset.*/


	g_get_xy(&ox,&oy);	/* get the origin x,y */
	g_gsave();
	g_get_hei(&g_fontsz);

	set_sizelength();

	zzzz("step1 ");
	for (i=1;i<=2;i++) {
		if (xxgrid[i]) {
			if (i == 1) {
				xx[i].ticks_length = ylength;
				xx[i+2].ticks_length = 0.0000001;
				xx[i].subticks_off = true;
				xx[i+2].subticks_off = true;
				xx[i].subticks_length = ylength;
				xx[i+2].subticks_length = 0.0000001;
			}
			if (i==2) {
				xx[i].ticks_length = xlength;
				xx[i+2].ticks_length = 0.0000001;
				xx[i].subticks_length = xlength;
				xx[i].subticks_off = true;
				xx[i+2].subticks_off = true;
				xx[i+2].subticks_length = 0.0000001;
			}
		}
	}

	if (xlength<ylength) g_fontsz = xlength/23;
	g_set_hei(g_fontsz);

/* 	draw the box */

	if (!g_nobox) {
		g_line(ox+g_xsize,oy);
		g_line(ox+g_xsize,oy+g_ysize);
		g_line(ox,oy+g_ysize);
		g_line(ox,oy);
	}

	/* set graph globals */
	graph_x1 = xbl;
	graph_y1 = ybl;
	graph_x2 = xbl + xlength;
	graph_y2 = ybl + ylength;
	graph_xmin = wxmin;
	graph_xmax = wxmax;
	graph_ymin = wymin;
	graph_ymax = wymax;

	/* Throw away missing values if NOMISS on datasets */
	gr_thrownomiss();

	/* Lets do any filling now. */
	draw_fills();
	g_move(ox,oy);		/* move back to the origin x,y */

	/* draw the bars */
	zzzz("step2 ");
	draw_bars();
	zzzz("step3 ");
	g_move(ox,oy);		/* move back to the origin x,y */

	/* Draw SHADE (psuedo contours) , shade patterns */

	/* Draw axises (moved up, may cause problems)*/
	{
		double h;

		h = g_fontsz;
		for (i=1;i<=4;i++) if (xx[i].base==0) xx[i].base= h;
		xx[1].length = xlength;
		xx[2].length = ylength;
		xx[3].length = xlength;
		xx[4].length = ylength;
	}
	xx[3].type = 3;
	xx[4].type = 4;

	g_move(ox,oy);		/* move back to the origin x,y */
	g_move(xbl,ybl);
	draw_axis(&xx[1]);
	if (abort_key()) goto graph_abort;
	g_move(xbl,ybl);
	draw_axis(&xx[2]);
	if (abort_key()) goto graph_abort;
	g_move(xbl,ybl+ylength);
	draw_axis(&xx[3]);
	if (abort_key()) goto graph_abort;
	g_move(xbl+xlength,ybl);
	draw_axis(&xx[4]);
	if (abort_key()) goto graph_abort;


	/* Draw the lines and  markers */
	draw_lines();
		zzzz("step4 ");

	g_move(ox,oy);		/* move back to the origin x,y */

	/* Draw the error bars */
	draw_err();
	g_move(ox,oy);		/* move back to the origin x,y */
	zzzz("step5 ");

	/* Draw markers, */
	/* (after lines so symbol blanking [white markers] will work) */
	draw_markers();
	if (abort_key()) goto graph_abort;
	g_move(ox,oy);		/* move back to the origin x,y */
		   zzzz("step56");

	if (!done_line) {
		g_hint("You must specify in a DN command wether to draw LINES, or MARKERS");
		g_hint("e.g.   D3 LINE    or    D2 MARKER TRIANGLE");
	}

	graph_freedata(); freedata = true;
/* Axis  were here, I'm moving them up so markers will not be over-written */
	if (*kpos==0) strcpy(kpos,"TR");
	if (khei==0) khei = g_fontsz;
	g_move(ox,oy);
	gdraw_key(koffsetx,koffsety,kpos,khei,knobox);
graph_abort:
	if (freedata==false) graph_freedata();
	g_move(ox,oy);
	graph_free(); /* free memory, and initialize counters for next graph */
	g_grestore();
return;
}

graph_init(void) /* Init all counters for next graph */
{
	range_x1 = range_y1 = 1e30; range_x2 = range_y2 = -1e30;
	ndata = 0;
	nfd = 0;
	g_nbar = 0;
	data_negate[1] = data_negate[2] = 0;	/* a.r. */
	}
void graph_freedata(void)
{
	int i,j;
	for (i=1;i<=g_nbar;i++) { myfree(br[i]); br[i] = 0; }
	for (i=1;i<=nfd;i++) {myfree(fd[i]); fd[i] = 0; }
	for (i=0;i<=ndata;i++) {
		if (dp[i]!=NULL) {
			iffree(dp[i]->xv,"b");
			iffree(dp[i]->yv,"c");
			iffree(dp[i]->miss,"d");
			dp[i]->xv = 0;
			dp[i]->yv = 0;
			dp[i]->miss = 0;
		}
	}
	free_temp();
}
graph_free(void) /* free memory, */
{
	int i,j;

	for (i=0;i<=ndata;i++) {
		if (dp[i]!=NULL) {
			iffree(dp[i]->key_name,"a");
			iffree(dp[i]->bigfile,"a");
			iffree(dp[i]->xv,"b");
			iffree(dp[i]->yv,"c");
			iffree(dp[i]->miss,"d");
			myfrees(dp[i],"dp");
		}
		dp[i] = 0;
	}
	for (i=1;i<=4;i++) {
	  iffree(xx[i].title,"t");
	  for (j=0;j<=xx[i].nnam;j++) {
		iffree(xx[i].names[j],"q");
		xx[i].names[j] = NULL;
	  }
	}
}
iffree(void *p, char *s)
{
	if (p!=NULL) myfrees(p,s);
}
set_sizelength()
{
	/* ! set up some more constants */
	double ox,oy;
	g_get_xy(&ox,&oy);	/* get the origin x,y */
	if (g_hscale==0) g_hscale = .7;
	if (g_vscale==0) g_vscale = .7;

	xbl = ox + (g_xsize/2)-(g_xsize*g_hscale/2);
	ybl = oy + (g_ysize/2)-(g_ysize*g_vscale/2);
	xlength = g_xsize*g_hscale;
	ylength = g_ysize*g_vscale;
	g_fontsz = ylength/23;

}
freedataset(int d)
{
	int i,c=0;
	for (i=1;i<=ndata;i++) {
		if (dp[i] == NULL) c++;
		else if (dp[i]->xv == NULL) c++;
		if (c==d) return i;
	}
	return ndata + d - c;
}
alloc_temp(int ntmp)
{
	double *a;
	int *b;
	if (ntmp < (ntmp_alloc-20)) return;
	ntmp_alloc = 50 + 2 * ntmp;
	a = myallocn(ntmp_alloc,sizeof(double));
	b = myallocn(ntmp_alloc,sizeof(int));
/*	if (a==0 || b==0) {
		gprint("Unable to allocate memory for dataset \n");
		gle_abort("No memory for dataset\n");
	}
*/
	if (tmpf != NULL) {
		memcpy(a,tmpf,(2+ntmp)*sizeof(double));
		memcpy(b,tmpmiss,(2+ntmp)*sizeof(int));
		myfrees(tmpf,"tmpfree"); myfree(tmpmiss);
	}
	tmpf = a; tmpmiss = b;
}
free_temp()
{
	if (tmpf==NULL) return;
	myfrees(tmpf,"tmpfree2"); myfree(tmpmiss);
	tmpf = 0; tmpmiss = 0;
	ntmp_alloc = 0;
}
copy_default(int dn)
{
	memcpy(dp[dn],dp[0],sizeof(*dp[0]));
	dp[dn]->key_name = NULL;
	dp[dn]->bigfile = NULL;
	dp[dn]->xv = NULL;
	dp[dn]->yv = NULL;
	dp[dn]->miss = NULL;
}
