home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
- * OKIGRAPH.C
- *
- * Bar Graph Maker for OKIDATA Laserline Printers and HP Compatables.
- *
- * Version 1.2 James Bumgardner 07/88
- * Version 1 James Bumgardner 09/87
- *
- * For Microsoft C, Turbo C or Vax C
- ***********************************************************************/
-
- #include <stdio.h>
- #include <ctype.h>
-
- /* These Constants are oriented to 720/INCH */
- #define HWIDTH 6120 /* Width of Paper */
- #define VWIDTH 7920 /* Height of Graph */
- #define RMARGIN 720 /* Right Margin Clearance */
- #define TMARGIN 1440 /* Top Margin */
- #define SHADOW 35 /* Height/Width of Shadow Shading */
- #define NOTCH 20 /* Length of Y Notches */
-
- int bmargin=2880; /* Bottom Margin - shortens with REDUCE command */
- #define YCLR 100 /* Clearance at top of graph */
- #define HTCHAR 200 /* Clearance for letters */
-
- double **drng,max; /* Pointers to data, Maximum Value */
- char **xrng,**lrng; /* Pointers to text and legends */
- int ranges,elements; /* Dimensions of Data */
- char mlegend;
-
- char ibuf[257];
- char *title;
-
- void *malloc();
- char *strchr();
-
- int linesflg, /* Draw Lines Across Graph To Represent Values */
- shadowflg, /* Draw Shadows on North East Sides */
- darken = 1, /* Darken North East Sides */
- dollarflg, /* Dollar Signs in front of numbers */
- combineflg, /* Combine shading and patterns */
- noabbrev, /* Don't abbreviate Numbers */
- noroundflg; /* Don't Round Up Numbers */
- int ldiv = 0; /* Number of Legends per Line */
- int lmargin = 720; /* Left margin */
-
- /**********************************
- * The Last Frontier!
- * extensive comments end here ...
- **********************************/
-
- main(argc,argv)
- char *argv[];
- {
- FILE *ifile;
- char *p;
- if (argc < 2)
- {
- fprintf(stderr,"OKIGRAPH filename\n");
- exit();
- }
- if ((ifile = fopen(argv[1],"r")) == NULL)
- {
- fprintf(stderr,"Can't open %s for input\n",argv[1]);
- exit();
- }
-
- allocation_pass(ifile);
-
- while (fgets(ibuf,256,ifile)) /* Parse Control File */
- {
- if (ibuf[0] == '\n' || ibuf[0] == 0 || ibuf[0] == ';')
- continue;
- ibuf[strlen(ibuf)-1] = '\0';
- switch (*((short *) ibuf))
- {
- case 'LA': do_literal(ibuf); break;
- case 'TI':
- p = strchr(ibuf,' ');
- ++p;
- title = malloc(strlen(p)+1);
- strcpy(title,p);
- break;
- case 'LM': sscanf(ibuf,"%*s%d",&lmargin); break;
- case 'LD': sscanf(ibuf,"%*s%d",&ldiv); break;
- case 'SH': shadowflg = 1; darken = 2; break;
- case 'DA': darken = 10; break;
- case 'DO': dollarflg = 1; break;
- case 'LI': linesflg = 1; break;
- case 'CO': combineflg = 1; break;
- case 'RE': bmargin = 4000; break;
- case 'BI': noabbrev = 1; break;
- case 'NO': noroundflg = 1; break;
- default:
- if (*((short *) ibuf) == 'L ') get_legend();
- else get_data();
- }
- }
- print_graph();
- }
-
- do_literal(str) /* Process Literal Printer Escape Codes */
- char *str;
- {
- while (isgraph(*str)) ++str;
- while (isspace(*str)) ++str;
- while (*str) {
- if (*str == '^')
- {
- ++str;
- putc(toupper(*str) - '@',stdout);
- }
- else
- putc(*str,stdout);
- ++str;
- }
- }
-
- allocation_pass(ifile) /* Do a pass through file to determine dimensions */
- FILE *ifile; /* Then allocate space */
- {
- int i,n;
- double t,t1,t2,t3,t4,t5,t6,t7,t8,t9,t0;
- static char scanstr[] = "%f%f%f%f%f%f%f%f%f%f";
- ranges = elements = 0;
- while (fgets(ibuf,256,ifile))
- {
- if (sscanf(ibuf,"%f",&t) == 1) {
- ++elements;
- if (ranges == 0)
- ranges = sscanf(ibuf,scanstr,
- &t1,&t2,&t3,&t4,&t5,
- &t6,&t7,&t8,&t9,&t0);
- }
- }
- fseek(ifile,0L,0); /* rewind file */
- fprintf(stderr,"%d ranges, %d elements\n",ranges,elements);
- xrng = (char **) malloc(elements * sizeof(char *));
- lrng = (char **) malloc(ranges * sizeof (char *));
- drng = (double **) malloc(ranges * sizeof(double *));
- for (i = 0; i < ranges; ++i)
- {
- lrng[i] = NULL;
- drng[i] = (double *) malloc(elements * sizeof(double));
- for (n = 0; n < elements; ++n)
- drng[i][n] = 0L;
- }
-
- for (i = 0; i < elements; ++i)
- xrng[i] = NULL;
- }
-
- get_legend() /* Get Legend Text from Control File */
- {
- static int lcnt;
- char *p,l;
- p = &ibuf[2];
- lrng[lcnt] = malloc(strlen(p)+1);
- strcpy(lrng[lcnt],p);
- l = strlen(p);
- if (mlegend < l) mlegend = l;
- if (++lcnt > ranges) ranges = lcnt;
- }
-
- get_data() /* Get Data from Control File */
- {
- static int dcnt;
- int i;
- double v;
- char *p;
-
- if (sscanf(ibuf,"%d",&i) == 0) return;
-
- p = ibuf;
- for (i = 0; i < ranges; ++i)
- {
- while (isspace(*p)) p++;
- if (*p == '\0') break;
- sscanf(p,"%le",&v);
- if (v > max) max = v;
- drng[i][dcnt] = v;
- while (isdigit(*p) || *p == '.') p++;
- if (*p == '\0') break;
- }
- while (isspace(*p)) p++;
- if (*p == '\"' || *p == '\'') ++p;
- if (isprint(*p))
- {
- xrng[dcnt] = malloc(strlen(p)+1);
- strcpy(xrng[dcnt],p);
- }
-
- if (++dcnt > elements) elements = dcnt;
- }
-
- int wgraph,welement,wbar;
- int hgraph,bline;
- double yfact;
-
- #define NO_COMBS 10
- char combtran[] = {0,20,40,80,1,2,3,4,5,6};
- char *locstr = "\033&a%dh%dV";
- char *rulstr = "\033*c%dh%dv0P";
- char *patstr = "\033*c%dh%dv%dg3P";
- char *shdstr = "\033*c%dh%dv%dg2P";
-
- #define locate(x,y) printf(locstr,x,y)
- #define prul(h,w) printf(rulstr,h,w)
- #define ppat(h,w,c) printf(patstr,h,w,c+1)
- #define pcmb(h,w,c) printf(((c % NO_COMBS) < 4)? shdstr : patstr,h,w,combtran[c % NO_COMBS])
-
- int basex,xclear;
-
-
- fix_graph() /* Convert graphs with multiple ranges, 1 element to */
- /* One range, multiple elements (cosmetic fix) */
- {
- int i;
- char *p;
- double *trng;
- if (elements > 1 || ranges == 1 || ranges > 8) return;
- fprintf(stderr,"Switching to better format...\n");
- trng = (double *) malloc(sizeof(double) * ranges);
- for (i = 0; i < ranges;++i)
- trng[i] = drng[i][0];
- drng[0] = trng;
- if (xrng[0] != NULL)
- { /* insert element name into title */
- for (p = title; *p && *((short *) p) != ' '; ++p)
- ;
- if (*((short *) p) == ' ' && strlen(p) >= strlen(xrng[0])+2)
- {
- sprintf(p,", %s",xrng[0]);
- p[strlen(p)] = ' ';
- }
- free(xrng[0]);
- }
- free(xrng);
- xrng = (char **) malloc(ranges * sizeof(char *));
- for (i = 0; i < ranges; ++i)
- xrng[i] = lrng[i];
- lrng[0] = NULL;
- elements = ranges;
- ranges = 1;
- }
-
- print_graph() /* Main Typesetting Routine */
- {
- int i,n,x,y;
- int hbar,y2;
-
- fix_graph();
-
- setup_ylabels();
-
- wgraph = HWIDTH - (lmargin + RMARGIN);
- welement = wgraph / elements;
- xclear = (welement)/8;
- wbar = (welement-(xclear*2))/ranges;
- if (wbar > 480) wbar = 480;
- /* recalculate xclear to take integer error into account */
- xclear = (welement-(wbar*ranges))/2;
-
- hgraph = VWIDTH - (TMARGIN + bmargin);
- bline = TMARGIN + hgraph + YCLR;
- yfact = hgraph / max;
-
- print_title_frame();
-
- print_legends();
-
- draw_ylabels();
-
- printf("\033(s1P"); /* Roman Proportional */
-
- for (i = 0; i < elements; ++i)
- {
- basex = lmargin + welement*i;
- if (xrng[i]) {
- locate(basex + welement/2 - romwidstr(xrng[i])/2,
- bline+HTCHAR);
- printf("%s",xrng[i]);
- }
- basex += xclear;
- for (n = 0; n < ranges; ++n)
- {
- if (drng[n][i] == 0) continue;
- hbar = drng[n][i] * yfact;
- x = basex+wbar*n;
- y = bline-hbar;
- /* Locate */
- draw_box(x,y,wbar,hbar,1,3);
- if (shadowflg) {
- if (n == ranges - 1)
- draw_shadow(x,y,wbar,hbar+SHADOW);
- else {
- y2 = bline - drng[n+1][i]*yfact;
- locate(x+SHADOW,y-SHADOW);
- ppat(wbar-SHADOW,SHADOW,2);
- if (y2 > y-SHADOW) {
- locate(x+wbar,y-SHADOW);
- ppat(SHADOW,y2-(y-SHADOW),2);
- }
- }
- }
- locate(basex+wbar*n,bline-hbar);
- /* Draw Bar */
- if (combineflg)
- pcmb(wbar,hbar,n);
- else
- ppat(wbar,hbar,n);
- }
- }
- putchar(12);
- }
-
- unsigned long tdiv[] = {1000,1000000,1000000000};
- char divc[] = {'K','M','B'};
- unsigned long ydiv;
- int ydecimal,yrng;
-
- setup_ylabels() /* figure out some nice round numbers for left hand side */
- {
- double log10(),pow();
- double mm;
- unsigned long il;
-
- if (max <= 10)
- ydiv = 1;
- else {
- mm = pow(10.0,(double) ((int) log10(max)));
- if (max >= mm * 5)
- ydiv = mm;
- else ydiv = mm/2;
- }
-
- if (max >= 1000000000) yrng = 2;
- else if (max >= 1000000) yrng = 1;
- else yrng = 0;
-
- ydecimal = (ydiv < tdiv[yrng]); /* Check if decimals are needed */
-
- il = (int)(max/ydiv)*ydiv;
-
- /* Show next hightest line if it's close */
- if (noroundflg == 0 && max-il > ydiv / 2)
- max = il+ydiv;
- }
-
- draw_ylabels() /* Draw Numbers and Lines on left edge */
- {
- /* Roman Non-Proportional, Italics Off */
- static char ystr[17];
- unsigned long il;
- int i,y,n;
-
- printf("\033(s10v0p0s0b5T");
-
- /* Y Labels */
- for (il = 0; il <= max; il += ydiv)
- {
- strcpy(ystr,(dollarflg)? "$" : "");
- if (noabbrev || max < 1000 || il == 0)
- sprintf(&ystr[dollarflg],"%d",il);
- else {
- sprintf(&ystr[dollarflg],"%.*f%c",
- ydecimal,(double) il/tdiv[yrng],divc[yrng]);
- }
- y = il*yfact;
- locate(lmargin-720,bline - y);
- printf("%9s",ystr);
- if (linesflg) {
- for (i = 0; i < elements; ++i) {
- basex = lmargin + welement*i;
- locate(basex,bline-y);
- prul(xclear,1);
- basex += xclear;
- for (n = 0; n < ranges; ++n) {
- if (y > drng[n][i]*yfact) {
- locate(basex+wbar*n,bline-y);
- prul(wbar,1);
- }
- }
- locate(basex+wbar*n,bline-y);
- prul(xclear,1);
- }
- }
- else { /* Notch */
- locate(lmargin - NOTCH,bline-y);
- prul(NOTCH,1);
- }
- }
- }
-
- print_title_frame()
- {
- if (title) {
- locate(lmargin,TMARGIN-HTCHAR);
- /* HELVETICA */
- printf("\033&l00\033(0U\033(s1p14.4v0s3b4T");
- printf("%s",title);
- }
- /* draw box around graph */
- draw_box(lmargin,TMARGIN,wgraph,hgraph + YCLR,3,3);
- if (shadowflg)
- draw_shadow(lmargin,TMARGIN,wgraph,hgraph+YCLR);
- }
-
- print_legends()
- {
- int i,x,y;
-
- if (lrng[0]) /* Italics for Legends */
- printf("\033(s%s10v1s0b5T",(mlegend > 16)? "-1p" : "");
-
- if (ldiv == 0)
- {
- if (ranges % 2 == 0 && ranges % 3 != 0) ldiv = 2; /* 2 4 8 10 */
- else ldiv = 3; /* 3 5 6 7 9 11 12 */
- }
- for (i = 0; i < ranges; ++i)
- {
-
- if (lrng[i] == NULL) break;
-
- x = lmargin + (i%ldiv) * (wgraph/ldiv);
- y = bline + 410 + 410 * (i/ldiv);
-
- draw_box(x,y,300,200,1,3);
- if (shadowflg)
- draw_shadow(x,y,300,200);
-
- locate(x,y);
-
- if (combineflg) pcmb(300,200,i);
- else ppat(300,200,i);
-
- locate((x+((mlegend > 22)? 338 : 410)),y+145);
- printf("%s",lrng[i]);
- }
- }
-
-
- draw_box(x,y,w,h,xt,yt)
- {
- locate(x,y);
- prul(w,xt+((w)? darken : 0));
- prul(yt,h);
- locate(x+w,y);
- prul(yt+((h)? darken : 0),h);
- locate(x,y+h);
- prul(w,xt);
- }
-
- draw_shadow(x,y,w,h)
- {
- locate(x+SHADOW,y-SHADOW);
- ppat(w-SHADOW,SHADOW,2);
- if (h > 0) {
- locate(x+w,y-SHADOW);
- ppat(SHADOW,h,2);
- }
- }
-
-
- /* Table to determine width of Times Roman Characters from OKIDATA LASERLINE */
- /* This was borrowed from a Word Perfect Printer Driver */
-
- unsigned char roman_width[] =
- {17,10,16,31,24,36,36,12, 16,16,22,26,12,16,10,22,
- 24,24,24,24,24,24,24,24, 24,24,10,12,25,26,25,20,
- 39,36,30,32,36,31,30,36, 37,18,22,39,31,40,37,35,
- 28,35,36,24,32,38,36,38, 38,36,32,14,22,14,24,40,
- 12,24,26,22,27,22,22,24, 27,16,16,27,15,38,27,24,
- 26,26,20,18,17,27,26,36, 26,26,22,17, 8,17,27,17};
-
- romwidstr(str)
- char *str;
- {
- int n;
- for (n = 0; *str; ++str)
- if (roman_width[*str - ' '] == 0)
- n += 16;
- else
- n += roman_width[*str - ' '];
- return((int) (n * 2.4));
- }