home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / LASER / OKIBAR.ZIP / OKIBAR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-07-14  |  11.4 KB  |  489 lines

  1. /***********************************************************************
  2.  * OKIGRAPH.C
  3.  *
  4.  * Bar Graph Maker for OKIDATA Laserline Printers and HP Compatables.
  5.  *
  6.  * Version 1.2  James Bumgardner   07/88
  7.  * Version 1    James Bumgardner   09/87
  8.  *
  9.  * For Microsoft C, Turbo C or Vax C
  10.  ***********************************************************************/
  11.  
  12. #include <stdio.h>
  13. #include <ctype.h>
  14.  
  15. /* These Constants are oriented to 720/INCH */
  16. #define HWIDTH    6120    /* Width of Paper */
  17. #define VWIDTH    7920    /* Height of Graph */
  18. #define RMARGIN    720    /* Right Margin Clearance */
  19. #define TMARGIN 1440    /* Top Margin */
  20. #define SHADOW    35    /* Height/Width of Shadow Shading */ 
  21. #define NOTCH    20    /* Length of Y Notches */
  22.  
  23. int bmargin=2880;    /* Bottom Margin - shortens with REDUCE command */
  24. #define YCLR    100    /* Clearance at top of graph */
  25. #define HTCHAR    200    /* Clearance for letters */
  26.  
  27. double **drng,max;    /* Pointers to data, Maximum Value */
  28. char **xrng,**lrng;    /* Pointers to text and legends */
  29. int ranges,elements;    /* Dimensions of Data */
  30. char mlegend;
  31.  
  32. char ibuf[257];
  33. char *title;
  34.  
  35. void *malloc();
  36. char *strchr();
  37.  
  38. int linesflg,        /* Draw Lines Across Graph To Represent Values */
  39.     shadowflg,        /* Draw Shadows on North East Sides */
  40.     darken = 1,        /* Darken North East Sides */
  41.     dollarflg,        /* Dollar Signs in front of numbers */
  42.     combineflg,        /* Combine shading and patterns */
  43.     noabbrev,        /* Don't abbreviate Numbers */
  44.     noroundflg;        /* Don't Round Up Numbers */
  45. int ldiv = 0;        /* Number of Legends per Line */
  46. int lmargin = 720;    /* Left margin */
  47.  
  48. /**********************************
  49.  * The Last Frontier!
  50.  * extensive comments end here ...
  51.  **********************************/
  52.  
  53. main(argc,argv)
  54. char *argv[];
  55. {
  56.     FILE *ifile;
  57.     char *p;
  58.     if (argc < 2)
  59.     {
  60.         fprintf(stderr,"OKIGRAPH filename\n");
  61.         exit();
  62.     }    
  63.     if ((ifile = fopen(argv[1],"r")) == NULL)
  64.     {
  65.         fprintf(stderr,"Can't open %s for input\n",argv[1]);
  66.         exit();
  67.     }
  68.  
  69.     allocation_pass(ifile);
  70.  
  71.     while (fgets(ibuf,256,ifile))    /* Parse Control File */
  72.     {
  73.         if (ibuf[0] == '\n' || ibuf[0] == 0 || ibuf[0] == ';')
  74.             continue;
  75.         ibuf[strlen(ibuf)-1] = '\0';
  76.         switch (*((short *) ibuf))
  77.         {
  78.         case 'LA':    do_literal(ibuf);    break;
  79.         case 'TI':
  80.             p = strchr(ibuf,' ');
  81.             ++p;
  82.             title = malloc(strlen(p)+1);
  83.             strcpy(title,p);
  84.             break;
  85.         case 'LM':    sscanf(ibuf,"%*s%d",&lmargin);    break;
  86.         case 'LD':    sscanf(ibuf,"%*s%d",&ldiv);    break;
  87.         case 'SH':    shadowflg = 1;    darken = 2; break;
  88.         case 'DA':    darken = 10;    break;
  89.         case 'DO':    dollarflg = 1;    break;
  90.         case 'LI':    linesflg = 1;    break;
  91.         case 'CO':    combineflg = 1;    break;
  92.         case 'RE':    bmargin = 4000;    break;
  93.         case 'BI':    noabbrev = 1;    break;
  94.         case 'NO':    noroundflg = 1;    break;
  95.         default:
  96.             if (*((short *) ibuf) == 'L ')    get_legend();
  97.             else                get_data();
  98.         }
  99.     }
  100.     print_graph();
  101. }
  102.  
  103. do_literal(str)        /* Process Literal Printer Escape Codes */
  104. char *str;
  105. {
  106.     while (isgraph(*str))    ++str;
  107.     while (isspace(*str))    ++str;
  108.     while (*str) {
  109.         if (*str == '^')
  110.         {
  111.             ++str;
  112.             putc(toupper(*str) - '@',stdout);
  113.         }
  114.         else
  115.             putc(*str,stdout);
  116.         ++str;
  117.     }
  118. }
  119.  
  120. allocation_pass(ifile)    /* Do a pass through file to determine dimensions */
  121. FILE *ifile;        /* Then allocate space */
  122. {
  123.     int i,n;
  124.     double t,t1,t2,t3,t4,t5,t6,t7,t8,t9,t0;
  125.     static char scanstr[] = "%f%f%f%f%f%f%f%f%f%f";
  126.     ranges = elements = 0;
  127.     while (fgets(ibuf,256,ifile))
  128.     {
  129.         if (sscanf(ibuf,"%f",&t) == 1) {
  130.             ++elements;
  131.             if (ranges == 0)
  132.                 ranges = sscanf(ibuf,scanstr,
  133.                         &t1,&t2,&t3,&t4,&t5,
  134.                         &t6,&t7,&t8,&t9,&t0);
  135.         }
  136.     }
  137.     fseek(ifile,0L,0);    /* rewind file */
  138.     fprintf(stderr,"%d ranges, %d elements\n",ranges,elements);
  139.     xrng = (char **) malloc(elements * sizeof(char *));
  140.     lrng = (char **) malloc(ranges * sizeof (char *));
  141.     drng = (double **) malloc(ranges * sizeof(double *));
  142.     for (i = 0; i < ranges; ++i) 
  143.     {
  144.         lrng[i] = NULL;
  145.         drng[i] = (double *) malloc(elements * sizeof(double));
  146.         for (n = 0; n < elements; ++n)
  147.             drng[i][n] = 0L;
  148.     }
  149.  
  150.     for (i = 0; i < elements; ++i)
  151.         xrng[i] = NULL;
  152. }
  153.  
  154. get_legend()        /* Get Legend Text from Control File */
  155. {
  156.     static int lcnt;
  157.     char *p,l;
  158.     p = &ibuf[2];
  159.     lrng[lcnt] = malloc(strlen(p)+1);
  160.     strcpy(lrng[lcnt],p);
  161.     l = strlen(p);
  162.     if (mlegend < l)    mlegend = l;
  163.     if (++lcnt > ranges)    ranges = lcnt;
  164. }
  165.  
  166. get_data()        /* Get Data from Control File */
  167. {
  168.     static int dcnt;
  169.     int i;
  170.     double v;
  171.     char *p;
  172.  
  173.     if (sscanf(ibuf,"%d",&i) == 0)    return;
  174.  
  175.     p = ibuf;
  176.     for (i = 0; i < ranges; ++i)
  177.     {
  178.         while (isspace(*p))    p++;
  179.         if (*p == '\0')        break;
  180.         sscanf(p,"%le",&v);
  181.         if (v > max)        max = v;
  182.         drng[i][dcnt] = v;
  183.         while (isdigit(*p) || *p == '.')    p++;
  184.         if (*p == '\0')        break;
  185.     }
  186.     while (isspace(*p))    p++;
  187.     if (*p == '\"' || *p == '\'')    ++p;
  188.     if (isprint(*p))
  189.     {
  190.         xrng[dcnt] = malloc(strlen(p)+1);
  191.         strcpy(xrng[dcnt],p);
  192.     }
  193.         
  194.     if (++dcnt > elements)    elements = dcnt;
  195. }
  196.  
  197. int wgraph,welement,wbar;
  198. int hgraph,bline;
  199. double yfact;
  200.  
  201. #define NO_COMBS    10
  202. char combtran[] = {0,20,40,80,1,2,3,4,5,6};
  203. char *locstr = "\033&a%dh%dV";
  204. char *rulstr = "\033*c%dh%dv0P";
  205. char *patstr = "\033*c%dh%dv%dg3P";
  206. char *shdstr = "\033*c%dh%dv%dg2P";
  207.  
  208. #define locate(x,y)    printf(locstr,x,y)
  209. #define prul(h,w)    printf(rulstr,h,w)
  210. #define ppat(h,w,c)    printf(patstr,h,w,c+1)
  211. #define pcmb(h,w,c)    printf(((c % NO_COMBS) < 4)? shdstr : patstr,h,w,combtran[c % NO_COMBS])
  212.  
  213. int basex,xclear;
  214.  
  215.  
  216. fix_graph()    /* Convert graphs with multiple ranges, 1 element to  */
  217.                 /* One range, multiple elements (cosmetic fix)        */
  218. {
  219.     int i;
  220.     char *p;
  221.     double *trng;
  222.     if (elements > 1 || ranges == 1 || ranges > 8)    return;
  223.     fprintf(stderr,"Switching to better format...\n");
  224.     trng = (double *) malloc(sizeof(double) * ranges);
  225.     for (i = 0; i < ranges;++i)
  226.         trng[i] = drng[i][0];
  227.     drng[0] = trng;
  228.     if (xrng[0] != NULL)
  229.     {    /* insert element name into title */
  230.         for (p = title; *p && *((short *) p) != '  '; ++p)
  231.             ;
  232.         if (*((short *) p) == '  ' && strlen(p) >= strlen(xrng[0])+2)
  233.         {
  234.             sprintf(p,", %s",xrng[0]);
  235.             p[strlen(p)] = ' ';
  236.         }
  237.         free(xrng[0]);
  238.     }
  239.     free(xrng);
  240.     xrng = (char **) malloc(ranges * sizeof(char *));
  241.     for (i = 0; i < ranges; ++i)
  242.         xrng[i] = lrng[i];
  243.     lrng[0] = NULL;
  244.     elements = ranges;
  245.     ranges = 1;
  246. }
  247.  
  248. print_graph()            /* Main Typesetting Routine */
  249. {
  250.     int i,n,x,y;
  251.     int hbar,y2;
  252.  
  253.     fix_graph();
  254.  
  255.     setup_ylabels();
  256.  
  257.     wgraph = HWIDTH - (lmargin + RMARGIN);
  258.     welement = wgraph / elements;
  259.     xclear = (welement)/8;
  260.     wbar = (welement-(xclear*2))/ranges;
  261.     if (wbar > 480)    wbar = 480;
  262.     /* recalculate xclear to take integer error into account */
  263.     xclear = (welement-(wbar*ranges))/2;
  264.     
  265.     hgraph = VWIDTH - (TMARGIN + bmargin);
  266.     bline = TMARGIN + hgraph + YCLR;
  267.     yfact = hgraph / max;
  268.  
  269.     print_title_frame();
  270.  
  271.     print_legends();
  272.  
  273.     draw_ylabels();
  274.  
  275.     printf("\033(s1P");    /* Roman  Proportional */
  276.  
  277.     for (i = 0; i < elements; ++i)
  278.     {
  279.         basex = lmargin + welement*i;
  280.         if (xrng[i]) {
  281.             locate(basex + welement/2 - romwidstr(xrng[i])/2,
  282.                    bline+HTCHAR);
  283.             printf("%s",xrng[i]);
  284.         }
  285.         basex += xclear;
  286.         for (n = 0; n < ranges; ++n)
  287.         {
  288.             if (drng[n][i] == 0)    continue;
  289.             hbar = drng[n][i] * yfact;
  290.             x = basex+wbar*n;
  291.             y = bline-hbar;
  292.             /* Locate */
  293.             draw_box(x,y,wbar,hbar,1,3);
  294.             if (shadowflg) {
  295.                 if (n == ranges - 1)    
  296.                     draw_shadow(x,y,wbar,hbar+SHADOW);
  297.                 else {
  298.                     y2 = bline - drng[n+1][i]*yfact;
  299.                     locate(x+SHADOW,y-SHADOW);
  300.                     ppat(wbar-SHADOW,SHADOW,2);
  301.                     if (y2 > y-SHADOW) {
  302.                         locate(x+wbar,y-SHADOW);
  303.                         ppat(SHADOW,y2-(y-SHADOW),2);
  304.                     }
  305.                 }
  306.             }
  307.             locate(basex+wbar*n,bline-hbar);
  308.             /* Draw Bar */
  309.             if (combineflg)
  310.                 pcmb(wbar,hbar,n);
  311.             else
  312.                 ppat(wbar,hbar,n);
  313.         }
  314.     }
  315.     putchar(12);
  316. }
  317.  
  318. unsigned long tdiv[] = {1000,1000000,1000000000};
  319. char divc[] = {'K','M','B'};
  320. unsigned long ydiv;
  321. int ydecimal,yrng;
  322.  
  323. setup_ylabels()    /* figure out some nice round numbers for left hand side */
  324. {
  325.     double log10(),pow();
  326.     double mm;
  327.     unsigned long il;
  328.  
  329.     if (max <= 10)
  330.         ydiv = 1;
  331.     else {
  332.         mm = pow(10.0,(double) ((int) log10(max)));
  333.         if (max >= mm * 5)
  334.             ydiv = mm;
  335.         else    ydiv = mm/2;
  336.     }
  337.     
  338.     if (max >= 1000000000)     yrng = 2;
  339.     else if (max >= 1000000) yrng = 1;
  340.     else             yrng = 0; 
  341.  
  342.     ydecimal = (ydiv < tdiv[yrng]);    /* Check if decimals are needed */
  343.  
  344.     il = (int)(max/ydiv)*ydiv;    
  345.  
  346.     /* Show next hightest line if it's close */
  347.     if (noroundflg == 0 && max-il > ydiv / 2)
  348.         max = il+ydiv;
  349. }
  350.  
  351. draw_ylabels()        /* Draw Numbers and Lines on left edge */
  352. {
  353.     /* Roman  Non-Proportional, Italics Off */
  354.     static char ystr[17];
  355.     unsigned long il;
  356.     int i,y,n;
  357.     
  358.     printf("\033(s10v0p0s0b5T");
  359.  
  360.     /* Y Labels */
  361.     for (il = 0; il <= max; il += ydiv)
  362.     {
  363.         strcpy(ystr,(dollarflg)? "$" : "");
  364.         if (noabbrev || max < 1000 || il == 0)
  365.             sprintf(&ystr[dollarflg],"%d",il);
  366.         else {
  367.             sprintf(&ystr[dollarflg],"%.*f%c",
  368.                 ydecimal,(double) il/tdiv[yrng],divc[yrng]);
  369.         }
  370.         y = il*yfact;
  371.         locate(lmargin-720,bline - y);
  372.         printf("%9s",ystr);
  373.         if (linesflg) {
  374.             for (i = 0; i < elements; ++i) {
  375.                 basex = lmargin + welement*i;
  376.                 locate(basex,bline-y);
  377.                 prul(xclear,1);
  378.                 basex += xclear;
  379.                 for (n = 0; n < ranges; ++n) {
  380.                     if (y > drng[n][i]*yfact) {
  381.                         locate(basex+wbar*n,bline-y);
  382.                         prul(wbar,1);
  383.                     }
  384.                 }
  385.                 locate(basex+wbar*n,bline-y);
  386.                 prul(xclear,1);
  387.             }
  388.         }
  389.         else {    /* Notch */
  390.             locate(lmargin - NOTCH,bline-y);
  391.             prul(NOTCH,1);
  392.         }
  393.     }
  394. }
  395.  
  396. print_title_frame()
  397. {
  398.     if (title) {
  399.         locate(lmargin,TMARGIN-HTCHAR);
  400.         /* HELVETICA */
  401.         printf("\033&l00\033(0U\033(s1p14.4v0s3b4T");
  402.         printf("%s",title);
  403.     }
  404.     /* draw box around graph */
  405.     draw_box(lmargin,TMARGIN,wgraph,hgraph + YCLR,3,3);
  406.     if (shadowflg)
  407.         draw_shadow(lmargin,TMARGIN,wgraph,hgraph+YCLR);
  408. }
  409.  
  410. print_legends()
  411. {
  412.     int i,x,y;
  413.  
  414.     if (lrng[0])    /* Italics for Legends */
  415.         printf("\033(s%s10v1s0b5T",(mlegend > 16)? "-1p" : "");
  416.  
  417.     if (ldiv == 0)
  418.     {
  419.         if (ranges % 2 == 0 && ranges % 3 != 0) ldiv = 2; /* 2 4 8 10 */
  420.         else                  ldiv = 3; /* 3 5 6 7 9 11 12 */
  421.     }
  422.     for (i = 0; i < ranges; ++i)
  423.     {
  424.  
  425.         if (lrng[i] == NULL)    break;
  426.  
  427.         x = lmargin + (i%ldiv) * (wgraph/ldiv);
  428.         y = bline + 410 + 410 * (i/ldiv);
  429.  
  430.         draw_box(x,y,300,200,1,3);
  431.         if (shadowflg)
  432.             draw_shadow(x,y,300,200);
  433.  
  434.         locate(x,y);
  435.  
  436.         if (combineflg)        pcmb(300,200,i);
  437.         else            ppat(300,200,i);
  438.  
  439.         locate((x+((mlegend > 22)? 338 : 410)),y+145);
  440.         printf("%s",lrng[i]);
  441.     }
  442. }
  443.  
  444.     
  445. draw_box(x,y,w,h,xt,yt)
  446. {
  447.     locate(x,y);
  448.     prul(w,xt+((w)? darken : 0));
  449.     prul(yt,h);
  450.     locate(x+w,y);
  451.     prul(yt+((h)? darken : 0),h);
  452.     locate(x,y+h);
  453.     prul(w,xt);
  454. }
  455.  
  456. draw_shadow(x,y,w,h)
  457. {
  458.     locate(x+SHADOW,y-SHADOW);
  459.     ppat(w-SHADOW,SHADOW,2);
  460.     if (h > 0) {
  461.         locate(x+w,y-SHADOW);
  462.         ppat(SHADOW,h,2);
  463.     }
  464. }
  465.  
  466.  
  467. /* Table to determine width of Times Roman Characters from OKIDATA LASERLINE */
  468. /* This was borrowed from a Word Perfect Printer Driver */
  469.  
  470. unsigned char roman_width[] =
  471. {17,10,16,31,24,36,36,12, 16,16,22,26,12,16,10,22,
  472.  24,24,24,24,24,24,24,24, 24,24,10,12,25,26,25,20,
  473.  39,36,30,32,36,31,30,36, 37,18,22,39,31,40,37,35,
  474.  28,35,36,24,32,38,36,38, 38,36,32,14,22,14,24,40,
  475.  12,24,26,22,27,22,22,24, 27,16,16,27,15,38,27,24,
  476.  26,26,20,18,17,27,26,36, 26,26,22,17, 8,17,27,17};
  477.  
  478. romwidstr(str)
  479. char *str;
  480. {
  481.     int n;
  482.     for (n = 0; *str; ++str)
  483.         if (roman_width[*str - ' '] == 0)
  484.             n += 16;
  485.         else
  486.             n += roman_width[*str - ' '];
  487.     return((int) (n * 2.4));
  488. }
  489.