plt - Software for 2D Plots 2.5

File: <base>/plt-2.5a/classic/text.c (9,677 bytes)
/*	plt/text.c		Paul Albrecht		Sept 1987

	Copyright (C) Paul Albrecht 1988.  All rights reserved.

	Last Update:	May 21, 1989
	EMACS_MODES:	tabstop=4
*/

#include	"plt.h"
#include	"axis.h"
#include	"text.h"
#include	"optn.h"


TextInit( psdel )	/* initalize the font groups a, f, l, p and t */
{
char	changes[MAXLINE];

	sprintf( changes, "P%g,W3,Ea", 14.0+psdel );
	FontGroupDef( "a", changes );
	sprintf( changes, "P%g,W3,Ef", 14.0+psdel );
	FontGroupDef( "f", changes );
	sprintf( changes, "P%g,W3,El", 15.0+psdel );
	FontGroupDef( "l", changes );
	sprintf( changes, "P%g,W2,Ep", 12.0+psdel );
	FontGroupDef( "p", "P12,W2,Ep" );
	sprintf( changes, "P%g,W4,Et", 16.0+psdel );
	FontGroupDef( "t", changes );
}


MakeGraphTitle( argv )
char	*argv[];
{
long	time(), seconds;
Ptype	n, x, y, xsize, ysize;
char	*ptr, *ctime(), *getenv(), str[50], titleText[120];

	if( !(omode & TITLES) )
		return;
			
	if( title.text == 0 ) {
		titleText[0] = 0;
		while( *argv ) {
			strcat(titleText, *argv++);
			strcat(titleText, " " );
		}
		if( strlen(titleText) > 0 )
			strcat( titleText, "-- <" );

		ptr = getenv( "LOGNAME" );
		if( ptr ) {
			strcat( titleText, ptr );
			strcat( titleText, "-" );
		}

		time( &seconds );
		ptr = ctime( &seconds );
		n = (ptr[8] == ' ') ? 9 : 8;
		sprintf( str, "%.5s-%.4s%d>",
			&ptr[11], &ptr[4], atoi(&ptr[n]) );
		strcat( titleText, str );
		title.text = titleText;
	}
	else
		if( strlen(title.text) == 0 )
			return;

	FontGroupSelect( "t", title.fgName );

	x = (xwmin + xwmax)/2;
	if( theight == 0 ) {
		strsize( title.text, &xsize, &ysize, 0.0 );
		y = ywmax + (int)((yfract+0.4)*ysize + yfract*yinch/12);
		title.just = "CB";
	}
	else
		y = ywmin + (int)((ywmax-ywmin)*theight);

	plabel( title.text, x, y, title.just, 0.0 );
}

/****************** Output user defined labels ***********************/

TextDraw( l )
LblPtr	l;
{
short	n, nc, x, y, xsize, ysize;
char	c, lbl[MAXLINE];

	if( l->text == 0 || *l->text == 0 )
		return;

	FontGroupSelect( "l", l->fgName );
	transform( &x, &y, l->xpos, l->ypos, 0.5, l->coord );

	nc = 0;
	c = 1;
	while( c ) {
		n = 0;
		do {	c = l->text[nc++];
			lbl[n++] = (c == '\n') ? 0 : c;
		} while( c && c != '\n');

		plabel( lbl, x, y, l->just, l->angle );
		strsize( lbl, &xsize, &ysize, l->angle );
		if( fabs(l->angle) < 1 )
			y -= ysize;
		else	x += xsize;
	}
}

/******* Read plotting labels for text scatterplots **********/

ReadStrings( ps )	/* can be called to add to ps also */
PStrPtr	ps;
{
FILE	*fp;
short	k;
char	c, *str, line[200];

	if( ps->file ) {
		fp = fopen( ps->str, "r" );
		if( fp == 0 )
			err( YES, "Can't open string file %s", ps->str );
	}
	else	str = ps->str;

	while( YES ) {
		if( ps->file ) {
			if( fgets(line,sizeof(line),fp) == NULLS )
				break;
			k = strlen(line);
			if( line[k-1] == '\n' )
				line[k-1] = 0;
		}
		else {	if( *str == 0 )
				break;
			for( k=0;  (c=str[k]) && c != ' ' && c != '\n'; k++ )
				line[k] = c;
			line[k] = 0;
			str += (c == 0) ? k : k+1;
		}
		if( ps->n == ps->nmax )
			ps->list = (char **)azmem(ps->list,&ps->nmax,50,sizeof(*ps->list) );
		ps->list[ps->n++] = StringSave( line );
	}

	ps->just = (ps->just == 0) ? "CC" : JustMap( ps->just );

	if( ps->file )
		fclose( fp );
}

/******** Map user specified justification to a two character string *********/

char	*JustMap( userJust )
char	*userJust;
{
static	char	just[3];
short	n;

	for( n=0;  n < 2;  n++ ) {
		just[n] = (userJust[n] == 0) ? 0 : userJust[n];
		if( just[n] >= 'a' && just[n] <= 'z' )
			just[n] &= ~040;
	}

	if( just[0] == 'C' && just[1] == 0 )
			return( "CC" );		
	else	if(  just[1] == 0 && (just[0] == 'L' || just[0] == 'D') )
			return( "LB" );		
	else	if(  just[1] == 0 && (just[0] == 'R' || just[0] == 'U') )
			return( "RB" );		

	return( StringSave(just) );
}

/*************** Set font type, point size, etc ******************/

FontGroupSelect( dflt_fgName, fgName )
char	*dflt_fgName, *fgName;
{
PtrUnion	arg0, arg1;
FgPtr		fg;
double		scl;

	if( fgName != 0 ) {
		if( (fg=FontGroupFind(fgName,NO)) == 0 )
			/* use fgName as changes to make to default fgroup */
			fg = FontGroupCat( dflt_fgName, fgName );
	}
	else {
		if( dflt_fgName == 0 )
			err( YES, "Bad call to FontGroupSelect()" );
		fg = FontGroupFind( dflt_fgName, YES );
	}

	arg0.c = fg->gelem;
	special( GRAPHELEMENT, arg0, arg1 );

	if( strcmp(old_lm,fg->lm) != 0 ) { /* must precede to point size set */
		arg0.c = fg->lm;
		special( SETLINEMODE, arg0, arg1 );
	}
	arg0.c = fg->color;
	special( SETCOLOR, arg0, arg1 );

	if( oldGrayLevel < 0 || oldGrayLevel != fg->gray ) {
		oldGrayLevel = fg->gray;
		arg0.d = &oldGrayLevel;
		special( SETGRAY, arg0, arg1 );
	}
	if( old_lw < 0 ||  old_lw != fg->lw ) {
		old_lw = fg->lw;
		arg0.d = &old_lw;
		special( SETLINEWIDTH, arg0, arg1 );
	}

	if( fixed_font || (old_font != 0 &&
		strcmp(fg->font,old_font) == 0 && fg->ps == old_ps) )
			return;

	scl  = fg->ps/default_ps;
	chht = p->ch * scl + 0.5;
	chwd = p->cw * scl + 0.5;

	old_font = fg->font;
	old_ps = fg->ps;
	arg0.c = old_font;
	arg1.d = &old_ps;
	special( SETFONT, arg0, arg1 );
}

/****** Define the parameters for a font group ********/

FontGroupDef( fgName, specs )
char	*fgName, *specs;
{
FgPtr	fg;

	if( specs == 0 )
		return;

	if( fgName == 0 || strcmp(fgName,"all") == 0 ) {
		FontGroupDef( "a", specs );
		FontGroupDef( "f", specs );
		FontGroupDef( "l", specs );
		FontGroupDef( "p", specs );
		FontGroupDef( "t", specs );
	}	
	else {	if( (fg=FontGroupFind(fgName, NO)) == 0 )
			fg = FontGroupInit( fgName );

		FontGroupModify( fg, specs );
	}
}

/****** Create a new font group as a modified version of an old one ******/

FgPtr	FontGroupCat( fgName, changes )
char	*fgName, *changes;
{
FgPtr	fg, FontGroupInit();
char	newfgName[MAXLINE];

	sprintf( newfgName, "%s%s", fgName, changes );
	fg = FontGroupFind( newfgName, NO );
	if( fg != 0 )
		return( fg );

	fg = FontGroupInit( newfgName );
	*fg = *FontGroupFind( fgName, YES );
	fg->name = StringSave( newfgName );

	FontGroupModify( fg, changes );
	return( fg );
}

/***** Modify an existing font group according to the specs in `changes' ****/

FontGroupModify( fg, changes )
FgPtr	fg;
char	*changes;
{
FgPtr	fgnew;
short	errFlag;
char	*cp, *fgName;

	errFlag = NO;
	cp = changes;

	if( *cp == '(' || *cp == '[' )
		cp++;

	while( *cp ) {
		if( *cp == ')' || *cp == ']' ) {
			cp++;
			while( *cp == ' ' )
				cp++;
			if( *cp == 0 )
				break;
			/* go get the error */
		}
		switch( *cp++ ) {
			case ' ':
			case ',':
			case '\t':
				break;
			case GCOLOR:
				errFlag |= !getstr( &cp, &fg->color );
				break;
			case GELEMENT:
				errFlag |= !getstr( &cp, &fg->gelem );
				break;
			case GFONT:
				errFlag |= !getstr( &cp, &fg->font );
				break;
			case GGRAY:
				errFlag |= !getdbl(&cp,&fg->gray);
				if( fg->gray > 1)
					fg->gray = 1;
				break;
			case GLINEMODE:
				errFlag |= !getstr( &cp, &fg->lm );
				checklm( fg );
				break;
			case GPS:
				errFlag |= !getdbl( &cp, &fg->ps );
				break;
			case GLINEWIDTH:
				errFlag |= !getdbl( &cp, &fg->lw );
				break;
		   default:
				cp--;
				errFlag |= !getstr( &cp, &fgName );
				fgnew = FontGroupFind( fgName, NO );
				if( fgnew == 0 )
					errFlag = YES;
				else {
					fgName = fg->name;
					*fg = *fgnew;
					fg->name = fgName;
				}
				break;
		}

		if( errFlag ) {
			err( YES, "Font group syntax error `%s'", changes );
			break;
		}
	}
}


FgPtr	FontGroupFind( fgName, mustFind )
char	*fgName;
Boolean	mustFind;
{
FgPtr	fg;
short	n;
	
	for( n=0;  n < nfgrps;  n++ ) {
		fg = &fgrps[n];
		if( strcmp(fg->name,fgName) == 0 )
			return( fg );
	}
	if( mustFind )
		err( YES, "No font group `%s'", fgName );
	return( 0 );
}


FgPtr	FontGroupInit( fgName )
char	*fgName;
{
FgPtr	fg;

	if( nfgrps == maxfgrps )		
		fgrps = (FgPtr)azmem(fgrps,&maxfgrps,6,sizeof(*fgrps));

	fg = &fgrps[nfgrps++];
	fg->name = fgName;
	fg->font = DEFAULT_FONT;
	fg->ps = DEFAULT_PS;
	fg->lw = DEFAULT_LW;
	fg->gray = PS_BLACK;
	fg->lm = "solid";
	fg->color = "";
	fg->gelem = "";
	return( fg );
}


getstr( cpp, strp )
char	**cpp, **strp;
{
short	n;
char	*cp, str[MAXLINE];

	while( **cpp == ' ' )
		(*cpp)++;
	n = 0;
	cp = *cpp;
	while( *cp ) {
		if( *cp == ' ' || *cp == ',' || *cp == ')' || *cp == ']' )
			break;
		str[n++] = *cp++;
	}
	str[n] = 0;

	if( *cpp != cp ) {
		*cpp = cp;
		*strp = StringSave( str );
		return( YES );
	}
	else	return( NO );

}


getdbl( cpp, dblp )
char	**cpp;
double	*dblp;
{
double	dbl, dec;
char	*cp, operation;

	while( **cpp == ' ' )
		(*cpp)++;
	dbl = 1e-6;
	cp = *cpp;

	if( *cp == '+' || *cp == '-' || *cp == '*' || *cp == '/' )
		operation = *cp++;
	else
		operation = 0;

	while( *cp >= '0' && *cp <= '9' ) {
		dbl = 10*dbl + ((*cp++ -'0')&0177);
	}

	if( *cp == '.' ) {
		dec = .1;
		cp++;
		while( *cp >= '0' && *cp <= '9' ) {
			dbl += dec * ((*cp++ -'0')&0177);
			dec *= 0.1;
		}
	}

	if( *cpp != cp ) {
		*cpp = cp;
		switch( operation ) {
			case '+':	*dblp += dbl;	break;
			case '-':	*dblp -= dbl;	break;
			case '*':	*dblp *= dbl;	break;
			case '/':	*dblp /= dbl;	break;
			default:	*dblp = dbl;	break;
		}
		return( YES );
	}
	else	return( NO );
}


checklm( fg )
FgPtr	fg;
{
static	struct	{
	char	*name;
	short	n;
	}	*l, lm[] = {	/* the first 5 must appear first !!!!!!! ... */
	"solid", 0, "dotted", 1, "shortdashed", 2,
	"dotdashed", 3, "longdashed", 4, 
	"0", 0, "1", 1, "2", 2, "3", 3, "4", 4, "5", 5,
	"dash", 2 };
short	n;

	for( l=lm;  l < ENDP(lm);  l++ ) {
		n = strlen(fg->lm);
		if( strcmp(l->name,fg->lm) == 0 || strncmp(l->name,fg->lm,n) == 0 ) {
			fg->lm = lm[l->n].name;	/* ... and this is why !!!!!!!! */
			return;
		}
	}
	err( YES, "No linemode type `%s'", fg->lm );
}