fs@uwasa.fi (Filip Sawicki LAKE) (06/04/90)
Submitted-by: fs@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@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@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@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