Fchart part 02/04
Filip Sawicki LAKE
fs at uwasa.fi
Mon Jun 4 22:51:48 AEST 1990
Submitted-by: fs at chyde
Archive-name: Fchart/part02
#!/bin/sh
# This is part 02 of Fchart
if touch 2>&1 | fgrep '[-amc]' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= fcmd.c ==============
echo "x - extracting fcmd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > fcmd.c &&
X/* Fchart - fcmd.c */
X/*
X * Gnuplot code
X * Copyright (C) 1986, 1987, 1990 Thomas Williams, Colin Kelley
X *
X * Permission to use, copy, and distribute this software and its
X * documentation for any purpose with or without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and
X * that both that copyright notice and this permission notice appear
X * in supporting documentation.
X *
X * Permission to modify the software is granted, but not the right to
X * distribute the modified code. Modifications are to be distributed
X * as patches to released version.
X *
X * This software is provided "as is" without express or implied warranty.
X *
X *
X * AUTHORS
X *
X * Original Software:
X * Thomas Williams, Colin Kelley.
X *
X * Gnuplot 2.0 additions:
X * Russell Lang, Dave Kotz, John Campbell.
X *
X * Fchart changes and additions:
X * Piotr Filip Sawicki
X *
X * send your comments or suggestions to fs at uwasa.fi
X *
X */
X#include <stdio.h>
X#include <math.h>
X#include <ctype.h>
X
X#ifdef MSDOS
X#include <process.h>
X
X#ifdef __ZTC__
X#define P_WAIT 0
X#include <time.h> /* usleep() */
X#else
X
X#ifdef __TURBOC__
X#include <dos.h> /* sleep() */
X
X#else /* must be MSC */
X#include <time.h> /* kludge to provide sleep() */
Xvoid sleep(); /* defined later */
X#endif /* TURBOC */
X#endif /* ZTC */
X
X#endif /* MSDOS */
X
X#include "plot.h"
X#include "fchart.h"
X#include "help.h"
X
X#ifndef STDOUT
X#define STDOUT 1
X#endif
X
X#ifndef HELPFILE
X#define HELPFILE "fchart.gih" /* changed by makefile */
X#endif
X
X/* global defs for default values */
X#define DEF_T_FORMAT "%g" /* make it as narrow as possible */
X#define EXPL_RAD 0.3 /* ratio of explosion of a slice */
X#define MAXBARWIDTH 0.2 /* default maximal allowable width of bar */
X#define INTERBAR 0.2 /* interbar space in terms of real bar width */
X#define INTERGROUP 0.5 /* space between groups of bars */
X#define OTHER "other" /* name for combined slice */
X
X/*
X * global variables to hold status of 'set' options
X *
X */
X
XBOOLEAN autoscale = TRUE,
X auto_label = FALSE,
X p_clockwise = TRUE,
X b_clockwise = TRUE,
X draw_border = TRUE;
X
Xenum DRAW_STYLE data_style = ABARS;
Xenum GRAV_DIR gravity = SOUTH,
X explode = DEFAULT;
Xenum INP_STYLE inp_style = PRIVATE;
Xenum FONT_STYLE vect_font = F_WHENN;
XBOOLEAN log_y = FALSE;
XFILE* outfile;
Xchar outstr[MAX_LINE_LEN+1] = "STDOUT";
Xint samples = SAMPLES;
Xint term = 0; /* unknown term is 0 */
Xint xmin = -1,
X xmax = -1;
Xdouble base = 0.0;
Xdouble loff = 0.0,
X roff = 0.0,
X toff = 0.0,
X boff = 0.0;
Xdouble b_wid = MAXBARWIDTH,
X b_int = INTERBAR,
X b_spc = INTERGROUP;
Xdouble radexp = EXPL_RAD; /* explosion power */
Xdouble zero = ZERO; /* zero threshold, not 0! */
Xint HLitem = HL_NON; /* no highliting by default */
Xstruct pair data_place = { -1, -1 }, /* not defined yet */
X label_plac = { -1, -1 }; /* not defined yet */
Xfloat xsize = 1.0,
X ysize = 1.0;
Xdouble treshold = 0.0;
Xchar thrname[MAX_LINE_LEN+1] = OTHER;
Xchar tic_form[MAX_LINE_LEN+1] = DEF_T_FORMAT;
Xint strunc = -1;
X
Xstruct dfile data_head = { NULL, 0.0, 0.0, 0, 0, HL_NON, FALSE, NULL, NULL } ;
X
XBOOLEAN screen_ok;
XBOOLEAN term_init;
X/* BOOLEAN undefined; */ /* probably not even used */
X
X/*
X * instead of <strings.h>
X */
X
Xchar *gets(),*getenv(),*sprintf(); /* for lint only */
Xchar *strcpy(),*strncpy(),*strcat();
X
Xextern double real();
Xextern void set_label(), set_nolabel(), set_arrow(), set_noarrow();
Xextern void show_labels(), show_arrow();
X
Xextern struct termentry term_tbl[];
X
Xstruct lexical_unit token[MAX_TOKENS];
Xchar input_line[MAX_LINE_LEN+1] = "";
Xint num_tokens, c_token;
X
Xstatic char replot_line[MAX_LINE_LEN+1];
Xstatic int plot_token; /* start of 'plot' command */
X
Xextern void squash_spaces(), lower_case();
X
Xcom_line()
X{
X read_line(PROMPT);
X
X screen_ok = interactive; /* see 'Gnuplot' why */
X
X do_line();
X}
X
X
Xdo_line() /* also used in load_file */
X{
X if (is_system(input_line[0])) {
X do_system();
X fputs("!\n",stderr);
X return;
X }
X num_tokens = scanner(input_line);
X c_token = 0;
X while(c_token < num_tokens) {
X command();
X if (c_token < num_tokens) /* something after command */
X if (equals(c_token,";"))
X c_token++;
X else
X int_error("';' expected",c_token);
X }
X}
X
Xcommand()
X{
X static char sv_file[MAX_LINE_LEN+1];
X /* string holding name of save or load file */
X
X if (equals(c_token,"help") || equals(c_token,"?")) {
X c_token++;
X do_help();
X }
X else if (almost_equals(c_token,"test")) {
X c_token++;
X term_test();
X }
X else if (almost_equals(c_token,"pa$use")) {
X int stime=1, text=0;
X char buf[MAX_LINE_LEN+1];
X
X c_token++;
X if (equals(c_token,"-")) stime=-1, c_token++;
X stime *= (int)real(c_token);
X c_token++;
X if (!(END_OF_COMMAND)) {
X if (!isstring(c_token))
X int_error("expecting string",c_token);
X else {
X quote_str(buf,c_token);
X fprintf (stderr, "%s",buf);
X text = 1;
X }
X }
X if (stime < 0) fgets (buf,MAX_LINE_LEN,stdin); /* Hold until CR hit */
X#ifdef __ZTC__
X if (stime > 0) usleep((unsigned long) stime);
X#else
X if (stime > 0) sleep((unsigned) stime);
X#endif
X if (text != 0 && stime >= 0) fprintf (stderr,"\n");
X c_token++;
X screen_ok = FALSE;
X }
X else if (almost_equals(c_token,"p$lot") ||
X almost_equals(c_token,"d$raw")) {
X plot_token = c_token++;
X plotrequest(FALSE);
X }
X else if (almost_equals(c_token,"tp$lot") ||
X almost_equals(c_token,"td$raw") ||
X almost_equals(c_token,"xp$lot") || /* for backward compatibility */
X almost_equals(c_token,"xd$raw") || /* for backward compatibility */
X almost_equals(c_token,"trans_plot") ||
X almost_equals(c_token,"trans_draw")) {
X plot_token = c_token++;
X plotrequest(TRUE);
X }
X else if (almost_equals(c_token,"rep$lot") ||
X almost_equals(c_token,"red$raw")) {
X c_token++;
X if (replot_line[0] == '\0')
X int_error("no previous plot",c_token);
X if (!END_OF_COMMAND) {
X char str[MAX_LINE_LEN+1];
X capture(str,c_token,num_tokens-1);
X if ((strlen(str)+strlen(input_line)) <= MAX_LINE_LEN-1) {
X (void) strcat(replot_line,",");
X (void) strcat(replot_line,str);
X }
X else
X int_error("plot line too long with replot arguments",c_token);
X }
X (void) strcpy(input_line,replot_line);
X screen_ok = FALSE;
X num_tokens = scanner(input_line);
X c_token = 1; /* skip the 'plot' part */
X plotrequest(almost_equals(0,"td$raw") ||
X almost_equals(0,"tp$lot") ||
X almost_equals(0,"xd$raw") ||
X almost_equals(0,"xp$lot") ||
X almost_equals(0,"tr$ans_plot") ||
X almost_equals(0,"tr$ans_draw")); /* fetch plot type */
X }
X else if (almost_equals(c_token,"se$t"))
X set_stuff();
X else if (almost_equals(c_token,"sh$ow"))
X show_stuff();
X else if (almost_equals(c_token,"sa$ve")) {
X c_token++;
X if (END_OF_COMMAND || !isstring(c_token))
X int_error("name of file expected", c_token);
X quote_str(sv_file,c_token);
X save_sets(fopen(sv_file,"w"));
X /* c_token updated in save_sets */
X }
X else if (almost_equals(c_token,"cl$ear")) {
X if (!term_init) {
X (*term_tbl[term].init)();
X term_init = TRUE;
X }
X (*term_tbl[term].graphics)();
X (*term_tbl[term].text)();
X (void) fflush(outfile);
X screen_ok = FALSE;
X c_token++;
X }
X else if (almost_equals(c_token,"she$ll")) {
X do_shell();
X screen_ok = FALSE;
X c_token++;
X }
X else if (almost_equals(c_token,"l$oad") ||
X almost_equals(c_token,"r$ead")) {
X if (!isstring(++c_token))
X int_error("expecting filename",c_token);
X else {
X quote_str(sv_file,c_token);
X load_file(fopen(sv_file,"r"));
X /* input_line[] and token[] now destroyed! */
X c_token = num_tokens = 0;
X }
X }
X else if (almost_equals(c_token,"ex$it") ||
X almost_equals(c_token,"q$uit")) {
X done(IO_SUCCESS);
X }
X else if (!equals(c_token,";")) { /* null statement */
X int_error("Invalid command. Try:\n\
X'?/help', 'test', 'pause', '[t]draw/[t]plot',\n\
X'replot/redraw', 'set', 'show', 'save', 'shell',\n\
X'load/read', 'exit/quit'",c_token);
X }
X}
X
X
Xenum DRAW_STYLE
Xget_style()
X{
Xregister enum DRAW_STYLE ps;
X
X c_token++;
X if (almost_equals(c_token,"a$djacent_bars"))
X ps = ABARS;
X else if (almost_equals(c_token,"l$ayer_bars"))
X ps = LAYB;
X else if (almost_equals(c_token,"s$tacked_bars"))
X ps = SBAR;
X else if (almost_equals(c_token,"p$iechart"))
X ps = PIECHART;
X else
X int_error("expecting 'adjacent_bars', 'stacked_bars', 'layer_bars' or 'piechart'",c_token);
X c_token++;
X return(ps);
X}
X
Xenum GRAV_DIR
Xget_gravity()
X{
X c_token++;
X if (END_OF_COMMAND) return(DEFAULT);
X else if (almost_equals(c_token,"b$ottom") || almost_equals(c_token,"s$outh")) {
X c_token++;
X return(SOUTH);
X }
X else if (almost_equals(c_token,"t$op") || almost_equals(c_token,"n$orth")) {
X c_token++;
X return(NORTH);
X }
X else if (almost_equals(c_token,"l$eft") || almost_equals(c_token,"w$est")) {
X c_token++;
X return(WEST);
X }
X else if (almost_equals(c_token,"r$ight") || almost_equals(c_token,"e$ast")) {
X c_token++;
X return(EAST);
X }
X else
X int_error("expecting direction: 'left/west', 'right/east',\n'bottom/south' or 'top/north'",c_token);
X /*NOTREACHED*/
X}
X
Xenum INP_STYLE
Xget_input()
X{
X if (END_OF_COMMAND) return(PRIVATE);
X else if (almost_equals(c_token,"g$nuplot")) {
X c_token++;
X return(GNUPLOT);
X }
X else if (almost_equals(c_token,"p$rivate")) {
X c_token++;
X return(PRIVATE);
X }
X else if (almost_equals(c_token,"c$ustomized")) {
X c_token++;
X return(CUSTOMD);
X }
X else
X int_error("expected 'gnuplot', 'private' or 'customized'",c_token);
X /*NOTREACHED*/
X}
X
Xset_stuff()
X{
X static char testfile[MAX_LINE_LEN+1];
X
X if (almost_equals(++c_token,"b$ar")) {
X set_bar_stuff();
X }
X else if (almost_equals(c_token,"fr$ame")) {
X draw_border = TRUE;
X c_token++;
X }
X else if (almost_equals(c_token,"nof$rame")) {
X draw_border = FALSE;
X c_token++;
X }
X else if (almost_equals(c_token,"for$mat")) {
X c_token++;
X if (END_OF_COMMAND)
X (void) strcpy(tic_form, DEF_T_FORMAT);
X else if (!isstring(c_token))
X int_error("enquoted format expected", c_token);
X else
X quote_str(tic_form, c_token++);
X }
X else if (almost_equals(c_token,"fon$t")) {
X c_token++;
X if (END_OF_COMMAND)
X vect_font = F_ALWYS;
X else {
X if (almost_equals(c_token,"n$ever"))
X vect_font = F_NEVER;
X else if (almost_equals(c_token,"w$hen_needed"))
X vect_font = F_WHENN;
X else if (almost_equals(c_token,"r$otated"))
X vect_font = F_ROTAT;
X else if (almost_equals(c_token,"a$lways"))
X vect_font = F_ALWYS;
X else
X int_error("'never', 'when_needed', 'rotated', or 'always' expected",c_token);
X c_token++;
X }
X }
X else if (almost_equals(c_token,"au$tolabeling")) {
X auto_label = TRUE;
X c_token++;
X }
X else if (almost_equals(c_token,"noau$tolabeling")) {
X auto_label = FALSE;
X c_token++;
X }
X else if (almost_equals(c_token,"ar$row")) {
X c_token++;
X set_arrow(TRUE);
X }
X else if (almost_equals(c_token,"noar$row")) {
X c_token++;
X set_noarrow();
X }
X else if (almost_equals(c_token,"c$ustomized")) {
X c_token++;
X if (END_OF_COMMAND) {
X data_place.from = -1; /* not defined */
X label_plac.from = -1; /* thus no label */
X }
X else {
X if (!equals(c_token,"["))
X int_error("expecting '['",c_token);
X c_token++;
X load_range(&data_place.from,&data_place.upto);
X if (!equals(c_token,"]"))
X int_error("expecting ']'",c_token);
X c_token++;
X if (END_OF_COMMAND)
X label_plac.from = -1; /* no label */
X else {
X if (equals(c_token,",")) c_token++; /* optional ',' */
X if (!equals(c_token,"["))
X int_error("expecting '['",c_token);
X c_token++;
X load_range(&label_plac.from,&label_plac.upto);
X if (!equals(c_token,"]"))
X int_error("expected ']'",c_token);
X c_token++;
X }
X if (!check_ranges(&data_place,&label_plac)) { /* overlapping ranges ? */
X data_place.from = label_plac.from = -1;
X int_error("value and label places are overlapping or are empty",NO_CARET);
X }
X }
X }
X else if (almost_equals(c_token,"h$ighlight")) {
X c_token++;
X HLitem = get_HL();
X }
X else if (almost_equals(c_token,"i$nput")) {
X c_token++;
X inp_style = get_input();
X }
X else if (almost_equals(c_token,"lo$gscale")) {
X c_token++;
X log_y = TRUE;
X }
X else if (almost_equals(c_token,"nolo$gscale")) {
X log_y = FALSE;
X c_token++;
X }
X else if (almost_equals(c_token,"la$bel")) {
X c_token++;
X set_label();
X }
X else if (almost_equals(c_token,"nola$bel")) {
X c_token++;
X set_nolabel();
X }
X else if (almost_equals(c_token,"li$ne")) {
X c_token++;
X set_arrow(FALSE);
X }
X else if (almost_equals(c_token,"noli$ne")) {
X c_token++;
X set_noarrow();
X }
X else if (almost_equals(c_token,"of$fsets")) {
X c_token++;
X if (END_OF_COMMAND) {
X loff = roff = toff = boff = 0.0; /* Reset offsets */
X }
X else {
X load_offsets (&loff,&roff,&toff,&boff);
X if ((loff>1.0 ? loff/100.0 : loff) + (roff>1.0 ? roff/100.0 : roff) >= 1.0 ||
X (boff>1.0 ? boff/100.0 : boff) + (toff>1.0 ? toff/100.0 : toff) >= 1.0) {
X loff = roff = toff = boff = 0.0; /* Reset offsets for the future */
X int_error("null picture size within given offsets",NO_CARET);
X }
X }
X }
X else if (almost_equals(c_token,"o$utput")) {
X register FILE *f;
X
X c_token++;
X if (END_OF_COMMAND) { /* no file specified */
X UP_redirect (4);
X if (outfile != stdout) /* Never close stdout */
X (void) fclose(outfile);
X outfile = stdout; /* Avoid the dup... */
X term_init = FALSE;
X (void) strcpy(outstr,"STDOUT");
X } else if (!isstring(c_token))
X int_error("expecting filename",c_token);
X else {
X quote_str(testfile,c_token);
X if (!(f = fopen(testfile,"w"))) {
X os_error("cannot open file; output not changed",c_token);
X }
X if (outfile != stdout) /* Never close stdout */
X (void) fclose(outfile);
X outfile = f;
X term_init = FALSE;
X outstr[0] = '\'';
X (void) strcat(strcpy(outstr+1,testfile),"'");
X UP_redirect (1);
X }
X c_token++;
X }
X else if (almost_equals(c_token,"p$ie")) {
X set_pie_stuff();
X }
X else if (almost_equals(c_token,"si$ze")) {
X c_token++;
X if (END_OF_COMMAND) {
X xsize = 1.0;
X ysize = 1.0;
X }
X else {
X xsize = (float)real(c_token);
X c_token++;
X if (!equals(c_token,","))
X int_error("',' expected",c_token);
X c_token++;
X if (END_OF_COMMAND)
X int_error("value for ysize expected",c_token);
X ysize = (float)real(c_token);
X c_token++;
X }
X }
X else if (almost_equals(c_token,"st$yle")) {
X data_style = get_style();
X }
X else if (almost_equals(c_token,"te$rminal")) {
X c_token++;
X if (END_OF_COMMAND) {
X list_terms();
X screen_ok = FALSE;
X }
X else {
X if (term && term_init) {
X (*term_tbl[term].reset)();
X (void) fflush(outfile);
X }
X term = set_term(c_token);
X c_token++;
X }
X }
X else if (almost_equals(c_token,"ti$tle")) {
X c_token++;
X if (END_OF_COMMAND) {
X if (data_head.fname)
X free(data_head.fname);
X data_head.fname = NULL;
X }
X else if (isstring(c_token)) {
X m_quote_capture(&(data_head.fname), c_token, c_token);
X c_token++;
X }
X else
X int_error("title within quotes expected", c_token);
X }
X else if (almost_equals(c_token,"tr$uncate")) {
X c_token++;
X if (END_OF_COMMAND)
X strunc = 0;
X else {
X strunc = real(c_token);
X c_token++;
X }
X }
X else if (almost_equals(c_token,"not$runcate")) {
X c_token++;
X strunc = -1;
X }
X else if (almost_equals(c_token,"r$ange")) {
X c_token++;
X if (END_OF_COMMAND) xmin=-1;
X else {
X if (!equals(c_token,"["))
X int_error("expecting '['",c_token);
X c_token++;
X load_range(&xmin,&xmax);
X if (!equals(c_token,"]"))
X int_error("expecting ']'",c_token);
X c_token++;
X if (xmax != -1 && xmax < xmin) {
X xmin = -1; /* whole */
X int_error("given range is empty",NO_CARET);
X }
X }
X }
X else if (almost_equals(c_token,"z$ero") ||
X almost_equals(c_token,"eps$ilon")) {
X int sign=1;
X c_token++;
X if (equals(c_token,"-")) sign=-1, c_token++;
X zero = sign*real(c_token);
X c_token++;
X }
X else
X int_error(
X "valid set options: 'bar', '[no]logscale',\n\
X'customized', 'format', 'highlight', 'offsets'\n\
X'output', 'pie', 'style', '[no]autolabeling',\n\
X'terminal', 'title', 'range', 'zero/epsilon',\n\
X'[no]frame', 'font', '[no]truncate', '[no]label',\n\
X'[no]arrow', '[no]line'",
X c_token);
X}
X
Xset_bar_stuff()
X{
X if (almost_equals(++c_token,"a$utoscale")) {
X autoscale = TRUE;
X c_token++;
X }
X else if (almost_equals(c_token,"noa$utoscale")) {
X autoscale = FALSE;
X c_token++;
X }
X else if (almost_equals(c_token,"b$ase")) {
X int sign = 1;
X c_token++;
X if (END_OF_COMMAND) base = 0.0;
X else {
X if (equals(c_token,"-")) c_token++, sign=-1;
X base = sign*real(c_token);
X c_token++;
X }
X }
X else if (almost_equals(c_token,"cl$ockwise")) {
X b_clockwise = TRUE;
X c_token++;
X }
X else if (almost_equals(c_token,"co$unter_clockwise")) {
X b_clockwise = FALSE;
X c_token++;
X }
X else if (almost_equals(c_token,"g$ravitation")) {
X gravity = get_gravity();
X if (gravity==DEFAULT) gravity = SOUTH;
X }
X else if (almost_equals(c_token,"w$idth")) {
X c_token++;
X if (END_OF_COMMAND) {
X b_wid = MAXBARWIDTH;
X b_int = INTERBAR;
X b_spc = INTERGROUP;
X }
X else
X load_offsets(&b_wid, &b_int, &b_spc, (double *) NULL);
X }
X else
X int_error("valid options: '[no]autoscale', 'base',\n\
X'[counter_]clockwise', 'gravitation', 'width'",c_token);
X}
X
Xset_pie_stuff()
X{
X if (almost_equals(++c_token,"ex$plode")) {
X explode = get_gravity();
X }
X else if (almost_equals(c_token,"cl$ockwise")) {
X p_clockwise = TRUE;
X c_token++;
X }
X else if (almost_equals(c_token,"co$unter_clockwise")) {
X p_clockwise = FALSE;
X c_token++;
X }
X else if (almost_equals(c_token,"r$adius")) {
X c_token++;
X if (END_OF_COMMAND)
X radexp = EXPL_RAD;
X else {
X radexp = real(c_token);
X c_token++;
X }
X }
X else if (almost_equals(c_token,"s$amples")) {
X register int tsamp;
X
X c_token++;
X tsamp = (int)real(c_token);
X if (tsamp < 1)
X int_error("sampling rate must be > 0; sampling unchanged",
X c_token);
X else samples = tsamp;
X c_token++;
X }
X else if (almost_equals(c_token,"t$hreshold")) {
X c_token++;
X if (END_OF_COMMAND) {
X treshold = 0.0;
X strcpy(thrname, OTHER);
X }
X else {
X treshold = real(c_token);
X c_token++;
X if (END_OF_COMMAND)
X strcpy(thrname, OTHER);
X else if (!isstring(c_token))
X int_error("name in quotes expected", c_token);
X else {
X quote_str(thrname, c_token);
X c_token++;
X }
X }
X }
X else
X int_error("valid options: '[counter_]clockwise',\n\
X'explode', 'radius', 'samples', 'threshold'",c_token);
X}
X
Xget_HL()
X{
X if (END_OF_COMMAND) return(HL_NON);
X else if (almost_equals(c_token,"n$one")) {
X c_token++;
X return(HL_NON);
X }
X else if (almost_equals(c_token,"mi$nim")) {
X c_token++;
X return(HL_MIN);
X }
X else if (almost_equals(c_token,"ma$xim")) {
X c_token++;
X return(HL_MAX);
X }
X else if (isnumber(c_token)) {
X return((int) real(c_token++));
X }
X else
X int_error("'maximum', 'minimum', 'none' or number expected",c_token);
X /*NOTREACHED*/
X}
X
Xshow_stuff()
X{
X if (almost_equals(++c_token,"sc$ale")) {
X (void) putc('\n',stderr);
X show_autoscale();
X c_token++;
X }
X else if (almost_equals(c_token,"au$tolabeling")) {
X (void) putc('\n',stderr);
X show_label();
X c_token++;
X }
X else if (almost_equals(c_token,"lo$gscale")) {
X (void) putc('\n',stderr);
X show_logscale();
X c_token++;
X }
X else if (almost_equals(c_token,"la$bel")) {
X (void) putc('\n',stderr);
X c_token++;
X if (END_OF_COMMAND)
X show_labels(0, stderr, FALSE);
X else {
X show_labels((int)real(c_token), stderr, FALSE);
X c_token++;
X }
X }
X else if (almost_equals(c_token,"li$ne") || almost_equals(c_token,"ar$row")) {
X (void) putc('\n',stderr);
X c_token++;
X if (END_OF_COMMAND)
X show_arrow(0, stderr, FALSE);
X else {
X show_arrow((int)real(c_token), stderr, FALSE);
X c_token++;
X }
X }
X else if (almost_equals(c_token,"bas$e")) {
X (void) putc('\n',stderr);
X show_base();
X c_token++;
X }
X else if (almost_equals(c_token,"fr$ame")) {
X (void) putc('\n',stderr);
X show_border();
X c_token++;
X }
X else if (almost_equals(c_token,"for$mat")) {
X (void) putc('\n',stderr);
X show_format();
X c_token++;
X }
X else if (almost_equals(c_token,"fon$t")) {
X (void) putc('\n',stderr);
X show_font();
X c_token++;
X }
X else if (almost_equals(c_token,"cl$ockwise")) {
X (void) putc('\n',stderr);
X show_clock(TRUE);
X show_clock(FALSE);
X c_token++;
X }
X else if (almost_equals(c_token,"cu$stomized")) {
X (void) putc('\n',stderr);
X show_custom();
X c_token++;
X }
X else if (almost_equals(c_token,"ex$plode")) {
X (void) putc('\n',stderr);
X show_explode();
X c_token++;
X }
X else if (almost_equals(c_token,"gr$avitation")) {
X (void) putc('\n',stderr);
X show_gravity();
X c_token++;
X }
X else if (almost_equals(c_token,"h$ighlight")) {
X (void) putc('\n',stderr);
X show_HLset();
X c_token++;
X }
X else if (almost_equals(c_token,"i$nput")) {
X (void) putc('\n',stderr);
X show_input();
X c_token++;
X }
X else if (almost_equals(c_token,"of$fsets")) {
X (void) putc('\n',stderr);
X show_offsets();
X c_token++;
X }
X else if (almost_equals(c_token,"o$utput")) {
X (void) putc('\n',stderr);
X show_output();
X c_token++;
X }
X else if (almost_equals(c_token,"sa$mples")) {
X (void) putc('\n',stderr);
X show_samples();
X c_token++;
X }
X else if (almost_equals(c_token,"st$yle")) {
X (void) putc('\n',stderr);
X c_token++;
X show_style();
X }
X else if (almost_equals(c_token,"si$ze")) {
X (void) putc('\n',stderr);
X c_token++;
X show_size();
X }
X else if (almost_equals(c_token,"te$rminal")) {
X (void) putc('\n',stderr);
X show_term();
X c_token++;
X }
X else if (almost_equals(c_token,"ti$tle")) {
X (void) putc('\n',stderr);
X show_title();
X c_token++;
X }
X else if (almost_equals(c_token,"th$reshold")) {
X (void) putc('\n',stderr);
X show_tresh();
X c_token++;
X }
X else if (almost_equals(c_token,"tr$uncate")) {
X (void) putc('\n',stderr);
X show_trunc();
X c_token++;
X }
X else if (almost_equals(c_token,"w$idth")) {
X (void) putc('\n',stderr);
X show_width();
X c_token++;
X }
X else if (almost_equals(c_token,"ve$rsion")) {
X show_version();
X c_token++;
X }
X else if (almost_equals(c_token,"rad$ius")) {
X (void) putc('\n',stderr);
X show_radius();
X c_token++;
X }
X else if (almost_equals(c_token,"r$ange")) {
X (void) putc('\n',stderr);
X show_range();
X c_token++;
X }
X else if (almost_equals(c_token,"z$ero") ||
X almost_equals(c_token,"eps$ilon")) {
X (void) putc('\n',stderr);
X show_zero();
X c_token++;
X }
X else if (almost_equals(c_token,"g$eneral")) { /* no more !!! */
X c_token++;
X show_version();
X show_input();
X show_custom();
X show_range();
X show_label();
X show_trunc();
X show_output();
X show_term();
X show_size();
X show_offsets();
X show_border();
X show_font();
X show_title();
X show_labels(0, stderr, FALSE);
X show_arrow(0, stderr, FALSE);
X show_logscale();
X show_format();
X show_zero();
X show_HLset();
X show_style();
X }
X else if (almost_equals(c_token,"bar$charts")) {
X c_token++;
X show_version();
X show_style();
X fprintf(stderr,"\n\tsettings for barcharts (any bar style):\n\n");
X show_base();
X show_width();
X show_autoscale();
X show_gravity();
X show_clock(FALSE);
X }
X else if (almost_equals(c_token,"pie$charts")) {
X c_token++;
X show_version();
X show_style();
X fprintf(stderr,"\n\tsettings for piecharts:\n\n");
X show_clock(TRUE);
X show_explode();
X show_radius();
X show_tresh();
X show_samples();
X }
X else if (almost_equals(c_token,"a$ll")) {
X c_token++;
X show_version();
X show_input();
X show_custom();
X show_range();
X show_label();
X show_trunc();
X show_output();
X show_term();
X show_size();
X show_offsets();
X show_border();
X show_font();
X show_title();
X show_labels(0, stderr, FALSE);
X show_arrow(0, stderr, FALSE);
X show_logscale();
X show_format();
X show_zero();
X show_HLset();
X show_style();
X show_base();
X show_width();
X show_autoscale();
X show_gravity();
X show_clock(FALSE); /* bars */
X show_clock(TRUE); /* pies */
X show_explode();
X show_radius();
X show_tresh();
X show_samples();
X }
X else
X int_error(
X "valid show options: 'all', 'scale', 'base', 'font'\n\
X'customized', 'explode', 'gravitation', 'highlight',\n\
X'input', 'logscale', 'offsets', 'output', 'label',\n\
X'samples', 'style', 'terminal', 'version', 'range',\n\
X'radius', 'clockwise', 'width', 'zero/epsilon', 'frame',\n\
X'size', 'general', 'barcharts', 'piecharts', 'format',\n\
X'threshold', 'truncate', 'line', 'arrow', 'autolabeling'",
Xc_token);
X screen_ok = FALSE;
X (void) putc('\n',stderr);
X}
X
X
Xload_offsets (a, b, c, d)
Xdouble *a, *b, *c, *d;
X{
X *a = real (c_token); /* loff value */
X if (*a >= 100.0 && d)
X int_error("value <0,100) expected",c_token);
X c_token++;
X if (equals(c_token,","))
X c_token++;
X if (END_OF_COMMAND)
X return;
X
X *b = real (c_token); /* roff value */
X if (*b >= 100.0 && d)
X int_error("value <0,100) expected",c_token);
X c_token++;
X if (equals(c_token,","))
X c_token++;
X if (END_OF_COMMAND)
X return;
X
X *c = real (c_token); /* toff value */
X if (*c >= 100.0 && d)
X int_error("value <0,100) expected",c_token);
X c_token++;
X
X if (!d) return;
X if (equals(c_token,","))
X c_token++;
X if (END_OF_COMMAND)
X return;
X
X *d = real (c_token); /* boff value */
X if (*d >= 100.0)
X int_error("value <0,100) expected",c_token);
X c_token++;
X}
X
X
Xload_range(a,b)
Xint *a, *b;
X{
X if (equals(c_token,"]"))
X return; /* no change */
X if (END_OF_COMMAND) {
X int_error("starting range value or ':' expected",c_token);
X } else if (!equals(c_token,"to") && !equals(c_token,":")) {
X *a = (int)real(c_token);
X c_token++;
X }
X else *a = 0; /* from the very begining */
X if (!equals(c_token,"to") && !equals(c_token,":"))
X int_error("':' expected",c_token);
X c_token++;
X if (!equals(c_token,"]")) {
X *b = (int)real(c_token);
X c_token++;
X }
X else *b = -1; /* to infinity */
X}
X
X
Xplotrequest(xplot)
XBOOLEAN xplot;
X{
X
X if (!term) /* unknown */
X int_error("use 'set term' to set terminal type first",c_token);
X
X if (log_y && base<1.0 && data_style != PIECHART)
X int_error("base for bars out of range for logscale",NO_CARET);
X
X if (equals(c_token,"[")) {
X c_token++;
X load_range(&xmin,&xmax);
X if (!equals(c_token,"]"))
X int_error("']' expected",c_token);
X c_token++;
X if (xmax != -1 && xmax < xmin)
X int_error("given range is empty",NO_CARET);
X }
X
X eval_plots(xplot);
X}
X
Xint missing(s)
Xchar *s;
X/* check if s represents a missing value (spaces and dot) */
X{
X char *p = s + strlen(s) - 1;
X if (!s || !*s)
X return(1);
X while (isspace(*s)) s++;
X if (s == p && *s == '.')
X return(1);
X else
X return(0);
X}
X
Xget_data(this_plot,this_style)
Xstruct dfile *this_plot;
Xenum INP_STYLE this_style;
X{
X static char data_file[MAX_LINE_LEN+1], line[MAX_LINE_LEN+1];
X register int i, l_num, ob_num, scanval;
X register FILE *fp;
X double x;
X struct chunk *chn;
X char *labpt;
X int chsiz = CH_INIT_SIZE;
X int lablen, aux;
X
X quote_str(data_file, c_token);
X m_quote_capture(&(this_plot->fname), c_token, c_token);
X
X chn = (struct chunk *) alloc((unsigned)sizeof(struct chunk), data_file);
X chn->next = NULL; /* in case of further errors */
X chn->dval = NULL;
X chn->vlbl = (char **) NULL;
X this_plot->data = chn;
X this_plot->chunks = 1;
X if (xmin != -1 && xmax != -1) /* known number of data */
X chsiz = xmax - xmin + 1;
X chn->dval = (vreal *) alloc((unsigned)chsiz*sizeof(vreal), data_file);
X chn->used = 0;
X if (this_style != CUSTOMD || label_plac.from != -1) { /* labels expected */
X chn->vlbl = (char **) alloc((unsigned)chsiz*sizeof(char *), data_file);
X for (i=0; i<chsiz; i++)
X chn->vlbl[i] = (char *) NULL;
X }
X this_plot->d_min = VERYLARGE;
X this_plot->d_max = -VERYLARGE;
X this_plot->points = 0;
X this_plot->makeHL = HL_NON;
X this_plot->labels = TRUE; /* label autogenerating may be possible */
X
X if (!(fp = fopen(data_file, "r")))
X os_error("can't open data file", c_token);
X
X l_num = 0;
X ob_num = -1; /* will be incremented before any operation */
X i = -1;
X
X while (fgets(line, MAX_LINE_LEN, fp)) { /* REWRITE ALL !!! */
X l_num++;
X if (is_comment(line[0]) && this_style != CUSTOMD) /* label can be on any position, incl. 1st column */
X continue; /* ignore comments */
X
X i++;
X if (i<xmin) continue; /* still out of range */
X if (xmax != -1 && i>xmax) break; /* don't even read the rest of file */
X
X line[strlen(line)-1] = '\0'; /* get rid of '\n' */
X ob_num++;
X if (ob_num==chsiz) { /* open new chunk */
X chn->next = (struct chunk *) alloc((unsigned)sizeof(struct chunk), data_file);
X chn = chn->next;
X chn->next = NULL; /* in case of further errors */
X chn->dval = NULL;
X chn->vlbl = (char **) NULL;
X this_plot->chunks++;
X this_plot->points += chsiz; /* chunkful of points */
X chsiz *= 2; /* probably the optimal allocation step */
X chn->dval = (vreal *) alloc((unsigned)chsiz*sizeof(vreal), (char *)NULL);
X if (!chn->dval)
X (void) fclose(fp),
X int_error("out of memory",c_token);
X chn->used = 0; /* this one */
X if (this_style != CUSTOMD || label_plac.from != -1) { /* labels expected */
X chn->vlbl = (char **) alloc((unsigned)chsiz*sizeof(char *), (char *)NULL);
X if (!chn->vlbl)
X (void) fclose(fp),
X int_error("out of memory",c_token++);
X else {
X int ii;
X for (ii=0; ii<chsiz; ii++)
X chn->vlbl[ii] = (char *) NULL;
X }
X }
X ob_num = 0;
X }
X
X if (!*line && this_style != CUSTOMD) { /* empty data == missing value. not in SAS */
X chn->dval[ob_num] = VERYLARGE;
X if (chn->vlbl)
X chn->vlbl[ob_num] = (char *) NULL;
X chn->used++;
X continue;
X }
X
X /* so here we go. now consider input format */
X switch (this_style) {
X case PRIVATE:
X scanval = sscanf(line,"%lf",&x);
X if (scanval == 1) {
X for (labpt = line; *labpt && isspace(*labpt); labpt++) ;
X while (*labpt && !isspace(*labpt)) labpt++;
X lablen = strlen(labpt); /* initialy */
X }
X break;
X case GNUPLOT:
X scanval = sscanf(line,"%*lf %lf",&x);
X if (scanval == 1) {
X for (aux=0; isspace(line[aux]); aux++);
X labpt = line + aux;
X for (lablen=0; !isspace(line[aux++]); lablen++) ;
X }
X else labpt=NULL, scanval = sscanf(line,"%lf",&x);
X break;
X case CUSTOMD:
X if (strlen(line) < data_place.from) {
X scanval = 0; /* generate error */
X break;
X }
X labpt = line + data_place.from;
X if (data_place.upto == -1 || data_place.upto >= strlen(line))
X if (missing(labpt))
X x = VERYLARGE;
X else
X scanval = sscanf(labpt,"%lf",&x);
X else {
X aux = line[data_place.upto];
X line[data_place.upto] = '\0';
X if (missing(labpt))
X x = VERYLARGE;
X else
X scanval = sscanf(labpt,"%lf",&x);
X line[data_place.upto] = aux;
X }
X if (x == VERYLARGE) { /* missing value detected, or unplottable anyway */
X chn->dval[ob_num] = VERYLARGE;
X if (chn->vlbl)
X chn->vlbl[ob_num] = (char *) NULL;
X chn->used++;
X continue;
X }
X if (label_plac.from >= strlen(line) || label_plac.from == -1)
X labpt = NULL;
X else {
X labpt = line + label_plac.from;
X if (label_plac.upto == -1 || label_plac.upto >= strlen(line))
X lablen = strlen(labpt);
X else
X lablen = label_plac.upto - label_plac.from - 1;
X }
X break;
X }
X
X if (scanval != 1) { /* can be also EOF for empty line */
X (void) sprintf(line, "bad data on line %d", l_num);
X (void) fclose(fp);
X int_error(line,c_token);
X }
X
X if (x<0.0 && data_style == PIECHART ||
X x<1.0 && data_style != PIECHART && log_y) {
X (void) fclose(fp);
X (void) sprintf(line,"unplotable data on line %d",l_num);
X int_error(line,c_token);
X }
X
X if (log_y) x = log10(x);
X
X chn->dval[ob_num] = (vreal) x;
X if (x<this_plot->d_min) this_plot->d_min = (vreal) x;
X if (x>this_plot->d_max) this_plot->d_max = (vreal) x; /* without 'else', I know */
X
X if (labpt && *labpt && lablen && strunc!=0) { /* copy existing label -- ignore if empty */
X char *q;
X /* remove meaningless spaces */
X while (isspace(*labpt)) labpt++, lablen--;
X while (isspace(labpt[lablen])) lablen--;
X if (strunc>0 && strunc<lablen)
X lablen = strunc;
X if (!lablen) /* truncated to zero */
X chn->vlbl[ob_num] = (char *) NULL;
X else {
X if (!(q = alloc((unsigned) lablen+1, (char *)NULL))) {
X (void) fclose(fp);
X int_error("out of memory",c_token);
X }
X (void) strncpy(q,labpt,lablen);
X q[lablen] = '\0';
X chn->vlbl[ob_num] = q;
X this_plot->labels = FALSE; /* cannot autogenerate labels if some exist */
X }
X }
X else
X chn->vlbl[ob_num] = (char *) NULL;
X
X chn->used++;
X } /* while */
X
X (void) fclose(fp);
X if (i<xmin)
X int_error("too few data",c_token);
X
X this_plot->points += chn->used;
X
X}
X
Xeval_plots(xplot)
XBOOLEAN xplot;
X{
X struct dfile *dp = &data_head, *tail;
X enum INP_STYLE in_st;
X
X data_head.d_min = VERYLARGE; data_head.d_max = -VERYLARGE;
X data_head.points = data_head.chunks = 0;
X if (data_head.data) free((char *)data_head.data);
X data_head.data = NULL;
X destroy(data_head.dnxt);
X data_head.dnxt = (struct dfile *) NULL;
X data_head.makeHL = HLitem;
X data_head.labels = auto_label;
X
X while (TRUE) {
X if (END_OF_COMMAND)
X int_error("data file to plot expected",c_token);
X if (equals(c_token,"(")) {
X c_token++;
X in_st = get_input();
X if (END_OF_COMMAND || !equals(c_token,")"))
X int_error("expected ')'",c_token);
X c_token++;
X }
X else
X in_st = inp_style;
X if (in_st == CUSTOMD && data_place.from == -1)
X int_error("Customized input format not defined. Use 'set customized'",NO_CARET);
X
X if (END_OF_COMMAND || !isstring(c_token))
X int_error("data file to plot expected",c_token);
X tail = (struct dfile *) alloc((unsigned int) sizeof(struct dfile), "data");
X tail->fname = NULL;
X tail->data = NULL;
X tail->dnxt = NULL;
X dp->dnxt = tail; /* to free all memory on error */
X
X get_data(tail,in_st);
X
X c_token++;
X dp = tail;
X data_head.chunks++; /* here we count overall number of files */
X if (data_style != ABARS && data_style != PIECHART || xplot) /* if (ABARS || PIECHART => xplot) */
X data_head.labels = data_head.labels && dp->labels; /* is making labels sensible or not ? */
X /* else this serves different purpose */
X if (data_head.points < dp->points)
X data_head.points = dp->points; /* ... and maximal number of points */
X if (data_head.d_min > dp->d_min)
X data_head.d_min = dp->d_min; /* minimum ... */
X if (data_head.d_max < dp->d_max)
X data_head.d_max = dp->d_max; /* and maximum */
X
X if (almost_equals(c_token,"a$s")) {
X c_token++;
X if (END_OF_COMMAND || !isstring(c_token))
X int_error("name in quotes expected", c_token);
X else {
X m_quote_capture(&(dp->fname), c_token, c_token);
X c_token++;
X }
X }
X
X if (almost_equals(c_token,"h$ighlighting")) {
X c_token++;
X dp->makeHL = get_HL();
X }
X
X if (END_OF_COMMAND)
X break;
X else if (equals(c_token,","))
X c_token++;
X else
X int_error("expected ','",c_token);
X }
X
X if (data_head.d_min == VERYLARGE || data_head.d_max == -VERYLARGE)
X int_error("all points undefined, nothing to draw",NO_CARET);
X
X if (data_head.chunks > 1) { /* reserve space for xpointers structure */
X /* do it here, to avoid memory management in graphics.c */
X data_head.data = (struct chunk *) alloc((unsigned)data_head.chunks*sizeof(struct xptr), "data");
X }
X
X capture(replot_line,plot_token,c_token);
X do_plot(xplot,data_style,xmin<=0?0:xmin);
X}
X
Xdone(status)
Xint status;
X{
X if (term && term_init)
X (*term_tbl[term].reset)();
X#ifdef VMS
X vms_reset();
X#endif
X exit(status);
X}
X
X#ifdef MSDOS
X#ifndef __TURBOC__ /* Turbo C already has sleep() */
X#ifndef __ZTC__ /* ZTC already has usleep() */
X/* kludge to provide sleep() for msc 5.1 */
Xvoid sleep(delay)
Xunsigned int delay;
X{
Xunsigned long time_is_up;
X time_is_up = time(NULL) + (unsigned long) delay;
X while (time(NULL)<time_is_up)
X /* wait */ ;
X}
X#endif /* not ZTC */
X#endif /* not TURBOC */
X#endif /* MSDOS */
X
X
X/* Support for input, shell, and help for various systems */
X
X#ifdef vms
X
X#include <descrip.h>
X#include <rmsdef.h>
X#include <errno.h>
X
Xextern lib$get_input(), lib$put_output();
X
Xint vms_len;
X
Xunsigned int status[2] = {1, 0};
X
Xstatic char help[MAX_LINE_LEN+1] = "fchart";
X
X$DESCRIPTOR(prompt_desc,PROMPT);
X$DESCRIPTOR(line_desc,input_line);
X
X$DESCRIPTOR(help_desc,help);
X$DESCRIPTOR(helpfile_desc,"FCHART$HELP");
X
Xread_line(prompt)
Xchar *prompt;
X{
X int more, start=0;
X char exp_prompt = EXP_PROMPT;
X prompt_desc.dsc$w_length = strlen (prompt);
X prompt_desc.dsc$a_pointer = prompt;
X do {
X line_desc.dsc$w_length = MAX_LINE_LEN - start;
X line_desc.dsc$a_pointer = &input_line[start];
X switch(status[1] = lib$get_input(&line_desc, &prompt_desc, &vms_len)){
X case RMS$_EOF:
X done(IO_SUCCESS); /* ^Z isn't really an error */
X break;
X case RMS$_TNS: /* didn't press return in time */
X vms_len--; /* skip the last character */
X break; /* and parse anyway */
X case RMS$_BES: /* Bad Escape Sequence */
X case RMS$_PES: /* Partial Escape Sequence */
X sys$putmsg(status);
X vms_len = 0; /* ignore the line */
X break;
X case SS$_NORMAL:
X break; /* everything's fine */
X default:
X done(status[1]); /* give the error message */
X }
X start += vms_len;
X input_line[start] = '\0';
X if (input_line[start-1] == '\\') {
X /* Allow for a continuation line. */
X prompt_desc.dsc$w_length = strlen (exp_prompt);
X prompt_desc.dsc$a_pointer = exp_prompt;
X more = 1;
X --start;
X }
X else {
X line_desc.dsc$w_length = strlen(input_line);
X line_desc.dsc$a_pointer = input_line;
X more = 0;
X }
X } while (more);
X}
X
X
Xdo_help()
X{
X help_desc.dsc$w_length = strlen(help);
X if ((vaxc$errno = lbr$output_help(lib$put_output,0,&help_desc,
X &helpfile_desc,0,lib$get_input)) != SS$_NORMAL)
X os_error("can't open FCHART$HELP");
X}
X
X
Xdo_shell()
X{
X if ((vaxc$errno = lib$spawn()) != SS$_NORMAL) {
X os_error("spawn error",NO_CARET);
X }
X}
X
X
Xdo_system()
X{
X input_line[0] = ' '; /* an embarrassment, but... */
X
X if ((vaxc$errno = lib$spawn(&line_desc)) != SS$_NORMAL)
X os_error("spawn error",NO_CARET);
X
X (void) putc('\n',stderr);
X}
X
X#else /* vms */
X
X/* do_help: (not VMS, although it would work)
X * Give help to the user.
X * It parses the command line into helpbuf and supplies help for that
X * string. Then, if there are subtopics available for that key,
X * it prompts the user with this string. If more input is
X * given, do_help is called recursively, with the argument the index of
X * null character in the string. Thus a more specific help can be
X * supplied. This can be done repeatedly.
X * If null input is given, the function returns, effecting a
X * backward climb up the tree.
X * David Kotz (dfk at cs.duke.edu) 10/89
X */
Xdo_help()
X{
X static char helpbuf[MAX_LINE_LEN] = "";
X static char prompt[MAX_LINE_LEN] = "";
X int base; /* index of first char AFTER help string */
X int len; /* length of current help string */
X BOOLEAN more_help;
X BOOLEAN only; /* TRUE if only printing subtopics */
X int subtopics; /* 0 if no subtopics for this topic */
X int start; /* starting token of help string */
X char *help_ptr; /* name of help file */
X
X if ( (help_ptr = getenv("FCHARTHELP")) == (char *)NULL )
X /* if can't find environment variable then just use HELPFILE */
X help_ptr = HELPFILE;
X
X len = base = strlen(helpbuf);
X
X /* find the end of the help command */
X for (start = c_token; !(END_OF_COMMAND); c_token++) ;
X /* copy new help input into helpbuf */
X if (len > 0)
X helpbuf[len++] = ' '; /* add a space */
X capture(helpbuf+len, start, c_token-1);
X squash_spaces(helpbuf+base); /* only bother with new stuff */
X lower_case(helpbuf+base); /* only bother with new stuff */
X len = strlen(helpbuf);
X
X /* now, a lone ? will print subtopics only */
X if (strcmp(helpbuf + (base ? base+1 : 0), "?") == 0) {
X /* subtopics only */
X subtopics = 1;
X only = TRUE;
X helpbuf[base] = '\0'; /* cut off question mark */
X } else {
X /* normal help request */
X subtopics = 0;
X only = FALSE;
X }
X
X switch ( help(helpbuf, help_ptr, &subtopics)) {
X case H_FOUND: {
X /* already printed the help info */
X /* subtopics now is true if there were any subtopics */
X screen_ok = FALSE;
X
X do {
X if (subtopics && !only) {
X /* prompt for subtopic with current help string */
X if (len > 0)
X (void) sprintf(prompt, "Subtopic of %s: ", helpbuf);
X else
X (void) strcpy(prompt, "Help topic: ");
X read_line(prompt);
X num_tokens = scanner(input_line);
X c_token = 0;
X more_help = !(END_OF_COMMAND);
X if (more_help)
X /* base for next level is all of current helpbuf */
X do_help();
X } else
X more_help = FALSE;
X } while(more_help);
X
X break;
X }
X case H_NOTFOUND: {
X printf("Sorry, no help for '%s'\n", helpbuf);
X break;
X }
X case H_ERROR: {
X perror(help_ptr);
X break;
X }
X default: { /* defensive programming */
X int_error("Impossible case in switch\n", NO_CARET);
X /* NOTREACHED */
X }
X }
X
X helpbuf[base] = '\0'; /* cut it off where we started */
X}
X
Xdo_system()
X{
X if (system(input_line + 1))
X os_error("system() failed",NO_CARET);
X}
X
X#ifdef MSDOS
X
Xread_line(prompt)
Xchar *prompt;
X{
X int last, start = 0;
X BOOLEAN more;
X
X#ifndef __ZTC__
X if (interactive) { /* if interactive use console IO so CED will work */
X cputs(prompt);
X do {
X input_line[start] = MAX_LINE_LEN - start - 1;
X cgets(&(input_line[start]));
X (void) putc('\n',stderr);
X if (input_line[start+2] == 26) {
X /* end-of-file */
X (void) putc('\n',stderr);
X input_line[start] = '\0';
X if (start > 0) /* don't quit yet - process what we have */
X more = FALSE;
X else {
X (void) putc('\n',stderr);
X done(IO_SUCCESS);
X /* NOTREACHED */
X }
X } else {
X /* normal line input */
X register i = start;
X while ( (input_line[i] = input_line[i+2]) != (char)NULL )
X i++; /* yuck! move everything down two characters */
X
X last = strlen(input_line) - 1;
X if (last + 1 >= MAX_LINE_LEN)
X int_error("Input line too long",NO_CARET);
X
X if (input_line[last] == '\\') { /* line continuation */
X start = last;
X more = TRUE;
X } else
X more = FALSE;
X }
X if (more && isatty(fileno(stdin)))
X cputs(EXP_PROMPT);
X } while(more);
X }
X else { /* not interactive */
X#endif /* not ZTC */
X if (interactive)
X fputs(prompt,stderr);
X do {
X /* grab some input */
X if ( fgets(&(input_line[start]), MAX_LINE_LEN - start, stdin)
X == (char *)NULL ) {
X /* end-of-file */
X if (interactive)
X (void) putc('\n',stderr);
X input_line[start] = '\0';
X if (start > 0) /* don't quit yet - process what we have */
X more = FALSE;
X else
X done(IO_SUCCESS); /* no return */
X } else {
X /* normal line input */
X last = strlen(input_line) - 1;
X if (input_line[last] == '\n') { /* remove any newline */
X input_line[last] = '\0';
X /* Watch out that we don't backup beyond 0 (1-1-1) */
X if (last > 0) --last;
X } else if (last+1 >= MAX_LINE_LEN)
X int_error("Input line too long",NO_CARET);
X
X if (input_line[last] == '\\') { /* line continuation */
X start = last;
X more = TRUE;
X } else
X more = FALSE;
X }
X if (more && interactive)
X fputs(EXP_PROMPT, stderr);
X } while(more);
X#ifndef __ZTC
X }
X#endif
X
X#ifdef FILIP
X input_line[0] = MAX_LINE_LEN - 1;
X cputs(PROMPT);
X cgets(input_line); /* console input so CED will work */
X (void) putc('\n',stderr);
X if (input_line[2] == 26) {
X (void) putc('\n',stderr); /* end-of-file */
X done(IO_SUCCESS);
X }
X
X i = 0;
X while (input_line[i] = input_line[i+2])
X i++; /* yuck! move everything down two characters */
X#endif
X}
X
X
Xdo_shell()
X{
X register char *comspec;
X if (!(comspec = getenv("COMSPEC")))
X comspec = "\command.com";
X if (spawnl(P_WAIT,comspec,NULL) == -1)
X os_error("unable to spawn shell",NO_CARET);
X}
X
X#else /* MSDOS */
X/* plain old Unix */
X
Xread_line(prompt)
Xchar *prompt;
X{
X int start=0, last=0;
X BOOLEAN more;
X
X if (interactive) fputs(prompt,stderr);
X do {
X if (!fgets(&input_line[start], MAX_LINE_LEN-start, stdin)) {
X if (interactive)
X (void) putc('\n',stderr); /* end-of-file */
X input_line[start] = '\0';
X if (start > 0) /* don't quit yet - process what we have */
X more = FALSE;
X else
X done(IO_SUCCESS); /* no return */
X }
X else { /* normal line input */
X last = strlen(input_line)-1;
X if (input_line[last] == '\n') { /* remove any newline */
X input_line[last] = '\0';
X /* Watch out that we don't backup beyond 0 (1-1-1) */
X if (last > 0) --last;
X }
X else if (last+1 >= MAX_LINE_LEN)
X int_error("Input line too long",NO_CARET);
X
X if (input_line[last] == '\\') { /* line continuation */
X start = last;
X more = TRUE;
X } else
X more = FALSE;
X }
X if (more && interactive) fputs(EXP_PROMPT,stderr);
X } while (more);
X}
X
X#ifdef VFORK
X
Xdo_shell()
X{
Xregister char *shell;
Xregister int p;
Xstatic int execstat;
X if (!(shell = getenv("SHELL")))
X shell = SHELL;
X if ((p = vfork()) == 0) {
X execstat = execl(shell,shell,NULL);
X _exit(1);
X } else if (p == -1)
X os_error("vfork failed",c_token);
X else
X while (wait(NULL) != p)
X ;
X if (execstat == -1)
X os_error("shell exec failed",c_token);
X (void) putc('\n',stderr);
X}
X#else /* VFORK */
X
X#define EXEC "exec "
Xdo_shell()
X{
Xstatic char exec[100] = EXEC;
Xregister char *shell;
X if (!(shell = getenv("SHELL")))
X shell = SHELL;
X
X if (system(strncpy(&exec[sizeof(EXEC)-1],shell,
X sizeof(exec)-sizeof(EXEC)-1)))
X os_error("system() failed",NO_CARET);
X
X (void) putc('\n',stderr);
X}
X#endif /* VFORK */
X#endif /* MSDOS */
X#endif /* vms */
SHAR_EOF
$TOUCH -am 0604152590 fcmd.c &&
chmod 0666 fcmd.c ||
echo "restore of fcmd.c failed"
set `wc -c fcmd.c`;Wc_c=$1
if test "$Wc_c" != "45623"; then
echo original size 45623, current size $Wc_c
fi
# ============= fgraf.c ==============
echo "x - extracting fgraf.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > fgraf.c &&
X/*
X *
X * Fchart -- fgraf.c
X *
X * Copyright (C) 1990 Piotr Filip Sawicki
X *
X * WARNING:
X * Included "fstyles.i" is an older version of already rewritten graphics
X * module. Please, don't change anything, rather mail me suggestions.
X * It emerged like a ball of mud -- don't be shocked with this code.
X * Writing program I jjust have been adding here new styles, parameters,
X * bells and whistles -- so it looks like it looks.
X *
X * Rest of the code can be freely modified and used, as long as this message
X * is retained and modified code is not redistributed.
X *
X * Please e-mail any useful additions to fs at uwasa.fi so they may be
X * included in later releases.
X *
X * This file should be edited with 4-column tabs! (:set ts=4 sw=4 in vi)
X */
X
X#include <stdio.h>
X#include <math.h>
X#include "plot.h"
X#include "fchart.h"
X
X/***********************************************************************/
X
X#define MARGIN 0.95 /* margin within frame */
X
X/***********************************************************************/
X
X
Xchar *strcpy(),*strncpy(),*strcat(),*sprintf(); /* for lint only */
X
Xchar *make_labl();
X
Xextern BOOLEAN autoscale;
Xextern FILE *outfile;
Xextern BOOLEAN log_y;
Xextern int term;
Xextern BOOLEAN draw_border;
X
Xextern BOOLEAN screen_ok;
Xextern BOOLEAN term_init;
X
Xextern double loff,roff,toff,boff;
Xextern double zero;
X
Xextern enum GRAV_DIR gravity, explode;
Xextern int samples;
Xextern double base;
Xextern BOOLEAN p_clockwise, b_clockwise;
Xextern double radexp, treshold;
Xextern double b_wid, b_spc, b_int;
Xextern char thrname[];
X
Xextern float xsize, ysize;
X
Xextern char tic_form[];
X
Xextern enum FONT_STYLE vect_font;
X
Xextern struct termentry term_tbl[];
Xextern struct dfile data_head; /* static head of data list */
X
Xextern struct label_def *first_label; /* defined in flblarr.c */
Xextern struct linearrow_def *first_arrow; /* defined in flblarr.c */
X
X#ifndef toascii
X#define toascii(A) (((int)(A)) & 0x7F)
X#endif
X
X#define SIGN(A) (A>=0 ? 1 : -1)
X
Xextern struct Char trt[]; /* font translation table */
X
Xstatic struct termentry *t; /* faster */
Xstatic int xbase, ybase, xmaxp, ymaxp; /* viewport */
Xstatic struct xptr *across; /* used for xplot */
Xstatic int first_element; /* first element for autolabeling */
Xstatic BOOLEAN trotate; /* whether terminal can rotate text or not */
Xstatic int tstate; /* state of terminal text rotation */
Xstatic int howmuch; /* how much space takes as text the longest used value */
X
Xdo_plot(xplot,style,fel)
XBOOLEAN xplot;
Xenum DRAW_STYLE style;
Xint fel;
X{
X /**This bloody part of code initializes graphic *
X * environment, draws borders, outputs trailer, *
X * etc. Before calling drawing fuctions it cal- *
X * culates viewport (see toff,boff,roff,loff) *
X * and some other variables used in any style. *
X * Ough, how I long to Pascal's nested local *
X * procedures !!! */
X
X BOOLEAN dolabel = (data_head.fname != (char *)NULL);
X int effect, x, y, x0, dx, y0, dy;
X struct label_def *lb;
X struct linearrow_def *ar;
X
X t = &term_tbl[term];
X if (!(*t->scale)(xsize, ysize)) {
X x = t->xmax * xsize;
X y = t->ymax * ysize;
X }
X else {
X x = t->xmax;
X y = t->ymax;
X }
X
X y0 = ybase = (int) ((boff>1.0 ? boff/100.0 : boff)*y) + 1;
X dy = ymaxp = (int) ((1.0-(toff>1.0 ? toff/100.0 : toff))*(y-2)) - (dolabel ? 3*t->v_char : 0);
X if (ymaxp <= ybase)
X int_error("no space to put title, change offsets", NO_CARET);
X x0 = xbase = (int) ((loff>1.0 ? loff/100.0 : loff)*x) + 1;
X dx = xmaxp = (int) ((1.0-(roff>1.0 ? roff/100.0 : roff))*(x-2));
X
X across = (struct xptr *) data_head.data;
X first_element = fel;
X
X if (!term_init) {
X (*t->init)();
X term_init = TRUE;
X }
X screen_ok = FALSE;
X (*t->graphics)();
X trotate = (*t->text_angle)(0); /* mostly harmless */
X tstate = 0;
X
X switch (style) {
X case ABARS : effect = dr_abar(xplot);
X break;
X case SBAR : effect = dr_sbar(xplot);
X break;
X case LAYB : effect = dr_lbar(xplot);
X break;
X case PIECHART : effect = dr_pies(xplot);
X break;
X default :
X (*t->text)();
X (void) fflush(outfile);
X int_error("style not yet implemented",NO_CARET);
X }
X
X if (!effect) {
X (*t->text)();
X (void) fflush(outfile);
X int_error("too many data to make sensible picture", NO_CARET);
X }
X
X (*t->linetype)(-2); /* border linetype */
X if (draw_border) { /* draw plot border */
X (*t->move)(0,0);
X (*t->vector)(x-1,0);
X (*t->vector)(x-1,y-1);
X (*t->vector)(0,y-1);
X (*t->vector)(0,0);
X }
X
X (*t->linetype)(0); /* only one guaranted to be solid */
X if (dolabel) /* put title */
X put_txt((x0+dx)/2, (int)(dy+3*t->v_char/2), data_head.fname, CENTRE, 0);
X
X for (lb=first_label; lb; lb=lb->next) { /* process and put labels */
X double c_x = lb->x <= 1.0 ? lb->x : lb->x/RESOLUTION;
X double c_y = lb->y <= 1.0 ? lb->y : lb->y/RESOLUTION;
X double c_h = lb->h <= 1.0 ? lb->h : lb->h/RESOLUTION;
X double c_w = lb->w <= 1.0 ? lb->w : lb->w/RESOLUTION;
X int lx, ly, r_x, r_y, r0x, r0y;
X if (!*lb->text)
X continue;
X
X if (lb->paged) {
X r0x = r0y = 0;
X r_x = x; r_y = y;
X }
X else {
X r0x = x0; r0y = y0;
X r_x = dx-x0; r_y = dy-y0;
X }
X lx = r0x + c_x*r_x;
X ly = r0y + c_y*r_y;
X
X if ((lb->rot == L_NORMAL || lb->rot == L_BOTTOM) &&
X !lb->h && !lb->w) /* try to put it as a normal text */
X put_txt(lx, ly, lb->text, lb->pos, lb->rot==L_NORMAL ? 0 : 1);
X else {
X double an = (int)lb->rot * Pi/2;
X if (!lb->h && !lb->w) /* use standard size */
X (void) draw_text(lx, ly, lb->text, (int)t->v_char, 0, -1, lb->pos, lb->rot==L_RANDOM ? lb->a : an);
X else /* draw_text will worry */
X (void) draw_text(lx, ly, lb->text, (int)(c_h*r_y), (int)(c_w*r_x),
X -1, lb->pos, lb->rot==L_RANDOM ? lb->a : an);
X }
X }
X
X for (ar=first_arrow; ar; ar=ar->next) { /* process and put arrows/lines */
X double c_sx = ar->sx <= 1.0 ? ar->sx : ar->sx/RESOLUTION;
X double c_sy = ar->sy <= 1.0 ? ar->sy : ar->sy/RESOLUTION;
X double c_ex = ar->ex <= 1.0 ? ar->ex : ar->ex/RESOLUTION;
X double c_ey = ar->ey <= 1.0 ? ar->ey : ar->ey/RESOLUTION;
X int sx,sy,ex,ey;
X if (ar->startp) {
X sx = x*c_sx;
X sy = y*c_sy;
X }
X else {
X sx = x0 + (dx-x0)*c_sx;
X sy = y0 + (dy-y0)*c_sy;
X }
X if (ar->endp) {
X ex = x*c_ex;
X ey = y*c_ey;
X }
X else {
X ex = x0 + (dx-x0)*c_ex;
X ey = y0 + (dy-y0)*c_ey;
X }
X
X if (ar->arrow)
X (*t->arrow)(sx, sy, ex, ey);
X else {
X (*t->move)(sx, sy);
X (*t->vector)(ex, ey);
X }
X }
X
X (*t->text)();
X (void) fflush(outfile);
X}
X
X#define MCx(PT,R,AN) nint((PT)+(R)*cos(AN))
X#define MCy(PT,R,AN) nint((PT)+(R)*sin(AN))
X
Xput_arc(x,y,r,a0,da)
Xint x,y,r;
Xdouble a0,da;
X/* draw arc from a0, da long */
X{
X double step, drto;
X int iter;
X
X (*t->move)(MCx(x,r,a0),MCy(y,r,a0));
X step = 2*Pi/samples * (da>0.0 ? 1 : -1); /* angle step */
X iter = nint(floor(da/step)); /* number of iterations - makes loop faster */
X drto = a0 + step; /* next place to draw */
X while (iter--) {
X (*t->vector)(MCx(x,r,drto),MCy(y,r,drto));
X drto += step;
X }
X (*t->vector)(MCx(x,r,a0+da),MCy(y,r,a0+da)); /* last part - prob. shorter */
X}
X
Xput_bar(x0,y0,dx,dy,turn)
Xint x0,y0,dx,dy,turn;
X/* put single bar (opened rectangle) */
X{
X if (turn) (*t->move)(x0,y0+dy);
X else {
X (*t->move)(x0,y0);
X (*t->vector)(x0,y0+dy);
X }
X (*t->vector)(x0+dx,y0+dy);
X (*t->vector)(x0+dx,y0);
X if (turn)
X (*t->vector)(x0,y0);
X}
X
XBOOLEAN find_ran(min, max, sum, lab)
Xdouble *min, *max, *sum;
Xchar **lab; /* NULL if all labels undefined; "" if labels different; else pointer to the good label */
X/**find function used for stacked bars: find min, max and total sum across all data. *
X * Check also possibility of labelling across etc. */
X{
X int i;
X vreal w;
X static char nothing[] = "";
X int labfound = 1;
X char *good = NULL, *aux;
X
X *min = VERYLARGE;
X *max = -VERYLARGE;
X *sum = 0.0;
X for (i=0; i<data_head.chunks; i++) {
X if (!across[i].chnp || (w=across[i].chnp->dval[across[i].vindex]) == VERYLARGE) continue;
X if (*min > w) *min = w;
X if (*max < w) *max = w;
X *sum += w;
X if (labfound && across[i].chnp->vlbl && (aux = across[i].chnp->vlbl[across[i].vindex]))
X if (!good) /* first found */
X good = aux;
X else
X labfound = !strcmp(good,aux);
X }
X
X if (!good) /* no label found, all undefined */
X *lab = NULL;
X else if (labfound) /* all labels are the same -- return any */
X *lab = good;
X else /* different -- return fake label (will be processed in function, but rejected later) */
X *lab = nothing;
X
X if (*min == VERYLARGE || *max == -VERYLARGE) /* all points undefined */
X return(FALSE);
X else
X return(TRUE);
X}
X
Xchar *comm_lget()
X/* check labels (like find_ran above), but also advance pointers */
X{
X int i, j;
X static char nothing[] = "";
X int labfound = 1;
X char *good = NULL, *aux;
X
X for (i=0; i<data_head.chunks; i++) {
X if (!across[i].chnp) continue;
X j = across[i].vindex;
X if (across[i].chnp->dval[j] != VERYLARGE && across[i].chnp->vlbl && (aux = across[i].chnp->vlbl[j]))
X if (!good) /* first found */
X good = aux;
X else
X labfound = !strcmp(good,aux);
X if (++across[i].vindex == across[i].chnp->used) {
X across[i].chnp = across[i].chnp->next;
X across[i].vindex = 0;
X }
X }
X
X if (!good) /* no label found, all undefined */
X return (NULL);
X else if (labfound) /* all labels are the same -- return any */
X return (good);
X else
X return (nothing);
X}
X
Xdo_axis(a1,a2,xb,xm,yb,ym,reserved)
Xdouble *a1, *a2;
Xint xb, xm, yb, ym;
XBOOLEAN reserved; /* should we shrink drawing area, or there's enough space ? */
X/* draws axis for bars, reserve space for values, put tickmarks with labels */
X{
X double minv = *a1, maxv = *a2, tick, minpl, maxpl, unit;
X int dirNS = !((int)gravity&1);
X int i, j, space;
X
X space = dirNS ? (ym-yb)/t->v_char : (xm-xb)/t->h_char;
X if (minv == maxv)
X tick=0;
X else if (log_y) {
X minpl = minv = floor(minv)+log10(2.0)<minv ? floor(minv)+log10(2.0) : floor(minv);
X maxpl = maxv = ceil(maxv)-log10(2.0)>maxv ? ceil(maxv)-log10(2.0) : ceil(maxv);
X tick = floor(log10(maxv-minv))+1;
X }
X else {
X double aux = fabs(minv)>fabs(maxv) ? fabs(minv) : fabs(maxv);
X tick = exp10(floor(log10(aux)));
X aux = exp10(floor(log10(aux)-1));
X minpl = tick * ceil(minv/tick);
X maxpl = tick * floor(maxv/tick);
X minv = aux * floor(minv/aux);
X maxv = aux * ceil(maxv/aux);
X if ((maxv-minv)/tick <= 3.0) {
X int flip = 1;
X do {
X tick /= flip ? 2.0 : 5.0;
X flip = 1-flip;
X minpl = tick * ceil(minv/tick);
X maxpl = tick * floor(maxv/tick);
X } while ((maxv-minv)/tick <= 3.0);
X }
X if ((maxpl-minpl)/tick >= (double)space) {
X int flip = 1;
X do {
X tick *= flip ? 5.0 : 2.0;
X flip = 1-flip;
X minpl = tick * ceil(minv/tick);
X maxpl = tick * floor(maxv/tick);
X } while ((maxpl-minpl)/tick >= (double)space);
X }
X }
X
X if (!tick) return(0);
X
X unit = (dirNS ? ym-yb : xm-xb)/(maxv-minv);
X (*t->linetype)(0); /* solid linetype */
X switch (gravity) {
X case SOUTH:
X if (!reserved)
X xb += t->h_char*howmuch + 2*t->h_tic;
X j = xb - 2*t->h_tic;
X (*t->move)(xb,yb);
X (*t->vector)(xb,ym);
X (*t->linetype)(0); /* the only type solid for sure */
X while (minpl<=maxpl) {
X (*t->move)(xb,i=yb+nint((minpl-minv)*unit));
X (*t->vector)(xb-t->h_tic,i);
X put_txt(j, i, make_labl((double) (log_y ? exp10(minpl) : minpl)), RIGHT, 0);
X minpl += tick;
X }
X break;
X case NORTH:
X if (!reserved)
X xm -= t->h_char*howmuch + 2*t->h_tic;
X j = xm + 2*t->h_tic;
X (*t->move)(xm,yb);
X (*t->vector)(xm,ym);
X (*t->linetype)(0); /* the only type solid for sure */
X while (minpl<=maxpl) {
X (*t->move)(xm,i=ym-nint((minpl-minv)*unit));
X (*t->vector)(xm+t->h_tic,i);
X put_txt(j, i, make_labl((double) (log_y ? exp10(minpl) : minpl)), LEFT, 0);
X minpl += tick;
X }
X break;
X case WEST:
X if (!reserved)
X ym -= t->v_char*howmuch + 2*t->v_tic;
X j = ym + 2*t->v_tic;
X (*t->move)(xb,ym);
X (*t->vector)(xm,ym);
X (*t->linetype)(0); /* the only type solid for sure */
X while (minpl<=maxpl) {
X (*t->move)(i=xb+nint((minpl-minv)*unit),ym);
X (*t->vector)(i,ym+t->v_tic);
X put_txt(i, j, make_labl((double) (log_y ? exp10(minpl) : minpl)), LEFT, 1);
X minpl += tick;
X }
X break;
X case EAST:
X if (!reserved)
X yb += t->v_char*howmuch + 2*t->v_tic;
X j = yb - 2*t->v_tic;
X (*t->move)(xm,yb);
X (*t->vector)(xb,yb);
X (*t->linetype)(0); /* the only type solid for sure */
X while (minpl<=maxpl) {
X (*t->move)(i=xm-nint((minpl-minv)*unit),yb);
X (*t->vector)(i,yb-t->v_tic);
X put_txt(i, j, make_labl((double) (log_y ? exp10(minpl) : minpl)), RIGHT, 1);
X minpl += tick;
X }
X break;
X }
X
X *a1 = minv; *a2 = maxv;
X return ( (int) (2*(dirNS ? t->h_tic : t->v_tic) + howmuch*(dirNS ? t->h_char : t->v_char)) );
X /* if (reserved), return value is rejected, so it doesn't matter */
X}
X
X/* from hereon go different labeling functions. The basic one is the first */
X
Xint draw_text(x, y, s, h, w, tc, just, an)
Xint x, y, h, w, tc;
Xchar *s;
Xenum JUSTIFY just;
Xdouble an;
X/* draw text in vector font and return useful info - complementary of h parameter */
X{
X int wid, k, retv, rwid;
X char *p;
X double sc;
X int *d;
X MATRIX R, S, A;
X
X if (!s || !*s || !tc || !h && !w)
X return(0); /* nothing useful can be done */
X if (tc>0 && tc < strlen(s))
X s[tc] = '\0'; /* truncate */
X
X for (p=s, wid=0; *p; p++)
X if (!trt[*p=toascii(*p)].wid)
X wid += trt[0].wid + CHAR_OFF;
X else
X wid += trt[*p].wid + CHAR_OFF;
X rwid = wid;
X
X rotat(-an, R); /* rotate object system (!) */
X
X if (h) {
X sc = (double)(h) / (double)CHAR_GRD;
X wid *= sc;
X retv = wid;
X }
X else
X wid = 0;
X if (!wid || w && wid > w) { /* can't with with desired height -- try to schrink */
X sc = (double)(w)/(double)(rwid);
X wid = w;
X retv = CHAR_GRD*sc; /* return text height */
X }
X scale(sc, sc, S);
X multi(S, R, A);
X
X switch (just) {
X case LEFT: break;
X case CENTRE: {
X wid /= 2; /* and no break */
X }
X case RIGHT: {
X x -= (double)wid*cos(an); /* rotate within coordinate system */
X y -= (double)wid*sin(an);
X }
X }
X if (x<0 || y<0)
X return(0); /* nothing useful - failed */
X
X#ifdef NO_ROMAN_FONT
X
X x += (CHAR_OFF/2)*A[0][0]+A[0][2];
X y += (CHAR_OFF/2)*A[1][0]+A[1][2];
X
X#define MX(v) nint( (*(v))*A[0][0] + (*(v+1))*A[0][1] + A[0][2] )
X#define MY(v) nint( (*(v))*A[1][0] + (*(v+1))*A[1][1] + A[1][2] )
X
X {
X unsigned char *u;
X int i,j;
X for ( ; *s; wid=trt[*s].wid, x+=(wid+CHAR_OFF)*A[0][0]+A[0][2], y+=(wid+CHAR_OFF)*A[1][0]+A[1][2], s++) {
X if (!trt[c=*s].wid) c='\0';
X for (i=0; i<3 && (u=trt[c].def[i]); i++) {
X (*t->move) (x+MX(u), y+MY(u));
X while (*(u+=2))
X (*t->vector) (x+MX(u), y+MY(u));
X }
X }
X }
X
X#undef MX
X#undef MY
X
X#else /* another algorithm: for roman font */
X
X x -= (CHAR_OFF/2)*A[0][0]+A[0][2];
X y -= (CHAR_OFF/2)*A[1][0]+A[1][2];
X
X#define MX(v) nint( ((v)/100)*A[0][0] + ((v)%100)*A[0][1] + A[0][2] )
X#define MY(v) nint( ((v)/100)*A[1][0] + ((v)%100)*A[1][1] + A[1][2] )
X
X for ( ; *s; wid=trt[*s].wid, x+=(wid+CHAR_OFF)*A[0][0]+A[0][2], y+=(wid+CHAR_OFF)*A[1][0]+A[1][2], s++)
X for (d=trt[*s].def; *d; d++)
X if ((k=*d)<0) {
X k = abs(k);
X (*t->move)(x+MX(k), y+MY(k));
X }
X else
X (*t->vector)(x+MX(k), y+MY(k));
X
X#undef MX
X#undef MY
X
X#endif
X
X return(retv);
X}
X
Xmake_just(x, y, j, l, d)
Xint *x, *y;
Xint l, d; /* l != 0 */
Xenum JUSTIFY j;
X/* set terminal justification */
X{
X if (!d) {
X if (j == LEFT)
X (void) (*t->justify_text)(LEFT);
X else if ((*t->justify_text)(j)) ;
X else if (j == CENTRE)
X *x -= t->h_char * l/2;
X else if (j == RIGHT)
X *x -= t->h_char * l;
X else /* impossible */ return;
X }
X else {
X if (j == LEFT)
X (void) (*t->justify_text)(LEFT);
X else if ((*t->justify_text)(j)) ;
X else if (j == CENTRE)
X *y -= t->h_char * l/2;
X else if (j == RIGHT)
X *y -= t->h_char * l;
X else /* impossible */ return;
X }
X}
X
Xput_txt(x,y,s,j,d)
Xint x, y, d;
Xchar *s;
Xenum JUSTIFY j;
X/* put any text on given position, with standard size, sideways or rotated +Pi/2 */
X{
X if (!s || !*s) return;
X if ((trotate || !d) && vect_font == F_WHENN || /* terminal can or need not rotate */
X vect_font == F_NEVER) { /* never use vector font, regardles of anything */
X if (tstate != d)
X (*t->text_angle)(tstate = d);
X make_just(&x, &y, j, strlen(s), d);
X (*t->put_text)(x, y, s);
X }
X else { /* use vector font */
X int i = t->v_char;
X if (d)
X x += t->h_char/2; /* draw_text takes lower-left corner */
X else
X y -= t->h_char/2;
X (void) draw_text(x, y, s, i, 0, -1, j, d*Pi/2);
X }
X}
X
Xput_lab(x,y,s,d,size)
Xint x, y, d, size;
Xchar *s;
X/* put label centered around (x,y), fitting it within given size, use vector font if only allowed */
X{
X int i, j, l;
X
X if (!s || !*s || size<=0)
X return; /* nothing useful */
X
X j = size / t->h_char; /* number of standard chars that can fit */
X i = (l=strlen(s)) < howmuch ? howmuch : l; /* how many chars should we fit ? */
X
X if (vect_font == F_NEVER || /* never use vector font */
X !d && i <= j && vect_font != F_ALWYS) { /* horizontal, fits within req. size, no need for font */
X if (tstate != d)
X (*t->text_angle)(tstate = d);
X make_just(&x, &y, CENTRE, strlen(s), d);
X (*t->put_text)(x, y, s);
X }
X else { /* pain in the ass */
X if (d)
X x += t->h_char/2; /* draw_text takes lower-left corner */
X else
X y -= t->v_char/2;
X i = t->v_char;
X (void) draw_text(x, y, s, i, size, -1, CENTRE, d*Pi/2);
X }
X}
X
Xchar *make_labl(d)
Xdouble d;
X{
X static char buf[200];
X if (d == VERYLARGE || d== -VERYLARGE)
X return(NULL); /* will be rejected later */
X sprintf(buf, tic_form, (float) d); /* it's float from user point of view, and compatibility with Gnuplot */
X return(buf);
X}
X
Xset_hm(min, max)
Xdouble min, max;
X/* find space needed for ticks */
X{
X char buf[200];
X int i;
X sprintf(buf, tic_form, (float) min);
X howmuch = strlen(buf);
X sprintf(buf, tic_form, (float) max);
X if (howmuch < (i=strlen(buf)))
X howmuch = i;
X}
X
Xinit_acrs()
X/* init across pointer structure */
X{
X struct dfile *f = &data_head;
X int i = 0;
X
X while (f = f->dnxt) {
X across[i].chnp = f->data;
X across[i++].vindex = 0;
X }
X}
X
X/* test terminal by drawing border and text */
X/* called from command test */
Xterm_test()
X/* don't use original test_term() from term.c */
X{
X char *str;
X int x,y, xl,yl, i;
X char label[MAX_LINE_LEN];
X
X t = &term_tbl[term];
X if (!term_init) {
X (*t->init)();
X term_init = TRUE;
X }
X screen_ok = FALSE;
X (*t->graphics)();
X /* border linetype */
X (*t->linetype)(-2);
X (*t->move)(0,0);
X (*t->vector)(t->xmax-1,0);
X (*t->vector)(t->xmax-1,t->ymax-1);
X (*t->vector)(0,t->ymax-1);
X (*t->vector)(0,0);
X (void) (*t->justify_text)(LEFT);
X (*t->put_text)(t->h_char*5,t->ymax-t->v_char*3,"Terminal Test");
X (*t->linetype)(0);
X (*t->arrow)(t->h_char*5, t->ymax-t->v_char*5, t->h_char*5, t->ymax/2+t->v_char);
X /* axis linetype */
X (*t->linetype)(-1);
X (*t->move)(t->xmax/2,0);
X (*t->vector)(t->xmax/2,t->ymax-1);
X (*t->move)(0,t->ymax/2);
X (*t->vector)(t->xmax-1,t->ymax/2);
X /* test width and height of characters */
X (*t->linetype)(-2);
X (*t->move)( t->xmax/2-t->h_char*10,t->ymax/2+t->v_char/2);
X (*t->vector)(t->xmax/2+t->h_char*10,t->ymax/2+t->v_char/2);
X (*t->vector)(t->xmax/2+t->h_char*10,t->ymax/2-t->v_char/2);
X (*t->vector)(t->xmax/2-t->h_char*10,t->ymax/2-t->v_char/2);
X (*t->vector)(t->xmax/2-t->h_char*10,t->ymax/2+t->v_char/2);
X (*t->put_text)(t->xmax/2-t->h_char*10,t->ymax/2,
X "12345678901234567890");
X /* test justification */
X (void) (*t->justify_text)(LEFT);
X (*t->put_text)(t->xmax/2,t->ymax/2+t->v_char*5,"left justified");
X str = "centre+d text";
X if ((*t->justify_text)(CENTRE))
X (*t->put_text)(t->xmax/2,
X t->ymax/2+t->v_char*4,str);
X else
X (*t->put_text)(t->xmax/2-strlen(str)*t->h_char/2,
X t->ymax/2+t->v_char*4,str);
X str = "right justified";
X if ((*t->justify_text)(RIGHT))
X (*t->put_text)(t->xmax/2,
X t->ymax/2+t->v_char*3,str);
X else
X (*t->put_text)(t->xmax/2-strlen(str)*t->h_char,
X t->ymax/2+t->v_char*3,str);
X /* test text angle */
X str = "rotated ce+ntred text";
X if ((*t->text_angle)(1)) {
X if ((*t->justify_text)(CENTRE))
X (*t->put_text)(t->v_char,
X t->ymax/2,str);
X else
X (*t->put_text)(t->v_char,
X t->ymax/2-strlen(str)*t->h_char/2,str);
X }
X else {
X (void) (*t->justify_text)(LEFT);
X (*t->put_text)(t->h_char*2,t->ymax/2-t->v_char*2,"Can't rotate text");
X }
X (void) (*t->justify_text)(LEFT);
X (void) (*t->text_angle)(0);
X /* test tic size */
X (*t->move)(t->xmax/2+t->h_tic*2,0);
X (*t->vector)(t->xmax/2+t->h_tic*2,t->v_tic);
X (*t->move)(t->xmax/2,t->v_tic*2);
X (*t->vector)(t->xmax/2+t->h_tic,t->v_tic*2);
X (*t->put_text)(t->xmax/2+t->h_tic*2,t->v_tic*2+t->v_char/2,"test tics");
X /* test line and point types */
X x = t->xmax - t->h_char*4 - t->h_tic*4;
X y = t->ymax - t->v_char;
X for ( i = -2; y > t->v_char; i++ ) {
X (*t->linetype)(i);
X (void) sprintf(label,"%d",i);
X if ((*t->justify_text)(RIGHT))
X (*t->put_text)(x,y,label);
X else
X (*t->put_text)(x-strlen(label)*t->h_char,y,label);
X (*t->move)(x+t->h_char,y);
X (*t->vector)(x+t->h_char*4,y);
X y -= t->v_char;
X }
X /* test bars */
X (*t->linetype)(-1);
X x = t->xmax/2 + t->xmax/12;
X y = t->ymax/6;
X xl = t->xmax/32;
X yl = t->ymax/32;
X (*t->move)(x,y);
X (*t->vector)(x+xl*6,y);
X x += xl/4;
X for (i=1; i<=4; i++, x+=xl*3/2) {
X (*t->linetype)(i-1);
X put_bar(x,y,xl,i*yl,FALSE);
X }
X /* test pies */
X (*t->linetype)(0);
X x = t->xmax/4;
X y = t->ymax/4;
X i = 3*(t->xmax < t->ymax ? t->xmax : t->ymax)/32;
X xl = MCx(0,i,Pi/4);
X yl = MCy(0,i,Pi/4);
X (*t->move)(x+xl,y+yl);
X (*t->vector)(x-xl,y-yl);
X (*t->move)(x-xl,y+yl);
X (*t->vector)(x+xl,y-yl);
X put_arc(x,y,i,Pi/4,3*Pi/2);
X sprintf(label,"(pie sampling is %d)",samples);
X put_txt(x,y-yl-2*(int)(t->v_char),label,CENTRE,0);
X x += t->xmax/32;
X (*t->move)(x+xl,y-yl);
X (*t->vector)(x,y);
X (*t->vector)(x+xl,y+yl);
X put_arc(x,y,i,Pi/4,-Pi/2);
X
X /* experimental code */
X (*t->linetype)(0);
X x = t->xmax/2 + t->xmax/32;
X y = t->ymax*9/10;
X i = t->v_char;
X x += draw_text(x, y, "experimental", i, 0, -1, LEFT, 0.0);
X i = draw_text(x, y, "scalable", i*2, 0, -1, LEFT, -Pi/4);
X x += i*cos(-Pi/4); y += i*sin(-Pi/4);
X (void) draw_text(x, y, "vector font", 0, (int)(t->xmax/16), -1, LEFT, -Pi/2);
X y -= (int)(t->xmax/16);
X (void) draw_text(x, y, "0123456789", 0, (int)(t->xmax/8), -1, LEFT, -Pi);
X
X /* and back into text mode */
X (*t->text)();
X (void) fflush(outfile);
X}
X
X
X
X
X
X
X
X
X
X
X/* included file contains an old version of graphics routines */
X
X#include "fstyles.i"
X
X
X
X
X
SHAR_EOF
$TOUCH -am 0604152590 fgraf.c &&
chmod 0666 fgraf.c ||
echo "restore of fgraf.c failed"
set `wc -c fgraf.c`;Wc_c=$1
if test "$Wc_c" != "22428"; then
echo original size 22428, current size $Wc_c
fi
echo "End of part 2, continue with part 3"
exit 0
More information about the Alt.sources
mailing list