/*this is file hersh.c */
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "ana_structures.h"
#define ABS(x) ((x)>=0?(x):-(x))
#define	MIN(a,b) (((a)<(b))?(a):(b))
#define	MAX(a,b) (((a)>(b))?(a):(b))
#define	VSPACE	14.0
#define	SFAC	0.70
extern	int	tkplot();
extern	struct sym_desc sym[];
extern	struct sym_list		*subr_sym_list[];
extern	float	xfac, yfac;
int	hflag, font = 3, state, nullflag;
byte	*fontbase;
byte	*fontptr[40];
float	callig_xb, callig_yb, theta = 0.0, size = 1.0, dx, dy, sxb, syb;
float	st, ct, x, y, nct, nst, angle;
float	float_arg();
union	types_ptr { byte *b; short *w; int *l; float *f; double *d;};		
/*------------------------------------------------------------------------- */
int ana_callig(narg, ps)
					/* draws Hershy character sets */
int	narg, ps[];
{
int	iq;
char	*s;
nullflag = 1;
					/* first arg must be a string */
iq = ps[0];
if ( sym[iq].class != 2 ) return execute_error(70);
s = (char *) sym[iq].spec.array.ptr;
					/* the rest are scalars */
callig_xb = float_arg( ps[1]);  callig_yb = float_arg( ps[2]);
if (narg > 3 ) size = float_arg( ps[3]);
if (narg > 4 ) theta = float_arg( ps[4]);
if (narg > 5 ) font = int_arg( ps[5]);
if (narg > 6 ) nullflag = int_arg( ps[6]);
return callig2(s);
}
/*------------------------------------------------------------------------- */
int callig2(s)
/* called by either ana_callig or callig, finishes the job */
char	*s;
{
float	xq;
int	ic;
					/* setup context */
angle = theta * 0.017453293;
					/* put into DI form */
xq= size / 1024.;
if (callig_xb >= 1.0 ) callig_xb = callig_xb / xfac;
if (callig_yb >= 1.0 ) callig_yb = callig_yb / yfac;
nct = ct = cos( angle ) * xq;		nst = st = sin(angle) * xq;
					/* setup font */
if (fontchange(font) != 1) return -1;
state = dx = dy = 0; 
while ( (ic = *s++) != 0 ) {		/* decode string */
	/* either a command or a char. to draw */
if ( ic == '$') { if ( hcom( &s) != 1 ) return -1; }
	else if (draw(ic) != 1) return -1;
}
if (nullflag) empty();
return	1;
}
/*------------------------------------------------------------------------- */
int callig(s, xb, yb, fsize, th, ifont, nu)
/* for internal calls, sets variables and calls callig2 */
char	*s;
int	ifont, nu;
float	xb, yb, fsize, th;
{
callig_xb = xb;	callig_yb = yb;	theta = th;	font = ifont;
nullflag = nu;	size = fsize;
return callig2(s);
}
/*------------------------------------------------------------------------- */
int hcom(s)
					/* an inline callig command */
char	**s;
{
int	ic, i1, i2, iq, jq;
float	newsize;
ic = *(*s)++;
switch (ic) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
						/* font change */
ic = ic % 128;
i1 = ic - 48;			/* convert ASCII to binary */
if ( isdigit ( **s ) ) i1 = 10 * i1 + (*(*s)++) - 48;
if (fontchange(i1) != 1) return -1;	break;
case 'A':
case 'a':
				/* move up, no change in size */
callig_xb = callig_xb - st * VSPACE;	dx -= st * VSPACE;
callig_yb = callig_yb + ct * VSPACE;	dy += ct * VSPACE;	state = 1;
break;
case 'E':
case 'e':
				/* move up, change in size */
callig_xb = callig_xb - st * VSPACE;	dx -= st * VSPACE;
callig_yb = callig_yb + ct * VSPACE;	dy += ct * VSPACE;	state = 3;
st *= SFAC;			ct *= SFAC;
break;
case 'I':
case 'i':
				/* move down, change in size */
callig_xb = callig_xb + st * VSPACE;	dx += st * VSPACE;
callig_yb = callig_yb - ct * VSPACE;	dy -= ct * VSPACE;	state = 4;
st *= SFAC;			ct *= SFAC;
break;
case 'B':
case 'b':
				/* move down, no change in size */
callig_xb = callig_xb + st * VSPACE;	dx += st * VSPACE;
callig_yb = callig_yb - ct * VSPACE;	dy -= ct * VSPACE;	state = 2;
break;
case 'N':
case 'n':
				/* restore normal */
callig_xb = callig_xb - dx;
callig_yb = callig_yb - dy;
dx = dy = state = 0;	st = nst;	ct = nct;
break;
case '$':
case '<':
case '>':
	if (draw(ic) != 1) return -1;	break;
case 'S':
case 's':
				/* save position */
sxb = callig_xb;	syb = callig_yb;	break;
case 'R':
case 'r':
				/* restore position */
callig_xb = sxb;	callig_yb = syb;	break;
case 'X':
case 'x':
				/* restore entry font */
if (fontchange(font) != 1) return -1;	break;
case 'C':
case 'c':
				/* size change */
sscanf( *s, "%f", &newsize);
st = st * (newsize / size );	ct = ct * (newsize / size );
/* that was easy, but now figure out where we start again in string */
iq = jq = 0;
while ( ic = *(*s)++ ) { if ( isdigit(ic) != 1 ) {
	/* maybe done, check for allowed non digits */
  if ( ic != '.') { iq++; if (iq > 1 ) break; } else
  { if ( ic != 'f' || ic != 'e' || ic != 'F' || ic != 'f')
  	{ jq++; if (jq > 1 ) break; }
  break; }
} }
break;
case '.':
				/* draw a bullet */
if (fontchange(20) != 1) return -1;
if (draw('B') != 1) return -1;
if (fontchange(font) != 1) return -1;	break;
case '*':
				/* draw a star */
if (fontchange(20) != 1) return -1;
if (draw('E') != 1) return -1;
if (fontchange(font) != 1) return -1;	break;
}			/* end of switch */
return	1;
}
/*------------------------------------------------------------------------- */
int draw(ic)
int	ic;
{
int	nvec, offset, abflag = 0, ll0 = 0, mode, iq, ix, iy, gap;
short	is1, is2;
union	types_ptr p;
union	{ float f; short w[2]; }  spc;	
if ( isprint(ic) == 0 ) { printf("illegal char. in callig\n");  return -1; }
ic -= 32;
p.b = fontbase;
p.b = p.b + 4 * ic;	nvec = (int) *p.b;	gap = (int) *(p.b + 1);
if (nullflag)  {
#ifdef LITTLEENDIAN
is2= *(p.w+1);
#else
is1 = *(p.w + 1);	swab(&is1, &is2, 2);
#endif
offset = (int) is2;

			/* offset is in I*2 amounts */
p.b = fontbase;
p.w += offset;
			/* check if abnormal */
#ifdef LITTLEENDIAN
is1 = *p.w;
#else
is2 = *p.w;	swab(&is2, &is1, 2);
#endif
if ( is1 < 16384 ) { printf("special symbol, sorry - not supported\n");
	return -1; }
while (nvec--) {
#ifdef LITTLEENDIAN
is1 = *p.w++;
#else
is2 = *p.w++;	swab(&is2, &is1, 2);
#endif
iq = (int) is1;
if ( iq & 0x4000 ) mode = 0; else mode = 1;
iy =  ( iq & 0x7f );	ix = ( iq/ 0x7f) & 0x7f;
if (iy > 63) iy = iy-128;	if (ix > 63) ix = ix-128;
ix = ix - ll0;		iy = iy - ll0;		/* for abnormals */

y = (float) ix * st + (float) iy * ct + callig_yb;
x = (float) ix * ct - (float) iy * st + callig_xb;
tkplot( x, y, mode);
}
}
			/* update callig_xb and callig_yb */
callig_xb += ct * (float) gap;		callig_yb += st * (float) gap;
return 1;
}
/*------------------------------------------------------------------------- */
int fontchange(font)
int	font;
{
int	iq, n, i;
short	*pi;
byte	*p;
char	name[80], *ana_hersh;
FILE	*fin;
font = MAX ( font, 3);  if (font > 39) font = 3;
if (fontptr[font] != NULL) { fontbase = fontptr[font]; return 1; }
					/* new font, get font file name */
 /* look for env variable ANA_HERSH */
 ana_hersh = getenv("ANA_HERSH");
 printf("ANA_HERSH = %s\n", ana_hersh);
 if (ana_hersh != NULL) sprintf(name,"%s/font%03d.hex0", ana_hersh, font);
 printf("font name: %s\n", name);
 if (ana_hersh == NULL || (fin = fopen(name,"r")) == NULL) {
 printf("no env variable ANA_HERSH\n");
#if NeXT
sprintf(name,"/me/ana/font/font%03d.hex0",font);
#endif
#if __sgi
sprintf(name,"/usr1/people/shine/ana/font%03d.hex0",font);
#endif
#if defined(__alpha)
sprintf(name,"/usr/users/shine/ana/fonts/font%03d.hex0",font);
#endif
printf("file name = %s\n",name);
if ( (fin = fopen(name,"r")) == NULL)
	{ printf("font file %s not found, default to font 3\n",name);
	if (font == 3) {printf("can't find font003 file\n"); return -1;}
	fontchange(3); return 1; }
 }
					/* read in file */
fscanf(fin,"%d",&n);	n = n/2;
if ( (p = fontptr[font] = (byte *) malloc(n) ) == NULL)
	{ printf("memory problem while reading in font\n"); return -1; }
i = 0;
while (n--) { fscanf(fin, "%2x", &iq); *p++ = iq; }
fontbase = fontptr[font];
fclose(fin);
return	1;
}
/*------------------------------------------------------------------------- */
