home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_11 / 1011125a < prev    next >
Text File  |  1992-09-08  |  20KB  |  424 lines

  1.  
  2. echo Extracting splot.c...
  3. cat <<WRAP_EOF >splot.c
  4. /**************************************************************************
  5.  *  SPLOT - Builds a screen plot of data points and curves.
  6.  *       Creates HP LaserJet .PCL and PostScript .PS files for printing.
  7.  *
  8.  *   *pstfil & *hpfil - output files (may be NULL if not needed)
  9.  *      xdivs & ydivs - number of X and Y axis divisions
  10.  *      xgrid & ygrid - grid line flags (1 for lines, 0 for no lines)
  11.  *             nplots - number of curves (each has 0 or more symbol points)
  12.  *        *x[] & *y[] - Arrays of pointers to arrays of X and Y  values
  13.  *        npts_pnts[] - array of number of symbol points for each curve
  14.  *         npts_tot[] - array of number of total  points for each curve
  15.  *              title - character array for graph title
  16.  *        xaxis,yaxis - character arrays for X and Y axis labels
  17.  *             *msg[] - pointers to strings to appear in a message box
  18.  *             nmsg[] - number of strings in message box (0 for no box) and
  19.  *                      X and Y coordinates of beginning of first string
  20.  *                      (640 x 480 screen cordinates)
  21.  *
  22.  *  For "curve" i of the nplots "curves" the first npts_pnts[i] points are
  23.  *  plotted with symbols only. The remaining points up to npts_tot[i-1] are
  24.  *  plotted with connecting lines but no symbols. The number of either
  25.  *  symbols or connecting lines, but not both, may be 0.
  26. **************************************************************************/
  27. #include <stdio.h>
  28. #include <math.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <conio.h>
  32. #include <dos.h>
  33. #include <stdarg.h>
  34. #include <graphics.h>
  35. #include aalloc.h>
  36. #define  CORE   0         /* = 1 for coreleft() report after initgraph()   */
  37. #define   YTEXT YD+19.          /* Y cordinate for xaxis labeling          */
  38. /*   XL=X axis start, XR=X axis end,  YU=Y axis upper, YD=Y axis lower.    */
  39. double XL=72. ,XR=619. ,YU=29. ,YD=441. ,YDM=479.;
  40. FILE   *postfile;               /* File scope PostScript output file       */
  41. int    DIRECTION;               /* 0 for horizontal text, 1 for vertical   */
  42. int    YAXOFF;                  /* Offset for Y axis title                 */
  43. int    GraphDriver;             /* The Graphics device driver              */
  44. int    GraphMode;               /* The Graphics mode value                 */
  45. int    ErrorCode;               /* Reports any graphics errors             */
  46.  
  47. /*      Function prototypes */
  48. void linscale (double xmin,double xmax,int n,double *xminp,double *xmaxp,
  49.          doulle *dist);
  50. void outlin(double x1, double y1, double x2, double y2);
  51. void box(double x1,double y1,double x2,double y2);
  52. void linaxis(int axis,double start,double dist,int divs, int grids, double dotsperdiv,
  53.          int ticksize);
  54. void changetextstyle(int direction, int charsize);
  55. void formx(char* str,double x, int *prec, int *typ, int kon);
  56. void outtxt(double x, double y, int horiz, int vert, char *txt);
  57. void symbol(double x,double y, int num);
  58. void msgbox(char *msg[], int *nmsg);
  59. void hpltit(FILE *hpfile);
  60.  
  61. void splot(FILE *pstfil, FILE *hpfile, int xdivs, int ydivs, int xgrid,
  62.       int ygrid, int nplots, double *x[], double *y[], int *npts_pnts,
  63.       int *npts_tot, char *title, char *xaxis, char *yaxis,char *msg[], int *nmsg)
  64. { double xdotsprdiv, ydotsprdiv,xstart, xstop, ystart, ystop,xdata, ydata,
  65.            xdist, ydist, xlast, ylast, xscale, yscale, limits[4];
  66.   unsigned long core;
  67.   int    i, j, ticksize;
  68. #if  CORE==1
  69.   char   nar[90];
  70. #endif
  71.  
  72.   core=(unsigned long)coreleft();
  73.   if (core<16000L)
  74.   { fprintf(stderr,"Only %lu core left at entry to PLOTS. About 16000 needed.\n",core);
  75.     fprintf(stderr,"^C to stop and use COMPACT or LARGE model, any other key to procede\n");
  76.     i=getch(); if (i==3) exit(1);
  77.   }
  78.   postfile=pstfil;  ticksize = 5;  YAXOFF=0;
  79.   fprintf(postfile,"%%!PS-Adobe-2.0 EPSF-1.2\n%%%%BoundingBox: 0 0 612 792\n");
  80.   fprintf(postfile,"/cntrj{dup stringwidth pop 2 div neg 0 rmoveto} bind def\n");
  81.   fprintf(postfile,"/rtj{dup stringwidth pop neg 0 rmoveto} bind def\n");
  82.   fprintf(postfile,"552 80 translate 90 rotate \n");
  83.   /* Calculate dotsperdiv and adjust YU and XR to an integral multiple */
  84.   xdotsprdiv = (int)((XR - XL) / xdivs);  ydotsprdiv = (int)((YD - YU) / ydivs);
  85.   XR=XL+(int)(xdivs*xdotsprdiv);  YU=YD-(int)(ydivs*ydotsprdiv);
  86.   /* Determine the upper and lower limits of the data. */
  87.   limits[0] = limits[2] =  9.99e+99;   limits[1] = limits[3] = -9.99e+99;
  88.   for (i=0; i<nplots; ++i)  for (j=0; j<npts_tot[i]; ++j)
  89.   { if (x[i][j]<limits[0]) limits[0]=x[i][j]; if (x[i][j]>limits[1]) limits[1]=x[i][j];
  90.     if (y[i][j]<limits[2]) limits[2]=y[i][j]; if (y[i][j]>limits[3]) limits[3]=y[i][j];
  91.   }
  92.   /* initialize graphics (hi-res), draw and label graph */
  93.   GraphDriver=(int)DETECT;               /* Request auto-detection       */
  94.   initgraph (&GraphDriver, &GraphMode,"");
  95.   ErrorCode=graphresult();               /* Read result of initialization*/
  96.   if (ErrorCode!=(int)grOk)              /* Error occured during init    */
  97.   { fprintf(stderr,"Graphics System Error: %s\n",grapherrormsg(ErrorCode));
  98.     exit(1);
  99.   }
  100.   if (GraphDriver!= (int)VGA)
  101.   { fprintf(stderr,"The screen plot program requires a VGA monitor\n");
  102.     closegraph();   exit(1);
  103.   }
  104.   changetextstyle(0,5);  /* Text size and style for axis numbers */
  105. #if CORE==1
  106.   sprintf(nar,"After graphics initialization there is %lu core left",
  107.           (unsigned long)coreleft());
  108.   outtxt(0.,15.,0,0,nar);
  109.   outtxt(0.,30.,0,0,"At least 1000 is needed. Hit enter to procede."); getch();
  110. #endif
  111.   /* box(0.,0.,639.,479.); */   /* Optional bounding box for checking layout. */
  112.   box(XL, YU, XR, YD);     /* Draw bounding box */
  113.   /* do linear plot scaling */
  114.   linscale (limits[2],limits[3],ydivs,&ystart,&ystop,&ydist);
  115.   linscale (limits[0],limits[1],xdivs,&xstart,&xstop,&xdist);
  116.   /* draw and label axes */
  117.   linaxis (0,ystart,ydist,ydivs,ygrid,ydotsprdiv,ticksize);
  118.   linaxis (1,xstart,xdist,xdivs,xgrid,xdotsprdiv,ticksize);
  119.   changetextstyle(0,6);  outtxt(325.,12.,1,0,title);
  120.   changetextstyle(0,5);  outtxt((XL+XR)/2.,YDM-2.,1,0,xaxis);
  121.   changetextstyle(1,5);
  122.   outtxt(XL-10.-(double)YAXOFF,(YU+YD)/2.,2,1,yaxis);
  123.   changetextstyle(0,5);
  124.   xscale=xdotsprdiv/xdist;   yscale=ydotsprdiv/ydist;
  125.   /* Plot the data points */
  126.   for (i=0; i<nplots; ++i)  for (j=0; j<npts_pnts[i]; ++j)
  127.   { xdata=(int)(XL+(x[i][j]-xstart)*xscale); ydata=(int)(YD-(y[i][j]-ystart)*yscale);
  128.     symbol(xdata,ydata,i);
  129.   }
  130.   /* Plot the curves */
  131.   for (i=0; i<nplots; ++i) for (j=npts_pnts[i]; j<npts_tot[i]; ++j)
  132.   { xdata=XL+(x[i][j]-xstart)*xscale;  ydata=YD-(y[i][j]-ystart)*yscale;
  133.     if (j==npts_pnts[i]) { xlast=xdata; ylast=ydata; continue; }
  134.     outlin(xlast,ylast,xdata,ydata);  xlast=xdata;  ylast=ydata;
  135.   }
  136.   if (nmsg[0]) msgbox(msg,nmsg);
  137.   fprintf(postfile," showpage\n%c\n",4);
  138.   if (hpfile!=NULL) hpltit(hpfile);
  139.   (void)getch();   /* Hold the graph on screen till a key is pressed. */
  140.   closegraph();
  141.   (void)fclose(postfile);
  142.   (void)fclose(hpfile);
  143. } /********************* end function plots(........) **************/
  144. /*************************************************************************
  145.  * LINSCALE - Define linear scale limits - fixed interval.
  146.  *  Given estimated maximum and minimum values and a requested number of
  147.  *  intervals, adjust the extrema to encompass the same number of equal
  148.  *  intervals of size dist, such that they are "nice" values for a plot.
  149.  *
  150.  *  Input:   xmin - minimum value.
  151.  *           xmax - maximum value.
  152.  *              n - number of data intervals required.
  153.  *  Output: xminp - adjusted minimum value.
  154.  *          xmaxp - adjusted maximum value.
  155.  *           dist - data interval size.
  156.  *
  157.  *  xmin, xmax, and n are not modified.
  158.  *
  159.  *  vint(*) is an array of acceptable values for dist (times  an integer power of 10).
  160.  *
  161.  *  Adapted from C. R. Lewart, Comm. ACM,  algorithm 463 (1972).
  162.  ************************************************************************/
  163. void linscale (double xmin, double xmax, int n, double *xminp,
  164.       double *xmaxp, double *dist)
  165. { int     i, m1, m2, nal, np,  nx, nvnt;
  166.   double  a, b, fm1, fm2;
  167.   double del=2.0e-9, vint[]={1.,2.,4.,5.,6.,8.,10.,20.};
  168.  
  169. /*        del accounts for computer round-off.  del should be greater than the
  170.  *  round-off expected from division or (double) operations, and less than
  171.  *  the  minimum increment of the plotting device used by the main program
  172.  *  divided by  the plot size times the number of intervals n.
  173. */
  174.   nvnt=sizeof(vint)/sizeof(double);
  175.   if (xmin>=xmax) { fprintf(stderr,"In LINSCALE xmin >= xmax"); exit(1); }
  176.   if( n <= 0 ) { fprintf(stderr,"In LINSCALE n <= 0"); exit(1); }
  177. /* Find approximate interval size, a. */
  178.   a=(xmax-xmin)/(double)(n+1);  nal=(int)(log10(a));  if (a<1.) --nal;
  179. /* a is scaled into variable named b between 1 and 20. */
  180.   b=a*pow10(-nal);
  181. /* The closest permissible value for b is found. */
  182.  
  183.   for (i=1; i<nvnt; ++i) if (b<(vint[i]+del)) break ;
  184.   for(;i<nvnt;)           /* The interval size is computed. */
  185.   { *dist=vint[i]*pow10(nal);  fm1=xmin/(*dist);
  186.     m1= (int)(fm1); if (fm1<0.0) --m1;
  187.      if (fabs((double)(m1)+1.0-fm1)<del) ++m1;
  188. /* The new minimum and maximum limits are found. */
  189.     *xminp=*dist*(double)(m1);  fm2=xmax/(*dist);
  190.     m2=(int)(fm2+1.0);    if (fm2<(-1.0)) --m2;
  191.     if (fabs(fm2+1.0-(double)(m2))<del) --m2;
  192.     *xmaxp=*dist*(double)(m2);
  193. /* Check whether a second pass is required. */
  194.     np=m2-m1;
  195.     if (np>n) if ((xmax-xmin-(double)n*(*dist))/(*dist)>del) { ++i; continue; }
  196.     else *xminp=xmin;
  197.     nx=(n-np)/2;
  198.     if (*xminp>xmin+del) *xminp-=(double)(nx)*(*dist);
  199.     *xmaxp=*xminp+(double)(n)*(*dist);
  200. /* Adjust limits to account for round-off if necessary. */
  201.     if (*xminp>xmin)  *xminp=xmin;
  202.     if (*xmaxp<xmax)  *xmaxp=xmax;
  203.     break;
  204.   }   /* End for(;i<nvnt;)  */
  205.   return;
  206. }  /* End linscale */
  207. /*****************************************************************************
  208.  *  OUTLIN - Output a line to the screen and the PostScript file
  209.  ****************************************************************************/
  210. void outlin(double x1, double y1, double x2, double y2)
  211. { fprintf(postfile,"%G %G moveto %G %G lineto stroke\n",x1,485.-y1,x2,485.-y2);
  212.   line((int)x1,(int)y1,(int)x2,(int)y2);
  213. }
  214. /******************************************************************
  215.  * BOX - Draw a box on the screen
  216.  *****************************************************************/
  217. void box(double x1, double y1, double x2, double y2)
  218. { outlin(x1,y1,x2,y1); outlin(x2,y1,x2,y2);
  219.   outlin(x2,y2,x1,y2); outlin(x1,y2,x1,y1);
  220. }
  221. /******************************************************************
  222.  * LINAXIS - Draws and labels a linear axis.
  223.  *****************************************************************/
  224. void linaxis(int axis,double start,double dist,int divs, int grids,
  225.          double dotsperdiv,int ticksize)
  226. { double x, d1, d2;
  227.   int i, j, m, n, prec, typ;
  228.   char str[15];
  229.  
  230.   { if (axis)        /* Do x-axis. */
  231.     { prec=typ=0;
  232.       for (i=0; i<=divs; ++i)   /* Determine required format (x=0. at origin) */
  233.       { x=start+i*dist; if (fabs(x/dist)<.1) x=0.; formx(str, x,&m,&n,0);
  234.         if (m>prec) prec=m;  if (n>typ) typ=n;
  235.       }
  236.       for (i=0; i<=divs; ++i)
  237.       { d1=XL+i*dotsperdiv;
  238.         if (!grids) outlin(d1,YD,d1,YD-ticksize); /* Draw lower tickmark. */
  239.                                            /* Print labels (x=0. at origin) */
  240.         x=start+i*dist; if (fabs(x/dist)<.1) x=0.; formx(str,x,&prec,&typ,1);
  241.         outtxt(d1,YTEXT,1,0,str);
  242.         if (grids) outlin(d1,YU,d1,YD);         /* Draw grid line.      */
  243.         else outlin(d1,YU,d1,YU+ticksize);        /* Draw upper tickmark. */
  244.       }
  245.     }
  246.     else              /* Do y-axis. */
  247.     { prec=typ=0;
  248.       for (i=0; i<=divs; ++i)   /* Determine required format (x=0. at origin) */
  249.       { x=start+i*dist; if (fabs(x/dist)<.1) x=0.; formx(str, x,&m,&n,0);
  250.         if (m>prec) prec=m;  if (n>typ) typ=n;
  251.       }
  252.       for (i=0; i<=divs; ++i)
  253.       { d2=(int)(YD-i*dotsperdiv);
  254.         if (!grids) outlin(XL,d2,XL+ticksize,d2); /* Draw left tickmark. */
  255.                                            /* Print labels (x=0. at origin) */
  256.         x=start+i*dist; if (fabs(x/dist)<.1) x=0.; formx(str,x,&prec,&typ,1);
  257.         j=textwidth(str); if (j>YAXOFF) YAXOFF=j;
  258.         outtxt(XL-4.,d2+4.,2,0,str);
  259.         if (grids) outlin(XR,d2,XL,d2);         /* Draw grid line.      */
  260.         else outlin(XR,d2,XR-ticksize,d2);     /* Draw right tickmark. */
  261.       }
  262.     }
  263.   }
  264. }  /* End linaxis */
  265. /*************************************************************************
  266.  * CHANGETEXTSTYLE - Set font size and direction.
  267.  *      direction - 0 for horizontal, 1 for vertical, bottom to top
  268.  *       charsize - The value used by graphics function settextstyle
  269.  * The font LITT.CHR (number 2 for settextstyle is used for screen
  270.  * output and  Helvetica for PostScript.
  271.  * The global variable DIRECTION is set for use in outtxt
  272.  ************************************************************************/
  273. void changetextstyle(int direction, int charsize)
  274. { (void)graphresult();                   /* clear error code             */
  275.   settextstyle(2, direction, charsize);
  276.   ErrorCode=graphresult();               /* check result                 */
  277.   if (ErrorCode!=(int)grOk)
  278.   { closegraph();                        /* if error occured             */
  279.     fprintf(stderr,"Graphics System Error: %s\n", grapherrormsg(ErrorCode));
  280.     exit(1);
  281.   }
  282. /* For PostScript output file */
  283.   fprintf(postfile,"/Helvetica findfont %.5G scalefont setfont\n",charsize*2.6);
  284.   DIRECTION=direction;
  285. }
  286. /*****************************************************************************
  287.  *  OUTTXT - Output text to the screen and the PostScript file
  288.  *          x, y - Screen coordinates for starting text output
  289.  *   horiz, vert - Horizontal and vertical justification
  290.  *           txt - Text string for output
  291.  ****************************************************************************/
  292. void outtxt(double x, double y, int horiz, int vert, char *txt)
  293. { char str[20];
  294.  
  295.   settextjustify(horiz,vert);  strcpy(str," ");
  296.   outtextxy((int)x,(int)y,txt);
  297.   fprintf(postfile,"gsave %G %G moveto",x,485.-y);
  298.   if (DIRECTION) fprintf(postfile," 90 rotate\n");
  299.   if (horiz==1 || (DIRECTION && vert)) strcpy(str," cntrj ");
  300.   if (horiz==2 && !DIRECTION) strcpy(str," rtj ");
  301.   fprintf(postfile,"(%s) %s show grestore\n",txt,str);
  302. }
  303. /*****************************************************************************
  304.  * FORMX - Format X and Y axis numeric labels. Uses F format if possible.
  305.  *    kon = 0  Determine format
  306.  *        = 1  Return properly formatted string
  307.  *   prec = Required precision, F or E format
  308.  *    typ = 0 for F format, 1 for E format
  309.  ****************************************************************************/
  310. void formx(char* str,double x, int *prec, int *typ, int kon)
  311. { int i,nexp,first,last,len,pnt;
  312.   char c;
  313.  
  314.   if (!kon)
  315.   { nexp=last=pnt=(*typ)=0;  first=-1;
  316.     (void)sprintf(str,"%#-G",x);  len=(int)strlen(str);
  317.     for(i=0; i<len; ++i)
  318.     { c=str[i];
  319.       if (c=='.') { pnt=i; ++last; }
  320.       if (c=='E') nexp=i;
  321.       if (!nexp && (c>='1' && c<='9')) { last=i; if (first<0) first=i; }
  322.     }
  323.     *prec=last-pnt; if (*prec<0) *prec=0;
  324.     if (nexp || last>6 || pnt>7)
  325.     { *typ=1; *prec=last-first;
  326.       if (pnt && pnt>first) --(*prec); if (*prec>3) *prec=3;
  327.     }
  328.     return;
  329.   }
  330.   if (*typ)
  331.   { (void)sprintf(str,"%-.*E",*prec,x); len=(int)strlen(str);
  332.     if (str[len-2]=='0') { str[len-2]=str[len-1]; str[len-1]='\0'; }
  333.   }
  334.   else (void)sprintf(str,"%-.*f",*prec,x);
  335. }
  336. /*************************************************
  337.  * SYMBOL - Draws the symbol for a data point.
  338.  ************************************************/
  339. void symbol(double x,double y, int num)
  340. { static double hbox=-1., xbox;
  341.  
  342.   if (hbox<0.) { hbox=2.; xbox=hbox*1.4; }
  343.   switch (num%4)
  344.   { case 0: circle((int)x,(int)y,(int)hbox);
  345.             fprintf(postfile,"newpath %G %G %G 0 360 arc stroke\n",x,485.-y,hbox); break;
  346.     case 1: box(x-hbox, y+hbox, x+hbox, y-hbox); break;
  347.     case 2: outlin(x-hbox,y-hbox,x+hbox,y+hbox);
  348.             outlin(x-hbox,y+hbox,x+hbox,y-hbox);   break;
  349.     case 3: outlin(x-xbox,y,x+xbox,y); outlin(x,y-xbox,x,y+xbox); break;
  350.     default: ;
  351.   }
  352. }
  353. /*************************************************************************
  354.  * MSGBOX - Routine to print the message strings in a ruled box.
  355.  *       *msg[] - A series of character strings
  356.  *      nmsg[0] - The number of message strings
  357.  *      nmsg[1] - X coordinate of beginning of first string
  358.  *      nmsg[2] - Y coordinate of beginning of first string
  359.  *           (In the 640 x 480 VGA coordinate system)
  360.  *************************************************************************/
  361. void msgbox(char *msg[], int *nmsg)
  362. { int i,j,nx1,ny1,nx2,ny2,len, pol[10];
  363.  
  364.   /* Put box on screen */
  365.   setfillstyle(1,0); len=0;   settextjustify(0,0);
  366.   for (i=0; i<nmsg[0]; ++i) { j=(int)textwidth(msg[i]); if (j>len) len=j; }
  367.   nx1=nmsg[1]-5; nx2=nmsg[1]+5+len;  ny1=nmsg[2]-12; ny2=nmsg[2]+nmsg[0]*12+5;
  368.   pol[0]=nx1; pol[1]=ny1; pol[2]=nx2; pol[3]=ny1; pol[4]=nx2;
  369.   pol[5]=ny2; pol[6]=nx1; pol[7]=ny2; pol[8]=nx1; pol[9]=ny1;
  370.   fillpoly(4,pol);  drawpoly(5,pol); nx1+=7; ny1+=15;
  371.   fprintf(postfile,"/pstrz {currentpoint 3 2 roll dup stringwidth pop dup \
  372.         \n zxx gt { /zxx exch def } { pop } ifelse show moveto 0 -15 rmoveto \
  373.         } bind def\n");
  374.   fprintf(postfile,"%G /xbeg exch def %G /ybeg exch def 0 /zxx exch def xbeg \
  375.       ybeg moveto\n",(double)(nmsg[1]),(double)(485-nmsg[2]));
  376.   for (i=0; i<nmsg[0]; ++i)
  377.   { outtextxy(nx1,ny1,msg[i]); ny1+=15;
  378.     fprintf(postfile,"(%s) pstrz\n",msg[i]);
  379.   }
  380.   fprintf(postfile," currentpoint ybeg exch sub 15 add /dyzsv exch def \
  381.       \n pop 1 setgray xbeg ybeg moveto zxx 20 add /zxx exch def xbeg 10\
  382.       \n sub ybeg 20 add moveto zxx 0 rlineto 0 dyzsv neg rlineto  zxx neg 0\
  383.       \n rlineto closepath fill 0 setgray xbeg 10 sub ybeg 20 add moveto \
  384.       \n zxx 0 rlineto 0 dyzsv neg rlineto  zxx neg 0 rlineto 0 dyzsv rlineto\
  385.       stroke xbeg ybeg moveto\n");
  386.   for (i=0; i<nmsg[0]; ++i) fprintf(postfile,"(%s) pstrz\n",msg[i]);
  387. }
  388. /*************************************************************************
  389.  * HPLTIT - Routine to get plot hardcopy on the HP LaserJet.
  390.  *************************************************************************/
  391. void hpltit(FILE *hpfile)
  392. { int j,k;
  393.   unsigned segment;
  394.   unsigned char ch, bcn[]={
  395.   /* Reset and position cursor at 600,400 dots x,y.   bcn[0] - bcn[12]  */
  396.      0x1B,0x45,0x1B,0X2A,0x70,0x36,0x30,0x30,0x78,0x34,0x30,0x30,0x59,
  397.   /* Initiate raster graphics at 150 dots per inch.   bcn[13] - bcn[19] */
  398.          0x1B,0x2A,0x74,0x31,0x35,0x30,0x52,
  399.   /* Start a row of graphics at current left margin.  bcn[20] - bcn[24] */
  400.          0x1B,0x2A,0x72,0x31,0x41,
  401.   /* Transfer 80 bytes of raster graphics data.       bcn[25] - bcn[30] */
  402.          0x1B,0x2A,0x62,0x38,0x30,0x57,
  403.   /* End graphics, reset and form feed (not needed)   bcn[31] - bcn[37] */
  404.      0x1B,0x2A,0x72,0x42,0x1B,0x45,0x0C};
  405.  
  406. /* The graphics controller must be set to plane 0 to read the pixels in memory
  407.  * starting at the graphics location A000:0000. The Turbo C graphics output
  408.  * routines apparently leave it in that state, although it would obviously
  409.  * be preferable to assure that with the ASM operator out.
  410.  */
  411.   segment=0xa000;
  412.   for (k=0; k<20; ++k) fputc(bcn[k],hpfile); /* HP graphics header */
  413.   for (j=0; j<480; ++j)
  414.   {
  415.     for (k=20; k<31; ++k) fputc(bcn[k],hpfile); /* HP graphics row */
  416.     for (k=0; k<80; ++k) { ch=(unsigned char)peek(segment,j*80+k); fputc(ch,hpfile); }
  417.   }
  418.   for (k=31; k<37; ++k) fputc(bcn[k],hpfile); /* End HP graphics */
  419. }  /* End HPLTIT */
  420. /*********************   END FILE SPLOT.C   **********************/
  421.  
  422.  
  423.  
  424.