home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_08_03
/
8n03115a
< prev
next >
Wrap
Text File
|
1990-03-20
|
12KB
|
349 lines
#include "stdlib.h"
#include "stdio.h"
#include "conio.h"
#include "string.h"
#include "graph.fd"
#include "halo.h"
#define OK 1
#define FAIL 0
#define TRUE 1
#define FALSE 0
#define CMD_DELIMITER " \t\n"
#define VAL_DELIMITER ",\n"
#define TICK_WIDTH 0.025
#define SQRT_2 1.414213562
char *cmd_strs[] = {"DATA","COLORS","MODE","ATTRIBUTES","SCALE","LEGEND",
"FONT","TITLES","DEVICE","PRINTER","COMMENT","END" };
enum cmd_vals { C_DATA, C_COLORS, C_MODE, C_ATTRIBUTES, C_SCALE, C_LEGEND,
C_FONT, C_TITLES, C_DEVICE, C_PRINTER, C_COMMENT, C_END };
#define NUM_CMD_VALS ((int)C_END)
union udata {
float fdata[64]; /* Numeric data for commands (e.g. COLORS) */
char cdata[16][16]; /* String data for commands (e.g. LEGEND) */
};
typedef struct cmd_data_type {
union udata d; /* Commands data is string or numeric */
int count; /* Number of data items found in command */
} cmd_data_type, *cmd_data_type_p;
typedef struct { /* HALO '88 specific global data */
char *device; /* Name of HALO screen device driver */
char *font; /* Name of HALO stroke font file */
float x1,y1,x2,y2; /* World coordinates rectangle values */
int degree_mode; /* if true use degrees, else radians */
int lnstyle; /* Line style, 1 <= lnstyle <= 10 */
int lnwidth; /* Line thickness in pixels, always odd */
int maxcolor; /* Number of colors supported by device */
int mode; /* Device dependent graphics mode */
} halo_type;
typedef struct {
float start_x, start_y; /* Bottom corner of graph draw area */
float end_x, end_y; /* Upper corner of graph draw area */
float scale_min, scale_max; /* Y-Axis min and max values */
int num_points; /* Number of points in DATA file */
int num_ticks; /* Number of ticks on the Y-Axis */
int num_colors; /* Number of user-supplied colors */
char *legend; /* User-supplied LEGEND */
} graph_type;
cmd_data_type cmd_data[NUM_CMD_VALS];
halo_type halo;
graph_type graph;
main(argc,argv)
int argc;
char **argv;
{
char inp_line[128];
FILE *infile;
if (argc>1) { /* First argv should be input data file */
if ((infile=fopen(argv[1],"r")) == NULL) {
fprintf(stderr,"Error: can't open %s\n",argv[1]);
exit(-1);
}
}
else { /* no data file was given */
fprintf(stderr,"Usage: graph inputfile\n");
exit(-1);
}
memset(cmd_data, 0, sizeof(cmd_data));
while(fgets(inp_line,sizeof(inp_line)-1,infile) != NULL)
process_graphics_cmd_line(inp_line);
fclose(infile);
setup_halo_globals(); /* Capture relevant parameters */
setup_graph_globals();
draw_bar_graph(); /* Draw the actual graph */
deltcur(); /* Remove text "_" cursor */
getch();
print_graph(); /* Print graph if requested */
closegraphics(); /* Close out all devices */
return OK;
}
int process_graphics_cmd_line(inp_line)
char *inp_line;
{
char input[128];
char *cmd_keywd;
int found = FALSE;
int cmd_val;
strcpy(input,inp_line);
if ((cmd_keywd=strtok(input,CMD_DELIMITER)) == NULL) {
fprintf(stderr,"Unable to parse to command <%s>\n",inp_line);
return FAIL;
}
for (cmd_val=0; cmd_val<=NUM_CMD_VALS; cmd_val++)
if (stricmp(cmd_strs[cmd_val],cmd_keywd)==0) {
found = TRUE;
break;
}
if (!found) {
fprintf(stderr,"Keyword <%s> not recognized.\n",cmd_keywd);
return FAIL;
}
if (cmd_val <= C_SCALE)
parse_delimited_number_list(&cmd_data[cmd_val]);
else
parse_delimited_string_list(&cmd_data[cmd_val]);
return OK;
}
void parse_delimited_number_list(data_p)
cmd_data_type *data_p;
{
int i;
char *cmd_data;
i = data_p->count;
while ((cmd_data=strtok(NULL,VAL_DELIMITER)) != NULL)
data_p->d.fdata[i++] = (float) atof(cmd_data);
data_p->count = i;
}
void parse_delimited_string_list(data_p)
cmd_data_type_p data_p;
{
int i;
char *cmd_data;
i = data_p->count;
while ((cmd_data=strtok(NULL,VAL_DELIMITER)) != NULL)
strcpy(data_p->d.cdata[i++],cmd_data);
data_p->count = i;
}
void setup_halo_globals()
{
if (cmd_data[C_DEVICE].count) /* Was there a DEVICE command? */
halo.device = cmd_data[C_DEVICE].d.cdata[0];
else /* No, use the default */
halo.device = "HALOIBMG.DEV";
printf("using device <%s>, press any key to start:\n",halo.device);
getch();
setdev(halo.device); /* Initialize the graphics device */
halo.mode = (int) cmd_data[C_MODE].d.fdata[0];
initgraphics(&halo.mode); /* Clear screen in given mode */
halo.degree_mode = 1;
setdegree(&halo.degree_mode); /* Use degrees, not radians */
halo.x1 = (float) 0.0; halo.y1 = (float) 0.0;
halo.x2 = (float) 1.0; halo.y2 = (float) 1.0;
setworld(&halo.x1,&halo.y1,&halo.x2,&halo.y2); /* World rectangle */
inqcrange(&halo.maxcolor ); /* Find max color value */
halo.lnwidth = 1;
setlnwidth(&halo.lnwidth) ; /* Line width is 1 pixel */
halo.lnstyle = 1;
setlnstyle(&halo.lnstyle); /* Line style is solid */
setcolor(&halo.maxcolor); /* Max screen color is usually white */
if (cmd_data[C_FONT].count) /* Was there a FONT command? */
halo.font = cmd_data[C_FONT].d.cdata[0];
else /* No, use the default */
halo.font = "HALO104.FNT";
setfont(halo.font); /* Load font from disk file */
setstclr(&halo.maxcolor,&halo.maxcolor) ; /* Set stroke text color */
}
void setup_graph_globals()
{
float *data_ptr;
int i;
/* This rectangle is the active drawing area of the global window */
graph.start_x = (float) 0.1; graph.end_x = (float) 0.9;
graph.start_y = (float) 0.15; graph.end_y = (float) 0.88;
graph.num_ticks = 10;
graph.num_points = cmd_data[C_DATA].count;
graph.num_colors = cmd_data[C_COLORS].count;
graph.legend = cmd_data[C_LEGEND].d.cdata[0];
if (cmd_data[C_SCALE].count) { /* User supplied SCALE boundaries */
graph.scale_min = cmd_data[C_SCALE].d.fdata[0];
graph.scale_max = cmd_data[C_SCALE].d.fdata[1];
}
else { /* No SCALE bounds, use min and max data values for SCALE */
graph.scale_min = (float) 0.0;
graph.scale_max = (float) 0.0;
data_ptr = cmd_data[C_DATA].d.fdata;
for (i=0; i < graph.num_points; i++, data_ptr++) {
if (graph.scale_min > *data_ptr)
graph.scale_min = *data_ptr; /* New minimum data point */
if (graph.scale_max < *data_ptr)
graph.scale_max = *data_ptr; /* New maximum data point */
}
}
}
void draw_axes(bar_width)
double bar_width;
{
int i;
float tick_interval; /* Distance between Y-Axis ticks */
float axis_interval; /* Y-Axis tick value in scale units */
float height = (float) 0.10; /* Stroke text height */
float angle = (float) 45.0; /* Stroke text drawing angle */
float asp = (float) 1.0; /* Stroke text aspect ratio */
int path = 0; /* Stroke text path */
float text_height; /* Inquired height of text string */
float text_width; /* Inquired width of text String */
float offse; /* Offset for descenders */
float x_val, y_val; /* General-purpose registers */
char axis_label[20]; /* String used to label a tick */
char *title; /* User-specified graph TITLE */
/* draw the legend above the graph */
setstext(&height,&asp,&path);
inqstsize(graph.legend,&text_height,&text_width,&offse);
x_val = (halo.x2-text_width)/2.0;
y_val = (float) 0.99 - height;
movtcurabs(&x_val,&y_val);
stext(graph.legend);
/* draw X and Y axes */
draw_line(graph.start_x, graph.start_y, graph.end_x, graph.start_y);
draw_line(graph.start_x, graph.start_y, graph.start_x, graph.end_y);
tick_interval = (graph.end_y - graph.start_y) / graph.num_ticks;
axis_interval = (graph.scale_max - graph.scale_min) / graph.num_ticks;
height = tick_interval * 0.80; /* text height is 80% of tick dist. */
setstext(&height,&asp,&path);
/* Draw ticks and label the Y-Axis */
y_val = graph.start_y;
for (i=0; i<graph.num_ticks+1; i++) {
sprintf(axis_label,"%d", (int)(graph.scale_min + axis_interval * i));
inqstsize(axis_label,&text_height,&text_width,&offse);
x_val = graph.start_x - 1.5 * TICK_WIDTH - text_width;
movtcurabs(&x_val,&y_val);
stext(axis_label);
draw_line(graph.start_x-TICK_WIDTH,y_val,graph.start_x+TICK_WIDTH,y_val);
y_val += tick_interval;
}
/* draw bar labels at a 45-degree angle along the X-Axis */
setstang(&angle);
for (i=0; i<graph.num_points; i++) {
title = cmd_data[C_TITLES].d.cdata[i];
inqstsize(title,&text_height,&text_width,&offse);
x_val = graph.start_x + (i+0.5) * bar_width - text_width/SQRT_2;
y_val = graph.start_y - (text_height*1.25 + text_width/SQRT_2);
movtcurabs(&x_val,&y_val);
stext(title); /* draw the actual text */
}
}
void draw_bar_graph()
{
float bar_width; /* Width of a bar in display units */
float bar_height; /* Height of a bar in display units */
int bar_color; /* Color to draw the bar with */
float *data_ptr; /* Used to fetch user's DATA */
int i;
int hatch_style; /* Hatch style to draw the bar with */
/* draw_legend(); */
data_ptr = cmd_data[C_DATA].d.fdata; /* 1st data point to plot */
bar_width = (graph.end_x - graph.start_x) / graph.num_points;
draw_axes(bar_width);
for (i=0; i<graph.num_points; i++, data_ptr++) {
if (graph.num_colors && halo.maxcolor>1) {
bar_color = (int) cmd_data[C_COLORS].d.fdata[i % graph.num_colors];
setcolor(&bar_color);
}
else { /* Monochrome display or color display with no COLORS data */
hatch_style = (i % 4) + 1;
sethatchstyle(&hatch_style);
}
bar_height = (*data_ptr - graph.scale_min) /
(graph.scale_max - graph.scale_min) * (graph.end_y - graph.start_y);
draw_bar(graph.start_x+i*bar_width, graph.start_y,
graph.start_x+(i+1)*bar_width, graph.start_y + bar_height);
}
}
void print_graph()
{
char *print_name;
int print_attr[18];
int i;
print_name = cmd_data[C_PRINTER].d.cdata[0];
if (*print_name == '\0')
return; /* If no printer specified, do not print */
setprn(print_name);
if (cmd_data[C_ATTRIBUTES].count) { /* Device-specific attribs */
for (i=0; i < cmd_data[C_ATTRIBUTES].count; i++)
print_attr[i] = cmd_data[C_ATTRIBUTES].d.fdata[i];
setpattr(print_attr);
}
gprint();
}
void draw_bar(x1,y1,x2,y2) /* Draw a bar from (x1,y1) to (x2,y2) */
double x1,y1,x2,y2;
{
float x1_t,y1_t,x2_t,y2_t;
x1_t = (float)x1; y1_t = (float)y1; x2_t = (float)x2; y2_t = (float)y2;
bar(&x1_t,&y1_t,&x2_t,&y2_t);
}
void draw_line(x1,y1,x2,y2) /* Draw a line from (x1,y1) to (x2,y2) */
double x1,y1,x2,y2;
{
float x1_t,y1_t,x2_t,y2_t;
x1_t = (float)x1; y1_t = (float)y1; x2_t = (float)x2; y2_t = (float)y2;
movabs(&x1_t,&y1_t);
lnabs(&x2_t,&y2_t);
}