plt - Software for 2D Plots 2.5
(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 );
}