/* @(#)aglchar.c	19.1 (ES0-DMD) 02/25/03 13:53:03 */
/*===========================================================================
  Copyright (C) 1995 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  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.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/* @(#)aglchar.c	19.1  (OAA-ASTRONET) 02/25/03 13:53:03   */
/*
 * HEADER : aglchar.c      - Vers 3.6.006  - Feb 1994 -  L. Fini, OAA
 *                         - Vers 3.6.005  - Oct 1992 -  L. Fini, OAA
 */




/*                          CHARACTER GENERATOR                              */




#include <aglenvr.h>
#include <aglstat.h>




#include "aglfonts.c"


#define SLANTFACTOR 0.30



static struct AGL_font fonts[NFONTS];   /* character font descriptions      */



static struct AGL_cmod chstack[NCHLEVELS];
static int chstack_pt=0;
static int chstack_tp=FALSE;	/* If TRUE: pop the stack on entry to      */
				/*          AGL_mchar()                    */

static void AGL_chzero()	/* Clear the metacharacter stack           */
{				/* To be called prior of beginning the     */
chstack_pt=0;			/* interpretation of a string so that      */
chstack_tp=FALSE;		/* nesting errors do not cumulate between  */
}				/* strings                                 */

static void AGL_chpush(chmod)
struct AGL_char *chmod;		/* Character descriptor to push onto stack */
{
if(chstack_pt<NCHLEVELS) {
	chstack[chstack_pt].the_char = chmod->modifier.the_char;
	chstack[chstack_pt].font = chmod->modifier.font;
	chstack[chstack_pt].lwdt = chmod->modifier.lwdt;
	chstack[chstack_pt].mfact = chmod->modifier.mfact;
	chstack[chstack_pt].vshift = chmod->modifier.vshift;
	chstack[chstack_pt].slant = chmod->modifier.slant;
	chstack[chstack_pt].color = chmod->modifier.color;
	chstack_pt++;
}
}

static void AGL_chpop(chmod)
struct AGL_char *chmod;		/* Character descriptor to pop from  stack */
{
if(chstack_pt-->0) {
	chmod->modifier.the_char = chstack[chstack_pt].the_char ;
	chmod->modifier.font = chstack[chstack_pt].font ;
	chmod->modifier.lwdt = chstack[chstack_pt].lwdt ;
	chmod->modifier.mfact = chstack[chstack_pt].mfact ;
	chmod->modifier.vshift = chstack[chstack_pt].vshift ;
	chmod->modifier.slant = chstack[chstack_pt].slant ;
	chmod->modifier.color = chstack[chstack_pt].color ;
}
}


static char *mtable[] = {		/* Metasequence table                */
		/*	name	command	                                     */
		/*			N.B.: Names must be sorted, values   */
		/*			      are separated by a single tab  */ 
		/*			      if there is a number after the */
		/*			      tab it is a font switch  for   */
		/*			      the following character only,  */
		/*			      If it is a "!" it is a perma-  */
		/*			      nent font switch.              */
		/*			      if it is a ? the following is  */
		/*                            a color code                   */
			"AA	2A",
			"Alpha	1A",
			"Aquarius	4[",
			"Aries	4-",
			"Beta	1B",
			"Cancer	4:",
			"Capricorn	4@",
			"Chi	1X",
			"Delta	2D",
			"Earth	2)",
			"Epsilon	1E",
			"Eta	1H",
			"Gamma	2G",
			"Gemini	4/",
			"Iota	1I",
			"Jupiter	4%",
			"Kappa	1K",
			"Lambda	2L",
			"Leo	4;",
			"Libra	4=",
			"Mars	4$",
			"Mercury	4!",
			"Moon	4*",
			"Mu	1M",
			"Neptune	4(",
			"Nu	1N",
			"Omega	2W",
			"Omicron	1O",
			"PI	2P",
			"Phi	2F",
			"Pisces	4]",
			"Pluto	4)",
			"Psi	2Y",
			"Rho	1R",
			"Sagittarius	4?",
			"Saturn	4&",
			"Scorpio	4>",
			"Sigma	2S",
			"Sqrt	2^",
			"Tau	1T",
			"Taurus	4{",
			"Theta	2Q",
			"Upsilon	2U",
			"Uranus	4'",
			"Venus	4\"",
			"Virgo	4<",
			"Xi	2X",
			"Zeta	1Z",
			"aleph	2H",
			"alpha	2a",
			"asteroid	4,",
			"beta	2b",
			"bigcirc	2O",
			"black	?1",
			"blue	?4",
			"cents	2C",
			"chi	2c",
			"circ	3`",
			"clover	2@",
			"clubsuit	3~~",
			"comet	4+",
			"cyan	?7",
			"dag	2[",
			"ddag	2]",
			"default	!0",
			"delta	2d",
			"diamond	3}",
			"div	2/",
			"downarrow	2N",
			"epsilon	2e",
			"equinox	4^",
			"equiv	2=",
			"eta	2h",
			"firtree	2v",
			"gamma	2g",
			"ge	2>",
			"greek	!2",
			"green	?3",
			"hbar	2Z",
			"heart	3|",
			"infty	2B",
			"int	2:",
			"iota	2i",
			"italic	!i",
			"kappa	2k",
			"lambda	2l",
			"larrow	2~~",
			"le	2<",
			"magenta	?6",
			"mp	2-",
			"mu	2m",
			"nabla	2J",
			"ne	2?",
			"nu	2n",
			"odot	2(",
			"oint	2;",
			"old	!4",
			"omega	2w",
			"omicron	2o",
			"oplus	2)",
			"otimes	2K",
			"palmtree	2R",
			"paragraph	2&",
			"parallel	2|",
			"partial	2j",
			"perp	2T",
			"phi	2f",
			"pi	2p",
			"pm	2*",
			"propto	2,",
			"psi	2y",
			"red	?2",
			"rho	2r",
			"rightarrow	2_",
			"roman	!1",
			"script	!3",
			"shield	2V",
			"sigma	2s",
			"snow	4_",
			"spade	3}",
			"sqrt	2`",
			"sum	2$",
			"tau	2t",
			"theta	2q",
			"times	2*",
			"tiny	!5",
			"uparrow	2M",
			"upsilon	2u",
			"varepsilon	2!",
			"varphi	2#",
			"vartheta	2\"",
			"white	?8",
			"xi	2x",
			"yellow	?5",
			"zeta	2z",
};

static int my_cmp(s1,s2)	/* Minimum maching string compare       */
char *s1, *s2;
{
int ret=0;
for(;;) {
	int c1= *s1++, c2= *s2++;
	if((c1=='\0')||isspace(c1)||(c2=='\0'))
		break;
	if((ret = c1-c2)!=0)
		break;
}
return ret;
}

#define LAST  (sizeof(mtable)/sizeof(char *) - 1)

static char *AGL_lseq(string,my_char)	/* Execute a long metasequence  */
char *string;
struct AGL_char *my_char;	/* Output modifier for characters    */
{
int first,last,middle;
int cmp=(-1);
char *pt;

first=0;
last=LAST;

while (last>=first) {
	middle = (last+first)/2;
	if((cmp=my_cmp(string,mtable[middle]))==0)
		break;
	if(cmp < 0)
		last=middle-1;
	else 
		first=middle+1;
}
if(cmp==0) {			/* The sequence has been found              */
	pt=strchr(mtable[middle],'	')+1;

	switch(*pt) {
	case '!':				/* font change         */
		pt++;
		if(*pt=='i') {
			my_char->modifier.slant=SLANTFACTOR;
		} else {
			my_char->modifier.font= *pt - '0';
			my_char->modifier.the_char = '\0';
		}
		break;
	case '?':				/* Color change           */
		pt++;
		middle= *pt++-'0';
		if((middle>=1)&&(middle<=8)) 
			my_char->modifier.color=
			(AGL_status.actidx[AGL_status.devid]).colors[middle];
		break;
	default: 				/* Return the character   */
		AGL_chpush(my_char);
		chstack_tp=TRUE;
		my_char->modifier.font= *pt++ - '0';
		my_char->modifier.the_char = *pt;
		break;
	}
	pt=strchr(string,' ');	/* skip after next blank in input string */
	if(pt!=NULL)
		pt++;
	else
		pt=strchr(string,'\0');	
} else
	pt=string;

return pt;
}







/*****************************************************************************/
/*                        aglchrdf (Internal AGL use)                        */

/* Font file reading procedure                                               */

/* A new character font structure is allocated with data read from "filnam"  */

/* Font file structure is as follows:                                        */

/*  header                   (Header line to discard when reading)           */
/*  <first>  <number>  <nbytes>  <c_gap> <up> <down> <fscale>                */

/*  <nbyt1>  <chwd1>  <index1>            }                                  */
/*  <nbyt2>  <chwd2>  <index2>            }  Totally                         */
/*  <nbyt3>  <chwd3>  <index3>            }                                  */
/*  <nbyt4>  <chwd4>  <index4>            }  <number>                        */
/*  .......  .......  ........            }                                  */
/*  .......  .......  ........            }  lines                           */
/*  .......  .......  ........            }                                  */

/*  code1 code2 code3 ......              }                                  */
/*  ..... ..... ..... ......              }   Totally                        */
/*  ..... ..... ..... ......              }                                  */
/*  ..... ..... ..... ......              }   <nbytes>                       */
/*  ..... ..... ..... ......              }                                  */
/*  ..... ..... ..... ......              }    codes                         */
/*  ..... ..... ..... ......              }                                  */
/*  ..... ..... ..... ......              }                                  */

/* Where:   <first>  is the first ascii code defined (usually 32 (space))    */
/*          <number> is the number of characters defined, so that the last   */
/*                   ascii code defined is (<first>+<number>-1)              */
/*                   This is also the number of three elements rows in the   */
/*                   following part of the file                              */
/*          <nbytes> is the number of codes used to describe character draw- */
/*                   ing coordinates and commands. It is equal to the number */
/*                   of codes in the third part of the file                  */
/*          <c_gap>  Number of pixels between characters (average)           */
/*          <up>     is the upward extension of an uppercase character with  */
/*                   respect to the character origin (see below). It should  */
/*                   be usually equal to the height of the character "l". An */
/*                   integer positive number of pixels.                      */
/*          <down>   is the downward extension of charachters such as        */
/*                   "p" and "q" with respect to the character origin (see   */
/*                   below). An integer positive number of pixels.           */
/*          <scale>  is a scaling factor to allow complex fonts to be speci- */
/*                   fied with optimum definition. The standard font width   */
/*                   is 5, so if the medium width of a font is, say, 10, the */
/*                   scale factor should be set at 0.5                       */

/* Then for each character:                                                  */

/*          <nbyt.>  is the number of codes needed to define the caracter    */
/*          <chwd.>  is the character width in pixel (including a 1 pixel    */
/*                   space between this character and the next)              */
/*          <index.> is the index of the first code defining the character   */
/*                   into the vector of codes (so that the index of the last */
/*                   one is: (<index.>+<nbyt.>-1)                            */

/* Then all drawing codes follow.  Drawing codes are polyline coordinate     */
/* couples. Each polyline is terminated by the value 0.                      */
/* Coordinates are absolute with respect to the origin of the character box  */
/* (the left bottom corner of a box ideally enclosing a capital letter).     */
/* (x,y) coordinates are decimal numbers (in the range :[-127,127]) coded    */
/* excess 128 (i.e.: coordinate 0 is 128,  coordinate -127 is 1, coordinate  */
/* +127 is 255.                                                              */

/* E.g.: the character "/" supposed to be drawn as a single line across the  */
/*       character box could be encoded as:                                  */

/*            129 128 133 133                                                */
/*             ^   ^   ^   ^                                                 */
/*             |   |   |   |                                                 */
/*             |   |   |   |                                                 */
/*             |   |   |   |                                                 */
/*  (1,0)------+---+   |   |                                                 */
/*                     |   |                                                 */
/*                     |   |                                                 */
/* .. and draw to      |   |                                                 */
/*                     |   |                                                 */
/*  (5,5)--------------+---+                                                 */

/* The corresponding <chwd.> would be 6 (5+1), and <nbyt.> would be 4        */


static void aglchrdf(font)
int font;                    /* Font slot to use                           */
{
FILE *id;
int j;
extern void AG_DMSG();
extern FILE *AG_STDO();
int c1,c2,c3;
int ch;
float scale;
     
AGL_status.errstat=FNTNUMERR;
if ( (font<0 || font>=NFONTS) ||
     (fonts[font].index != NULL) )  
	return;

id = AG_STDO(fonts[font].fontnam,".nfn",0);

if(id == NULL) {
	AG_DMSG("... not","found");
	fonts[font].index = NULL;
	AGL_status.errstat=FNTFILERR;
	return;
}

while((ch=getc(id))=='#') 			/* Discard header lines    */
	while(getc(id)!='\n');
ungetc(ch,id);

fscanf(id,"%d %d",&fonts[font].fcode,          /* read first code and ... */
                  &fonts[font].nchars);        /* number of codes         */
fscanf(id,"%d",&fonts[font].nbytes);           /* number of descr bytes   */
fscanf(id,"%d",&c1);
fscanf(id,"%d",&c2);
fscanf(id,"%d",&c3);
fscanf(id,"%f",&scale);

fonts[font].fscale  = scale;
fonts[font].c_gap = c1;
fonts[font].maxup = c2;
fonts[font].maxdown = c3;

fonts[font].index =(short *)calloc(fonts[font].nchars,sizeof(short));
fonts[font].chrwdt=(unsigned char *)calloc(fonts[font].nchars,sizeof(char));
fonts[font].dsclen=(unsigned char *)calloc(fonts[font].nchars,sizeof(char));
fonts[font].cbuffr=(unsigned char *)calloc(fonts[font].nbytes,sizeof(char));

if(fonts[font].cbuffr == NULL) {
	fclose(id);
	free((char *)fonts[font].index);
	free((char *)fonts[font].dsclen);
	free((char *)fonts[font].chrwdt);
	fonts[font].index=NULL;
	AGL_status.errstat=(MEMORYERR);
	return;
}

for(j=0;j<fonts[font].nchars;j++) {	 /* Read lengths, widths, indexes  */
	fscanf(id,"%d %d %d", &c1, &c2, &c3);
	fonts[font].dsclen[j] = c1;
	fonts[font].chrwdt[j] = c2;
	fonts[font].index[j] = c3;
}

for(j=0;j<fonts[font].nbytes;j++) {		 /* Read data buffer        */
	if(fscanf(id,"%d", &c1) != 1) {
		fclose(id);
		AGL_status.errstat=(FNTRDERR);
		return;
	}
	fonts[font].cbuffr[j] = c1;
}

fclose(id);
AGL_status.errstat=(AGLNOERR);
}




/*****************************************************************************/
/*                     AGL_chinf  (Internal AGL Use)                         */

/* Returns a pointer to the font structure of the given font                 */
/* Return NULL if the font index is invalid or the font is not defined       */

struct AGL_font *AGL_chinf(fontidx)
int fontidx;
{
AGL_status.errstat=AGLNOERR;

if(fontidx<0 || fontidx>=NFONTS) { 
	AGL_status.errstat=FNTNUMERR; 
	return NULL; 
}

if(fonts[fontidx].index == NULL) 
	aglchrdf(fontidx);

if(AGL_status.errstat==AGLNOERR)
	return(fonts+fontidx);
else
	return NULL;
}
#define OPEN_PAREN   	'{'
#define CLOSED_PAREN 	'}'

char *AGL_mchar(chstrg,my_char)	/* Metacharacter interpretation. Returns   */
				/* pointer to the remaining part of the    */
				/* string, and modifiers into the output   */
				/* structure Together with the character   */
				/* to draw                                 */

char *chstrg;			/* input string                      */
struct AGL_char *my_char;	/* Output modifier for characters    */
{
enum {CLEAN,BEGIN_SEQUENCE,LONG_SEQUENCE,END_STRING,END} status;
int goon;
int thischar;

if(chstack_tp==TRUE) {		/* Get back saved status             */
	AGL_chpop(my_char);
	chstack_tp=FALSE;
}

my_char->modifier.the_char = 0;

if(chstrg == NULL) 
	return NULL;
if(*chstrg == '\0') 
	return NULL;

status=CLEAN;
my_char->modifier.backspace=0;
my_char->modifier.newline=0;

goon=TRUE;

do {
	switch(status) {
	case CLEAN:
		thischar = *chstrg++;

		switch(thischar) {

		case '\\':
		case '~':
			status=BEGIN_SEQUENCE;
			break;
		case '\0':
			status=END_STRING;
			break;
		default:
			my_char->modifier.the_char=thischar;
			status=END;
			break;
		}
		break;

	case BEGIN_SEQUENCE:
		thischar = *chstrg++;
		switch(thischar) {	/* Check first character of sequence */
		case BLANK:		/* forced blank (e.g.: at beginning) */
		case '\\':
		case '~':
			my_char->modifier.the_char=thischar;
			status=END;
			break;
		case '^':
			my_char->modifier.vshift += 0.5;
			my_char->modifier.mfact *= 0.833333333333;
			status=CLEAN;
			break;
		case '_':
			my_char->modifier.vshift -= 0.5;
			my_char->modifier.mfact *= 0.833333333333;
			status=CLEAN;
			break;
		case '<':                      /* Execute backspace         */
			my_char->modifier.backspace++;
			status=CLEAN;
			break;
		case '#':				/* Include a marker  */
			sscanf(chstrg,"%d",
			       &(my_char->modifier.the_char));

			AGL_chpush(my_char);	/* Save status to be        */
			chstack_tp=TRUE;	/* Restored at next call    */

			my_char->modifier.font=SYMBFONT;
			while(*chstrg) 
				if(isdigit(*chstrg))
					chstrg++;
				else
					break;
			if(*chstrg==' ')
				chstrg++;
			else
				if(*chstrg != '\0')
					AGL_status.errstat=STRSTXWNG;
			status=END;
			break;
		case '+':
			my_char->modifier.mfact *= 1.2;
			status=CLEAN;
			break;
		case '-':
			my_char->modifier.mfact *= 0.833333333333;
			status=CLEAN;
			break;
		case '0':
			my_char->modifier.font=0;
			status=CLEAN;
			break;
		case '1':			/* Select quality  font      */
			my_char->modifier.font=1;
			status=CLEAN;
			break;
		case '2':			/* Select greek    font      */
			my_char->modifier.font=2;
			status=CLEAN;
			break;
		case '3':			/* Select script   font      */
			my_char->modifier.font=3;
			status=CLEAN;
			break;
		case '4':			/* Select old english font   */
			my_char->modifier.font=4;
			status=CLEAN;
			break;
		case '5':			/* Select tiny roman font    */
			my_char->modifier.font=5;
			status=CLEAN;
			break;
		case '[':			/* use ticKer line width    */
			my_char->modifier.lwdt++;
			status=CLEAN;
			break;
		case ']':			/* use thinner line width   */
			my_char->modifier.lwdt--;
			status=CLEAN;
			break;
		case 'n':			/* Execute "newline"         */
			my_char->modifier.newline += 1;
			status=CLEAN;
			break;
		case '!':
			chstrg++;
			status=LONG_SEQUENCE;
			break;
		case '\0':			/* Unexpected end of string  */
			status=END_STRING;
			break;
		case CLOSED_PAREN:
			AGL_chpop(my_char);
			status=CLEAN;
			break;

		case OPEN_PAREN:
			AGL_chpush(my_char);
			status=CLEAN;
			break;

		default:
			status=LONG_SEQUENCE;
			break;
		}
		break;
	case LONG_SEQUENCE:
		chstrg=AGL_lseq((chstrg-1),my_char);
		if(my_char->modifier.the_char=='\0')
			status=CLEAN;
		else
			status=END;
		break;
	case END_STRING:
		chstrg = NULL;
		goon=FALSE;
		break;
	case END:
		AGL_gcdes(my_char);		/* Get the character descr. */
		goon=FALSE;
		break;
	}
} while (goon);

return(chstrg);
}




/*****************************************************************************/
/*                       AGL_gcdes (Internal AGL use)                        */
      
/* Returns description of a given character into a suitable structure        */

void AGL_gcdes(my_char)
struct AGL_char *my_char;               /* Returns required data            */
					/* my_char->the_char will  be (-1)  */
                                        /* if the font is not available, or */
					/* the first code availabe in the   */
					/* font, if the code is not in the  */
					/* font                             */
{
int thechar=my_char->modifier.the_char;
int thefont=my_char->modifier.font;
double scale;

my_char->modifier.the_char= -1;
AGL_status.errstat=AGLNOERR;

if(fonts[thefont].index == NULL) 
	aglchrdf(thefont);

if(AGL_status.errstat != AGLNOERR) 
	return;

if((thechar < fonts[thefont].fcode)||
   (thechar >= (fonts[thefont].fcode+fonts[thefont].nchars)))
	thechar = fonts[thefont].fcode;

my_char->modifier.the_char = thechar;

thechar -= fonts[thefont].fcode;

scale = fonts[thefont].fscale;
my_char->descriptor.blk_gap = scale * fonts[thefont].c_gap;
my_char->descriptor.heigth  = scale * fonts[thefont].maxup;
my_char->descriptor.down_ext= scale * fonts[thefont].maxdown;
my_char->descriptor.width   = scale * fonts[thefont].chrwdt[thechar];
my_char->descriptor.scale   = scale;
my_char->descriptor.ncodes  = fonts[thefont].dsclen[thechar];
my_char->descriptor.codes   = fonts[thefont].index[thechar] + fonts[thefont].cbuffr;
}



  

/*****************************************************************************/
/*                        AGL_strd (Internal AGL use)                       */

/* Returns dimensions in character generator coordinates of a given string   */
/* The string is scanned to account for metacharacter interpretation.        */

void AGL_strd(chstrg,font,twidth,theigth)
char *chstrg;
int font;
double *twidth;
double *theigth;

/*                   +-------  twidth ---------+                             */
/*               +     ***   *                                               */
/*               |    *   *  *                                               */
/*               |    *   *  *       ****                                    */
/*       theigth |    *****  ****   *      ****                              */
/*               |    *   *  *   *  *      *   *                             */
/*               |    *   *  ****    ****  ****                              */
/*               |                         *                                 */
/*               |                         *                                 */
/*               |                                                           */
/*               |                                                           */
/*               |    *      ****   *       ****                             */
/*               |    *      *   *  ***    *                                 */
/*               |    *      ****   *      *                                 */
/*               |    *      * *    *      *                                 */
/*               |    *      *  *   *   *  *                                 */
/*               +    *****  *   *   ***    ****                             */
/*                                                                           */

{
struct AGL_char my_char;
double hext=0.0, vext=0.0;
double twd,thg;

AGL_status.errstat = AGLNOERR;

my_char.modifier.mfact = 1.0;
my_char.modifier.font = font;
my_char.modifier.vshift=0.0;
my_char.modifier.backspace=0;
my_char.modifier.newline=0;
my_char.modifier.slant=0.0;
my_char.descriptor.blk_gap = 0.0;
my_char.descriptor.heigth = 0.0;
my_char.descriptor.width = 0.0;
my_char.descriptor.down_ext = 0.0;
my_char.descriptor.scale = 0.0;
my_char.descriptor.ncodes = 0;

twd=0.0;
thg=0.0;

AGL_chzero();		/* Clean possible previous nesting errors         */

while ((chstrg=AGL_mchar(chstrg,&my_char))!=NULL) {

	vext = my_char.descriptor.heigth;
	if(my_char.modifier.newline>0) {
		hext -= my_char.descriptor.blk_gap*my_char.modifier.mfact;
		twd=MAX(twd,hext);
		hext=0;
		thg += vext*2.0;
		vext=0;
	} else 
		hext += my_char.descriptor.width*(1-my_char.modifier.backspace)*my_char.modifier.mfact;
}
hext -= my_char.descriptor.blk_gap*my_char.modifier.mfact;
twd=MAX(twd,hext);
thg  += vext;
*twidth = twd;
*theigth = thg;

AGL_chzero();		/* Clean possible nesting errors for subsequent uses */
}





/*****************************************************************************/
/*                        AGL_ch2pl (Internal AGL use)                       */
      
/* Converts the given character into a sequence of polylines                 */


void AGL_ch2pl(my_char,flag)
struct AGL_char *my_char;		/* Character description structure   */
					/* (already filled by AGL_gcdes())   */
int flag;				/* If 0 center the character         */
{
float *XV=my_char->descriptor.XB,*YV=my_char->descriptor.YB;
int maxstrokes=MAX_STROKES;
int maxcoords =CHARPOLYBUFLNG;
int npt=my_char->descriptor.ncodes;
unsigned char *cd=my_char->descriptor.codes;
double xoff,yoff;
int i;
int goon;

AGL_status.errstat = AGLNOERR; 
my_char->descriptor.nstrokes=0;

if(flag==0) {
	xoff = -(my_char->descriptor.width*0.5);
	yoff = -(my_char->descriptor.heigth*0.5);
} else {
	xoff=0.0;
	yoff=0.0;
}

for(goon=TRUE,i=0;(i<maxstrokes)&&goon;i++) {
	int cur_pts;
	cur_pts=0;

	AGL_plmk(XV,YV,maxcoords,0,NORMAL,&(my_char->descriptor.strokes[i]));

	for(;;) { 			/* filling i-th polyline            */
		double auxx,auxy;

		if(*cd == 0) {		/* begin new stroke         */
			cd++;npt--;
			break;
		}
		if(--maxcoords<0) { 
			AGL_status.errstat = CHGBUFOVSEV; 
			return; 
		}
		auxx = (int)(*cd++)-128;
		auxy = (int)(*cd++)-128;
		*XV++ = (auxx+auxy*my_char->modifier.slant) * 
		         my_char->descriptor.scale + xoff;
		*YV++ = auxy * my_char->descriptor.scale + yoff;
		cur_pts++;

		if((npt-=2)<=0){		/* End of character         */
			goon=FALSE;
			break;
		}
	}
	my_char->descriptor.strokes[i].nvects=cur_pts;
	my_char->descriptor.strokes[i].maxvects=cur_pts;
}
if(i>maxstrokes)
	AGL_status.errstat = CHGBUFOVSEV; 
else
	my_char->descriptor.nstrokes=i;
}
  



/*****************************************************************************/
/*                        AGL_cginit (Internal AGL use)                      */
      
/* Character generation structure initialization                             */
/* This routine is to be called at AGL initialization in order to set up     */
/* character generator data structures and the standard AGL character font   */

void AGL_cginit ()
{
int i;

for(i=0;i<NFONTS;i++) {
	fonts[i].fontnam[0] = '\0';
	fonts[i].index = NULL;
	fonts[i].cbuffr= NULL;
	fonts[i].dsclen= NULL;
}

strcpy(fonts[0].fontnam,"standard");
strcpy(fonts[1].fontnam,"quality");
strcpy(fonts[2].fontnam,"greek");
strcpy(fonts[3].fontnam,"script");
strcpy(fonts[4].fontnam,"oldengl");
strcpy(fonts[5].fontnam,"tiny");

strcpy(fonts[SYMBFONT].fontnam,"symbol");

               
fonts[0].fcode=29;   			/* Init standard character font  */
fonts[0].nchars=98;

fonts[0].nbytes=sizeof(stdcbuf);
fonts[0].maxup = 8;
fonts[0].maxdown = 3;
fonts[0].fscale=1.00;                   /* Standard character font       */
fonts[0].c_gap=1;
fonts[0].index=stdidx;
fonts[0].cbuffr=stdcbuf;
fonts[0].dsclen=stdleng;
fonts[0].chrwdt=stdwdt;

fonts[SYMBFONT].fcode=0; 
fonts[SYMBFONT].nchars=NUM_OF_SYMBOLS; 

fonts[SYMBFONT].nbytes=sizeof(symbcbuf);
fonts[SYMBFONT].maxup = 16;
fonts[SYMBFONT].maxdown = 0;
fonts[SYMBFONT].fscale=0.5;
fonts[SYMBFONT].c_gap=2;
fonts[SYMBFONT].index=symbidx;
fonts[SYMBFONT].cbuffr=symbcbuf;
fonts[SYMBFONT].dsclen=symbleng;
fonts[SYMBFONT].chrwdt=symbwdt;
}
