home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1409 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  70.1 KB

  1. From: fs@uwasa.fi (Filip Sawicki LAKE)
  2. Newsgroups: alt.sources
  3. Subject: Fchart part 02/04
  4. Message-ID: <1990Jun4.125148.1181@uwasa.fi>
  5. Date: 4 Jun 90 12:51:48 GMT
  6.  
  7. Submitted-by: fs@chyde
  8. Archive-name: Fchart/part02
  9.  
  10. #!/bin/sh
  11. # This is part 02 of Fchart
  12. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  13.  then TOUCH=touch
  14.  else TOUCH=true
  15. fi
  16. # ============= fcmd.c ==============
  17. echo "x - extracting fcmd.c (Text)"
  18. sed 's/^X//' << 'SHAR_EOF' > fcmd.c &&
  19. X/* Fchart - fcmd.c */
  20. X/*
  21. X * Gnuplot code
  22. X * Copyright (C) 1986, 1987, 1990   Thomas Williams, Colin Kelley
  23. X *
  24. X * Permission to use, copy, and distribute this software and its
  25. X * documentation for any purpose with or without fee is hereby granted,
  26. X * provided that the above copyright notice appear in all copies and
  27. X * that both that copyright notice and this permission notice appear
  28. X * in supporting documentation.
  29. X *
  30. X * Permission to modify the software is granted, but not the right to
  31. X * distribute the modified code.  Modifications are to be distributed
  32. X * as patches to released version.
  33. X *
  34. X * This software  is provided "as is" without express or implied warranty.
  35. X *
  36. X *
  37. X * AUTHORS
  38. X *
  39. X *   Original Software:
  40. X *     Thomas Williams,  Colin Kelley.
  41. X *
  42. X *   Gnuplot 2.0 additions:
  43. X *       Russell Lang, Dave Kotz, John Campbell.
  44. X *
  45. X *   Fchart changes and additions:
  46. X *       Piotr Filip Sawicki
  47. X *
  48. X * send your comments or suggestions to fs@uwasa.fi
  49. X *
  50. X */
  51. X#include <stdio.h>
  52. X#include <math.h>
  53. X#include <ctype.h>
  54. X
  55. X#ifdef MSDOS
  56. X#include <process.h>
  57. X
  58. X#ifdef __ZTC__
  59. X#define P_WAIT 0
  60. X#include <time.h>       /* usleep() */
  61. X#else
  62. X
  63. X#ifdef __TURBOC__
  64. X#include <dos.h>        /* sleep() */
  65. X
  66. X#else   /* must be MSC */
  67. X#include <time.h>       /* kludge to provide sleep() */
  68. Xvoid sleep();           /* defined later */
  69. X#endif /* TURBOC */
  70. X#endif /* ZTC */
  71. X
  72. X#endif /* MSDOS */
  73. X
  74. X#include "plot.h"
  75. X#include "fchart.h"
  76. X#include "help.h"
  77. X
  78. X#ifndef STDOUT
  79. X#define STDOUT 1
  80. X#endif
  81. X
  82. X#ifndef HELPFILE
  83. X#define HELPFILE "fchart.gih" /* changed by makefile */
  84. X#endif
  85. X
  86. X/* global defs for default values */
  87. X#define DEF_T_FORMAT "%g"    /* make it as narrow as possible */
  88. X#define EXPL_RAD 0.3        /* ratio of explosion of a slice */
  89. X#define MAXBARWIDTH 0.2        /* default maximal allowable width of bar */
  90. X#define INTERBAR 0.2        /* interbar space in terms of real bar width */
  91. X#define INTERGROUP 0.5        /* space between groups of bars */
  92. X#define OTHER "other"        /* name for combined slice */
  93. X
  94. X/*
  95. X * global variables to hold status of 'set' options
  96. X *
  97. X */
  98. X
  99. XBOOLEAN            autoscale    = TRUE,
  100. X                auto_label    = FALSE,
  101. X                p_clockwise    = TRUE,
  102. X                b_clockwise = TRUE,
  103. X                draw_border = TRUE;
  104. X
  105. Xenum DRAW_STYLE data_style    = ABARS;
  106. Xenum GRAV_DIR    gravity        = SOUTH,
  107. X                explode        = DEFAULT;
  108. Xenum INP_STYLE    inp_style    = PRIVATE;
  109. Xenum FONT_STYLE    vect_font    = F_WHENN;
  110. XBOOLEAN            log_y        = FALSE;
  111. XFILE*            outfile;
  112. Xchar            outstr[MAX_LINE_LEN+1] = "STDOUT";
  113. Xint                samples        = SAMPLES;
  114. Xint                term        = 0;            /* unknown term is 0 */
  115. Xint                xmin        = -1,
  116. X                xmax        = -1;
  117. Xdouble            base        = 0.0;
  118. Xdouble            loff        = 0.0,
  119. X                roff        = 0.0,
  120. X                toff        = 0.0,
  121. X                boff        = 0.0;
  122. Xdouble            b_wid        = MAXBARWIDTH,
  123. X                b_int        = INTERBAR,
  124. X                b_spc        = INTERGROUP;
  125. Xdouble            radexp        = EXPL_RAD;        /* explosion power */
  126. Xdouble            zero        = ZERO;            /* zero threshold, not 0! */
  127. Xint                HLitem        = HL_NON;        /* no highliting by default */
  128. Xstruct pair        data_place    = { -1, -1 },    /* not defined yet */
  129. X                label_plac    = { -1, -1 };    /* not defined yet */
  130. Xfloat            xsize        = 1.0,
  131. X                ysize        = 1.0;
  132. Xdouble            treshold    = 0.0;
  133. Xchar            thrname[MAX_LINE_LEN+1] = OTHER;
  134. Xchar             tic_form[MAX_LINE_LEN+1]    = DEF_T_FORMAT;
  135. Xint                strunc        = -1;
  136. X
  137. Xstruct dfile data_head = { NULL, 0.0, 0.0, 0, 0, HL_NON, FALSE, NULL, NULL } ;
  138. X
  139. XBOOLEAN screen_ok;
  140. XBOOLEAN term_init;
  141. X/* BOOLEAN undefined; */  /* probably not even used */
  142. X
  143. X/*
  144. X * instead of <strings.h>
  145. X */
  146. X
  147. Xchar *gets(),*getenv(),*sprintf();    /* for lint only */
  148. Xchar *strcpy(),*strncpy(),*strcat();
  149. X
  150. Xextern double real();
  151. Xextern void set_label(), set_nolabel(), set_arrow(), set_noarrow();
  152. Xextern void show_labels(), show_arrow();
  153. X
  154. Xextern struct termentry term_tbl[];
  155. X
  156. Xstruct lexical_unit token[MAX_TOKENS];
  157. Xchar input_line[MAX_LINE_LEN+1] = "";
  158. Xint num_tokens, c_token;
  159. X
  160. Xstatic char replot_line[MAX_LINE_LEN+1];
  161. Xstatic int plot_token;                    /* start of 'plot' command */
  162. X
  163. Xextern void squash_spaces(), lower_case();
  164. X
  165. Xcom_line()
  166. X{
  167. X    read_line(PROMPT);
  168. X
  169. X    screen_ok = interactive;        /* see 'Gnuplot' why */
  170. X
  171. X    do_line();
  172. X}
  173. X
  174. X
  175. Xdo_line()      /* also used in load_file */
  176. X{
  177. X    if (is_system(input_line[0])) {
  178. X        do_system();
  179. X        fputs("!\n",stderr);
  180. X        return;
  181. X    }
  182. X    num_tokens = scanner(input_line);
  183. X    c_token = 0;
  184. X    while(c_token < num_tokens) {
  185. X        command();
  186. X        if (c_token < num_tokens)    /* something after command */
  187. X            if (equals(c_token,";"))
  188. X                c_token++;
  189. X            else
  190. X                    int_error("';' expected",c_token);
  191. X    }
  192. X}
  193. X
  194. Xcommand()
  195. X{
  196. X    static char sv_file[MAX_LINE_LEN+1];
  197. X            /* string holding name of save or load file */
  198. X
  199. X    if (equals(c_token,"help") || equals(c_token,"?")) {
  200. X        c_token++;
  201. X        do_help();
  202. X    }
  203. X    else if (almost_equals(c_token,"test")) {
  204. X        c_token++;
  205. X        term_test();
  206. X    }
  207. X    else if (almost_equals(c_token,"pa$use")) {
  208. X        int stime=1, text=0;
  209. X        char buf[MAX_LINE_LEN+1];
  210. X
  211. X        c_token++;
  212. X        if (equals(c_token,"-")) stime=-1, c_token++;
  213. X        stime *= (int)real(c_token);
  214. X        c_token++;
  215. X        if (!(END_OF_COMMAND)) {
  216. X            if (!isstring(c_token))
  217. X                int_error("expecting string",c_token);
  218. X            else {
  219. X                quote_str(buf,c_token);
  220. X                fprintf (stderr, "%s",buf);
  221. X                text = 1;
  222. X            }
  223. X        }
  224. X        if (stime < 0) fgets (buf,MAX_LINE_LEN,stdin);  /* Hold until CR hit */
  225. X#ifdef __ZTC__
  226. X        if (stime > 0) usleep((unsigned long) stime);
  227. X#else        
  228. X        if (stime > 0) sleep((unsigned) stime);
  229. X#endif
  230. X        if (text != 0 && stime >= 0) fprintf (stderr,"\n");
  231. X        c_token++;
  232. X        screen_ok = FALSE;
  233. X    }
  234. X    else if (almost_equals(c_token,"p$lot") ||
  235. X             almost_equals(c_token,"d$raw")) {
  236. X        plot_token = c_token++;
  237. X        plotrequest(FALSE);
  238. X    }
  239. X    else if (almost_equals(c_token,"tp$lot") ||
  240. X             almost_equals(c_token,"td$raw") ||
  241. X             almost_equals(c_token,"xp$lot") ||        /* for backward compatibility */
  242. X             almost_equals(c_token,"xd$raw") ||        /* for backward compatibility */
  243. X             almost_equals(c_token,"trans_plot") ||
  244. X             almost_equals(c_token,"trans_draw")) {
  245. X        plot_token = c_token++;
  246. X        plotrequest(TRUE);
  247. X    }
  248. X    else if (almost_equals(c_token,"rep$lot") ||
  249. X             almost_equals(c_token,"red$raw")) {
  250. X        c_token++;
  251. X        if (replot_line[0] == '\0') 
  252. X            int_error("no previous plot",c_token);
  253. X        if (!END_OF_COMMAND) {
  254. X            char str[MAX_LINE_LEN+1];
  255. X            capture(str,c_token,num_tokens-1);
  256. X            if ((strlen(str)+strlen(input_line)) <= MAX_LINE_LEN-1) {
  257. X                (void) strcat(replot_line,",");
  258. X                (void) strcat(replot_line,str);
  259. X            }
  260. X            else
  261. X                int_error("plot line too long with replot arguments",c_token);
  262. X        }
  263. X        (void) strcpy(input_line,replot_line);
  264. X        screen_ok = FALSE;
  265. X        num_tokens = scanner(input_line);
  266. X        c_token = 1;                    /* skip the 'plot' part */
  267. X        plotrequest(almost_equals(0,"td$raw") ||
  268. X                    almost_equals(0,"tp$lot") ||
  269. X                    almost_equals(0,"xd$raw") ||
  270. X                    almost_equals(0,"xp$lot") ||
  271. X                    almost_equals(0,"tr$ans_plot") ||
  272. X                    almost_equals(0,"tr$ans_draw"));  /* fetch plot type */
  273. X    }
  274. X    else if (almost_equals(c_token,"se$t"))
  275. X        set_stuff();
  276. X    else if (almost_equals(c_token,"sh$ow"))
  277. X        show_stuff();
  278. X    else if (almost_equals(c_token,"sa$ve")) {
  279. X        c_token++;
  280. X        if (END_OF_COMMAND || !isstring(c_token))
  281. X            int_error("name of file expected", c_token);
  282. X        quote_str(sv_file,c_token);
  283. X        save_sets(fopen(sv_file,"w"));
  284. X        /* c_token updated in save_sets */
  285. X    }
  286. X    else if (almost_equals(c_token,"cl$ear")) {
  287. X        if (!term_init) {
  288. X            (*term_tbl[term].init)();
  289. X            term_init = TRUE;
  290. X        }
  291. X        (*term_tbl[term].graphics)();
  292. X        (*term_tbl[term].text)();
  293. X        (void) fflush(outfile);
  294. X        screen_ok = FALSE;
  295. X        c_token++;
  296. X    }
  297. X    else if (almost_equals(c_token,"she$ll")) {
  298. X        do_shell();
  299. X        screen_ok = FALSE;
  300. X        c_token++;
  301. X    }
  302. X    else if (almost_equals(c_token,"l$oad") ||
  303. X             almost_equals(c_token,"r$ead")) {
  304. X        if (!isstring(++c_token))
  305. X            int_error("expecting filename",c_token);
  306. X        else {
  307. X            quote_str(sv_file,c_token);
  308. X            load_file(fopen(sv_file,"r"));    
  309. X        /* input_line[] and token[] now destroyed! */
  310. X            c_token = num_tokens = 0;
  311. X        }
  312. X    }
  313. X    else if (almost_equals(c_token,"ex$it") ||
  314. X            almost_equals(c_token,"q$uit")) {
  315. X        done(IO_SUCCESS);
  316. X    }
  317. X    else if (!equals(c_token,";")) {        /* null statement */
  318. X        int_error("Invalid command. Try:\n\
  319. X'?/help', 'test', 'pause', '[t]draw/[t]plot',\n\
  320. X'replot/redraw', 'set', 'show', 'save', 'shell',\n\
  321. X'load/read', 'exit/quit'",c_token);
  322. X    }
  323. X}
  324. X
  325. X
  326. Xenum DRAW_STYLE
  327. Xget_style()
  328. X{
  329. Xregister enum DRAW_STYLE ps;
  330. X
  331. X    c_token++;
  332. X    if (almost_equals(c_token,"a$djacent_bars"))
  333. X        ps = ABARS;
  334. X    else if (almost_equals(c_token,"l$ayer_bars"))
  335. X        ps = LAYB;
  336. X    else if (almost_equals(c_token,"s$tacked_bars"))
  337. X        ps = SBAR;
  338. X    else if (almost_equals(c_token,"p$iechart"))
  339. X        ps = PIECHART;
  340. X    else
  341. X        int_error("expecting 'adjacent_bars', 'stacked_bars', 'layer_bars' or 'piechart'",c_token);
  342. X    c_token++;
  343. X    return(ps);
  344. X}
  345. X
  346. Xenum GRAV_DIR
  347. Xget_gravity()
  348. X{
  349. X    c_token++;
  350. X    if (END_OF_COMMAND) return(DEFAULT);
  351. X    else if (almost_equals(c_token,"b$ottom") || almost_equals(c_token,"s$outh")) {
  352. X        c_token++;
  353. X        return(SOUTH);
  354. X    }
  355. X    else if (almost_equals(c_token,"t$op") || almost_equals(c_token,"n$orth")) {
  356. X        c_token++;
  357. X        return(NORTH);
  358. X    }
  359. X    else if (almost_equals(c_token,"l$eft") || almost_equals(c_token,"w$est")) {
  360. X        c_token++;
  361. X        return(WEST);
  362. X    }
  363. X    else if (almost_equals(c_token,"r$ight") || almost_equals(c_token,"e$ast")) {
  364. X        c_token++;
  365. X        return(EAST);
  366. X    }
  367. X    else
  368. X        int_error("expecting direction: 'left/west', 'right/east',\n'bottom/south' or 'top/north'",c_token);
  369. X    /*NOTREACHED*/
  370. X}
  371. X
  372. Xenum INP_STYLE
  373. Xget_input()
  374. X{
  375. X    if (END_OF_COMMAND) return(PRIVATE);
  376. X    else if (almost_equals(c_token,"g$nuplot")) {
  377. X        c_token++;
  378. X        return(GNUPLOT);
  379. X    }
  380. X    else if (almost_equals(c_token,"p$rivate")) {
  381. X        c_token++;
  382. X        return(PRIVATE);
  383. X    }
  384. X    else if (almost_equals(c_token,"c$ustomized")) {
  385. X        c_token++;
  386. X        return(CUSTOMD);
  387. X    }
  388. X    else
  389. X        int_error("expected 'gnuplot', 'private' or 'customized'",c_token);
  390. X    /*NOTREACHED*/
  391. X}
  392. X
  393. Xset_stuff()
  394. X{
  395. X    static char testfile[MAX_LINE_LEN+1];
  396. X
  397. X    if (almost_equals(++c_token,"b$ar")) {
  398. X        set_bar_stuff();
  399. X    }
  400. X    else if (almost_equals(c_token,"fr$ame")) {
  401. X        draw_border = TRUE;
  402. X        c_token++;
  403. X    }
  404. X    else if (almost_equals(c_token,"nof$rame")) {
  405. X        draw_border = FALSE;
  406. X        c_token++;
  407. X    }
  408. X    else if (almost_equals(c_token,"for$mat")) {
  409. X        c_token++;
  410. X        if (END_OF_COMMAND)
  411. X            (void) strcpy(tic_form, DEF_T_FORMAT);
  412. X        else if (!isstring(c_token))
  413. X            int_error("enquoted format expected", c_token);
  414. X        else 
  415. X            quote_str(tic_form, c_token++);
  416. X    }
  417. X    else if (almost_equals(c_token,"fon$t")) {
  418. X        c_token++;
  419. X        if (END_OF_COMMAND)
  420. X            vect_font = F_ALWYS;
  421. X        else {
  422. X            if (almost_equals(c_token,"n$ever")) 
  423. X                vect_font = F_NEVER;
  424. X            else if (almost_equals(c_token,"w$hen_needed"))
  425. X                vect_font = F_WHENN;
  426. X            else if (almost_equals(c_token,"r$otated"))
  427. X                vect_font = F_ROTAT;
  428. X            else if (almost_equals(c_token,"a$lways"))
  429. X                vect_font = F_ALWYS;
  430. X            else
  431. X                int_error("'never', 'when_needed', 'rotated', or 'always' expected",c_token);
  432. X            c_token++;
  433. X        }
  434. X    }    
  435. X    else if (almost_equals(c_token,"au$tolabeling")) {
  436. X        auto_label = TRUE;
  437. X        c_token++;
  438. X    }
  439. X    else if (almost_equals(c_token,"noau$tolabeling")) {
  440. X        auto_label = FALSE;
  441. X        c_token++;
  442. X    }
  443. X    else if (almost_equals(c_token,"ar$row")) {
  444. X        c_token++;
  445. X        set_arrow(TRUE);
  446. X    }
  447. X    else if (almost_equals(c_token,"noar$row")) {
  448. X        c_token++;
  449. X        set_noarrow();
  450. X    }
  451. X    else if (almost_equals(c_token,"c$ustomized")) {
  452. X        c_token++;
  453. X        if (END_OF_COMMAND) {
  454. X            data_place.from = -1;    /* not defined */
  455. X            label_plac.from = -1;    /* thus no label */
  456. X        }
  457. X        else {
  458. X            if (!equals(c_token,"["))
  459. X                int_error("expecting '['",c_token);
  460. X            c_token++;
  461. X            load_range(&data_place.from,&data_place.upto);
  462. X            if (!equals(c_token,"]"))
  463. X                int_error("expecting ']'",c_token);
  464. X            c_token++;
  465. X            if (END_OF_COMMAND)
  466. X                label_plac.from = -1;    /* no label */
  467. X            else {
  468. X                if (equals(c_token,",")) c_token++;        /* optional ',' */
  469. X                if (!equals(c_token,"["))
  470. X                    int_error("expecting '['",c_token);
  471. X                c_token++;
  472. X                load_range(&label_plac.from,&label_plac.upto);
  473. X                if (!equals(c_token,"]"))
  474. X                    int_error("expected ']'",c_token);
  475. X                c_token++;
  476. X            }
  477. X            if (!check_ranges(&data_place,&label_plac)) {    /* overlapping ranges ? */
  478. X                data_place.from = label_plac.from = -1;
  479. X                int_error("value and label places are overlapping or are empty",NO_CARET);
  480. X            }
  481. X        }
  482. X    }
  483. X    else if (almost_equals(c_token,"h$ighlight")) {
  484. X        c_token++;
  485. X        HLitem = get_HL();
  486. X    }
  487. X    else if (almost_equals(c_token,"i$nput")) {
  488. X        c_token++;
  489. X        inp_style = get_input();
  490. X    }
  491. X    else if (almost_equals(c_token,"lo$gscale")) {
  492. X        c_token++;
  493. X        log_y = TRUE;
  494. X    }
  495. X    else if (almost_equals(c_token,"nolo$gscale")) {
  496. X        log_y = FALSE;
  497. X        c_token++;
  498. X    }
  499. X    else if (almost_equals(c_token,"la$bel")) {
  500. X        c_token++;
  501. X        set_label();
  502. X    }
  503. X    else if (almost_equals(c_token,"nola$bel")) {
  504. X        c_token++;
  505. X        set_nolabel();
  506. X    }
  507. X    else if (almost_equals(c_token,"li$ne")) {
  508. X        c_token++;
  509. X        set_arrow(FALSE);
  510. X    }
  511. X    else if (almost_equals(c_token,"noli$ne")) {
  512. X        c_token++;
  513. X        set_noarrow();
  514. X    }    
  515. X    else if (almost_equals(c_token,"of$fsets")) {
  516. X        c_token++;
  517. X        if (END_OF_COMMAND) {
  518. X            loff = roff = toff = boff = 0.0;  /* Reset offsets */
  519. X        }
  520. X        else {
  521. X            load_offsets (&loff,&roff,&toff,&boff);
  522. X            if ((loff>1.0 ? loff/100.0 : loff) + (roff>1.0 ? roff/100.0 : roff) >= 1.0 ||
  523. X                (boff>1.0 ? boff/100.0 : boff) + (toff>1.0 ? toff/100.0 : toff) >= 1.0) {
  524. X                loff = roff = toff = boff = 0.0;  /* Reset offsets for the future */
  525. X                int_error("null picture size within given offsets",NO_CARET);
  526. X            }
  527. X        }
  528. X    }
  529. X    else if (almost_equals(c_token,"o$utput")) {
  530. X        register FILE *f;
  531. X
  532. X        c_token++;
  533. X        if (END_OF_COMMAND) {    /* no file specified */
  534. X             UP_redirect (4);
  535. X            if (outfile != stdout) /* Never close stdout */
  536. X                (void) fclose(outfile);
  537. X            outfile = stdout; /* Avoid the dup... */
  538. X            term_init = FALSE;
  539. X            (void) strcpy(outstr,"STDOUT");
  540. X        } else if (!isstring(c_token))
  541. X            int_error("expecting filename",c_token);
  542. X        else {
  543. X            quote_str(testfile,c_token);
  544. X            if (!(f = fopen(testfile,"w"))) {
  545. X              os_error("cannot open file; output not changed",c_token);
  546. X            }
  547. X            if (outfile != stdout) /* Never close stdout */
  548. X                (void) fclose(outfile);
  549. X            outfile = f;
  550. X            term_init = FALSE;
  551. X            outstr[0] = '\'';
  552. X            (void) strcat(strcpy(outstr+1,testfile),"'");
  553. X             UP_redirect (1);
  554. X        }
  555. X        c_token++;
  556. X    }
  557. X    else if (almost_equals(c_token,"p$ie")) {
  558. X        set_pie_stuff();
  559. X    }
  560. X    else if (almost_equals(c_token,"si$ze")) {
  561. X        c_token++;
  562. X        if (END_OF_COMMAND) {
  563. X            xsize = 1.0;
  564. X            ysize = 1.0;
  565. X        }
  566. X        else {
  567. X            xsize = (float)real(c_token);
  568. X            c_token++;
  569. X            if (!equals(c_token,","))
  570. X                int_error("',' expected",c_token);
  571. X            c_token++;
  572. X            if (END_OF_COMMAND)
  573. X                int_error("value for ysize expected",c_token);
  574. X            ysize = (float)real(c_token);
  575. X            c_token++;
  576. X        }
  577. X    }        
  578. X    else if (almost_equals(c_token,"st$yle")) {
  579. X        data_style = get_style();
  580. X    }
  581. X    else if (almost_equals(c_token,"te$rminal")) {
  582. X        c_token++;
  583. X        if (END_OF_COMMAND) {
  584. X            list_terms();
  585. X            screen_ok = FALSE;
  586. X        }
  587. X        else {
  588. X            if (term && term_init) {
  589. X                (*term_tbl[term].reset)();
  590. X                (void) fflush(outfile);
  591. X            }            
  592. X            term = set_term(c_token);
  593. X            c_token++;
  594. X        }
  595. X    }
  596. X    else if (almost_equals(c_token,"ti$tle")) {
  597. X        c_token++;
  598. X        if (END_OF_COMMAND) {
  599. X            if (data_head.fname)
  600. X                free(data_head.fname);
  601. X            data_head.fname = NULL;
  602. X        }
  603. X        else if (isstring(c_token)) {
  604. X            m_quote_capture(&(data_head.fname), c_token, c_token);
  605. X            c_token++;
  606. X        }
  607. X        else
  608. X            int_error("title within quotes expected", c_token);
  609. X    }
  610. X    else if (almost_equals(c_token,"tr$uncate")) {
  611. X        c_token++;
  612. X        if (END_OF_COMMAND)
  613. X            strunc = 0;
  614. X        else {
  615. X            strunc = real(c_token);
  616. X            c_token++;
  617. X        }
  618. X    }
  619. X    else if (almost_equals(c_token,"not$runcate")) {
  620. X        c_token++;
  621. X        strunc = -1;
  622. X    }
  623. X    else if (almost_equals(c_token,"r$ange")) {
  624. X        c_token++;
  625. X        if (END_OF_COMMAND) xmin=-1;
  626. X        else {
  627. X            if (!equals(c_token,"["))
  628. X                int_error("expecting '['",c_token);
  629. X            c_token++;
  630. X            load_range(&xmin,&xmax);
  631. X            if (!equals(c_token,"]"))
  632. X                int_error("expecting ']'",c_token);
  633. X            c_token++;
  634. X            if (xmax != -1 && xmax < xmin) {
  635. X                xmin = -1;  /* whole */
  636. X                int_error("given range is empty",NO_CARET);
  637. X            }
  638. X        }
  639. X    }
  640. X    else if (almost_equals(c_token,"z$ero") ||
  641. X             almost_equals(c_token,"eps$ilon")) {
  642. X        int sign=1;
  643. X        c_token++;
  644. X        if (equals(c_token,"-")) sign=-1, c_token++;
  645. X        zero = sign*real(c_token);
  646. X        c_token++;
  647. X    }
  648. X    else
  649. X        int_error(
  650. X    "valid set options:  'bar', '[no]logscale',\n\
  651. X'customized', 'format', 'highlight', 'offsets'\n\
  652. X'output', 'pie', 'style', '[no]autolabeling',\n\
  653. X'terminal', 'title', 'range', 'zero/epsilon',\n\
  654. X'[no]frame', 'font', '[no]truncate', '[no]label',\n\
  655. X'[no]arrow', '[no]line'",
  656. X    c_token);
  657. X}
  658. X
  659. Xset_bar_stuff()
  660. X{
  661. X    if (almost_equals(++c_token,"a$utoscale")) {
  662. X        autoscale = TRUE;
  663. X        c_token++;
  664. X    }
  665. X    else if (almost_equals(c_token,"noa$utoscale")) {
  666. X        autoscale = FALSE;
  667. X        c_token++;
  668. X    }
  669. X    else if (almost_equals(c_token,"b$ase")) {
  670. X        int sign = 1;
  671. X        c_token++;
  672. X        if (END_OF_COMMAND) base = 0.0;
  673. X        else {
  674. X            if (equals(c_token,"-")) c_token++, sign=-1;
  675. X            base = sign*real(c_token);
  676. X            c_token++;
  677. X        }
  678. X    }
  679. X    else if (almost_equals(c_token,"cl$ockwise")) {
  680. X        b_clockwise = TRUE;
  681. X        c_token++;
  682. X    }
  683. X    else if (almost_equals(c_token,"co$unter_clockwise")) {
  684. X        b_clockwise = FALSE;
  685. X        c_token++;
  686. X    }
  687. X    else if (almost_equals(c_token,"g$ravitation")) {
  688. X        gravity = get_gravity();
  689. X        if (gravity==DEFAULT) gravity = SOUTH;
  690. X    }
  691. X    else if (almost_equals(c_token,"w$idth")) {
  692. X        c_token++;
  693. X        if (END_OF_COMMAND) {
  694. X            b_wid = MAXBARWIDTH;
  695. X            b_int = INTERBAR;
  696. X            b_spc = INTERGROUP;
  697. X        }
  698. X        else
  699. X            load_offsets(&b_wid, &b_int, &b_spc, (double *) NULL);
  700. X    }
  701. X    else
  702. X        int_error("valid options:  '[no]autoscale', 'base',\n\
  703. X'[counter_]clockwise', 'gravitation', 'width'",c_token);
  704. X}
  705. X
  706. Xset_pie_stuff()
  707. X{
  708. X    if (almost_equals(++c_token,"ex$plode")) {
  709. X        explode = get_gravity();
  710. X    }
  711. X    else if (almost_equals(c_token,"cl$ockwise")) {
  712. X        p_clockwise = TRUE;
  713. X        c_token++;
  714. X    }
  715. X    else if (almost_equals(c_token,"co$unter_clockwise")) {
  716. X        p_clockwise = FALSE;
  717. X        c_token++;
  718. X    }
  719. X    else if (almost_equals(c_token,"r$adius")) {
  720. X        c_token++;
  721. X        if (END_OF_COMMAND)
  722. X            radexp = EXPL_RAD;
  723. X        else {
  724. X            radexp = real(c_token);
  725. X            c_token++;
  726. X        }
  727. X    }
  728. X    else if (almost_equals(c_token,"s$amples")) {
  729. X        register int tsamp;
  730. X
  731. X        c_token++;
  732. X        tsamp = (int)real(c_token);
  733. X        if (tsamp < 1)
  734. X            int_error("sampling rate must be > 0; sampling unchanged",
  735. X                c_token);
  736. X        else samples = tsamp;
  737. X        c_token++;
  738. X    }
  739. X    else if (almost_equals(c_token,"t$hreshold")) {
  740. X        c_token++;
  741. X        if (END_OF_COMMAND) {
  742. X            treshold = 0.0;
  743. X            strcpy(thrname, OTHER);
  744. X        }
  745. X        else {
  746. X            treshold = real(c_token);
  747. X            c_token++;
  748. X            if (END_OF_COMMAND)
  749. X                strcpy(thrname, OTHER);
  750. X            else if (!isstring(c_token))
  751. X                int_error("name in quotes expected", c_token);
  752. X            else {
  753. X                quote_str(thrname, c_token);
  754. X                c_token++;
  755. X            }
  756. X        }
  757. X    }
  758. X    else
  759. X        int_error("valid options: '[counter_]clockwise',\n\
  760. X'explode', 'radius', 'samples', 'threshold'",c_token);
  761. X}
  762. X
  763. Xget_HL()
  764. X{
  765. X    if (END_OF_COMMAND) return(HL_NON);
  766. X    else if (almost_equals(c_token,"n$one")) {
  767. X        c_token++;
  768. X        return(HL_NON);
  769. X    }
  770. X    else if (almost_equals(c_token,"mi$nim")) {
  771. X        c_token++;
  772. X        return(HL_MIN);
  773. X    }
  774. X    else if (almost_equals(c_token,"ma$xim")) {
  775. X        c_token++;
  776. X        return(HL_MAX);
  777. X    }
  778. X    else if (isnumber(c_token)) {
  779. X        return((int) real(c_token++));
  780. X    }
  781. X    else
  782. X        int_error("'maximum', 'minimum', 'none' or number expected",c_token);
  783. X    /*NOTREACHED*/
  784. X}
  785. X
  786. Xshow_stuff()
  787. X{
  788. X    if (almost_equals(++c_token,"sc$ale")) {
  789. X        (void) putc('\n',stderr);
  790. X        show_autoscale();
  791. X        c_token++;
  792. X    }
  793. X    else if (almost_equals(c_token,"au$tolabeling")) {
  794. X        (void) putc('\n',stderr);
  795. X        show_label();
  796. X        c_token++;
  797. X    }
  798. X    else if (almost_equals(c_token,"lo$gscale")) {
  799. X        (void) putc('\n',stderr);
  800. X        show_logscale();
  801. X        c_token++;
  802. X    }
  803. X    else if (almost_equals(c_token,"la$bel")) {
  804. X        (void) putc('\n',stderr);
  805. X        c_token++;
  806. X        if (END_OF_COMMAND)
  807. X            show_labels(0, stderr, FALSE);
  808. X        else {
  809. X            show_labels((int)real(c_token), stderr, FALSE);
  810. X            c_token++;
  811. X        }
  812. X    }
  813. X    else if (almost_equals(c_token,"li$ne") || almost_equals(c_token,"ar$row")) {
  814. X        (void) putc('\n',stderr);
  815. X        c_token++;
  816. X        if (END_OF_COMMAND)
  817. X            show_arrow(0, stderr, FALSE);
  818. X        else {
  819. X            show_arrow((int)real(c_token), stderr, FALSE);
  820. X            c_token++;
  821. X        }
  822. X    }    
  823. X    else if (almost_equals(c_token,"bas$e")) {
  824. X        (void) putc('\n',stderr);
  825. X        show_base();
  826. X        c_token++;
  827. X    }
  828. X    else if (almost_equals(c_token,"fr$ame")) {
  829. X        (void) putc('\n',stderr);
  830. X        show_border();
  831. X        c_token++;
  832. X    }
  833. X    else if (almost_equals(c_token,"for$mat")) {
  834. X        (void) putc('\n',stderr);
  835. X        show_format();
  836. X        c_token++;
  837. X    }
  838. X    else if (almost_equals(c_token,"fon$t")) {
  839. X        (void) putc('\n',stderr);
  840. X        show_font();
  841. X        c_token++;
  842. X    }    
  843. X    else if (almost_equals(c_token,"cl$ockwise")) {
  844. X        (void) putc('\n',stderr);
  845. X        show_clock(TRUE);
  846. X        show_clock(FALSE);
  847. X        c_token++;
  848. X    }
  849. X    else if (almost_equals(c_token,"cu$stomized")) {
  850. X        (void) putc('\n',stderr);
  851. X        show_custom();
  852. X        c_token++;
  853. X    }
  854. X    else if (almost_equals(c_token,"ex$plode")) {
  855. X        (void) putc('\n',stderr);
  856. X        show_explode();
  857. X        c_token++;
  858. X    }
  859. X    else if (almost_equals(c_token,"gr$avitation")) {
  860. X        (void) putc('\n',stderr);
  861. X        show_gravity();
  862. X        c_token++;
  863. X    }
  864. X    else if (almost_equals(c_token,"h$ighlight")) {
  865. X        (void) putc('\n',stderr);
  866. X        show_HLset();
  867. X        c_token++;
  868. X    }
  869. X    else if (almost_equals(c_token,"i$nput")) {
  870. X        (void) putc('\n',stderr);
  871. X        show_input();
  872. X        c_token++;
  873. X    }
  874. X    else if (almost_equals(c_token,"of$fsets")) {
  875. X        (void) putc('\n',stderr);
  876. X        show_offsets();
  877. X        c_token++;
  878. X    }
  879. X    else if (almost_equals(c_token,"o$utput")) {
  880. X        (void) putc('\n',stderr);
  881. X        show_output();
  882. X        c_token++;
  883. X    }
  884. X    else if (almost_equals(c_token,"sa$mples")) {
  885. X        (void) putc('\n',stderr);
  886. X        show_samples();
  887. X        c_token++;
  888. X    }
  889. X    else if (almost_equals(c_token,"st$yle")) {
  890. X        (void) putc('\n',stderr);
  891. X        c_token++;
  892. X        show_style();
  893. X    }
  894. X    else if (almost_equals(c_token,"si$ze")) {
  895. X        (void) putc('\n',stderr);
  896. X        c_token++;
  897. X        show_size();
  898. X    }
  899. X    else if (almost_equals(c_token,"te$rminal")) {
  900. X        (void) putc('\n',stderr);
  901. X        show_term();
  902. X        c_token++;
  903. X    }
  904. X    else if (almost_equals(c_token,"ti$tle")) {
  905. X        (void) putc('\n',stderr);
  906. X        show_title();
  907. X        c_token++;
  908. X    }
  909. X    else if (almost_equals(c_token,"th$reshold")) {
  910. X        (void) putc('\n',stderr);
  911. X        show_tresh();
  912. X        c_token++;
  913. X    }
  914. X    else if (almost_equals(c_token,"tr$uncate")) {
  915. X        (void) putc('\n',stderr);
  916. X        show_trunc();
  917. X        c_token++;
  918. X    }    
  919. X    else if (almost_equals(c_token,"w$idth")) {
  920. X        (void) putc('\n',stderr);
  921. X        show_width();
  922. X        c_token++;
  923. X    }
  924. X    else if (almost_equals(c_token,"ve$rsion")) {
  925. X        show_version();
  926. X        c_token++;
  927. X    }
  928. X    else if (almost_equals(c_token,"rad$ius")) {
  929. X        (void) putc('\n',stderr);
  930. X        show_radius();
  931. X        c_token++;
  932. X    }
  933. X    else if (almost_equals(c_token,"r$ange")) {
  934. X        (void) putc('\n',stderr);
  935. X        show_range();
  936. X        c_token++;
  937. X    }
  938. X    else if (almost_equals(c_token,"z$ero") ||
  939. X             almost_equals(c_token,"eps$ilon")) {
  940. X        (void) putc('\n',stderr);
  941. X        show_zero();
  942. X        c_token++;
  943. X    }
  944. X    else if (almost_equals(c_token,"g$eneral")) {    /* no more !!! */
  945. X        c_token++;
  946. X        show_version();
  947. X        show_input();
  948. X        show_custom();
  949. X        show_range();
  950. X        show_label();
  951. X        show_trunc();
  952. X        show_output();
  953. X        show_term();
  954. X        show_size();
  955. X        show_offsets();
  956. X        show_border();
  957. X        show_font();
  958. X        show_title();
  959. X        show_labels(0, stderr, FALSE);
  960. X        show_arrow(0, stderr, FALSE);
  961. X        show_logscale();
  962. X        show_format();
  963. X        show_zero();
  964. X        show_HLset();
  965. X        show_style();
  966. X    }
  967. X    else if (almost_equals(c_token,"bar$charts")) {
  968. X        c_token++;
  969. X        show_version();
  970. X        show_style();
  971. X        fprintf(stderr,"\n\tsettings for barcharts (any bar style):\n\n");
  972. X        show_base();
  973. X        show_width();
  974. X        show_autoscale();
  975. X        show_gravity();
  976. X        show_clock(FALSE);
  977. X    }
  978. X    else if (almost_equals(c_token,"pie$charts")) {
  979. X        c_token++;
  980. X        show_version();
  981. X        show_style();
  982. X        fprintf(stderr,"\n\tsettings for piecharts:\n\n");
  983. X        show_clock(TRUE);
  984. X        show_explode();
  985. X        show_radius();
  986. X        show_tresh();
  987. X        show_samples();
  988. X    }        
  989. X    else if (almost_equals(c_token,"a$ll")) {
  990. X        c_token++;
  991. X        show_version();
  992. X        show_input();
  993. X        show_custom();
  994. X        show_range();
  995. X        show_label();
  996. X        show_trunc();
  997. X        show_output();
  998. X        show_term();
  999. X        show_size();
  1000. X        show_offsets();
  1001. X        show_border();
  1002. X        show_font();
  1003. X        show_title();
  1004. X        show_labels(0, stderr, FALSE);
  1005. X        show_arrow(0, stderr, FALSE);
  1006. X        show_logscale();
  1007. X        show_format();
  1008. X        show_zero();
  1009. X        show_HLset();
  1010. X        show_style();
  1011. X        show_base();
  1012. X        show_width();
  1013. X        show_autoscale();
  1014. X        show_gravity();
  1015. X        show_clock(FALSE);    /* bars */
  1016. X        show_clock(TRUE);    /* pies */
  1017. X        show_explode();
  1018. X        show_radius();
  1019. X        show_tresh();
  1020. X        show_samples();
  1021. X    }
  1022. X    else
  1023. X        int_error(
  1024. X    "valid show options:  'all', 'scale', 'base', 'font'\n\
  1025. X'customized', 'explode', 'gravitation', 'highlight',\n\
  1026. X'input', 'logscale', 'offsets', 'output', 'label',\n\
  1027. X'samples', 'style', 'terminal', 'version', 'range',\n\
  1028. X'radius', 'clockwise', 'width', 'zero/epsilon', 'frame',\n\
  1029. X'size', 'general', 'barcharts', 'piecharts', 'format',\n\
  1030. X'threshold', 'truncate', 'line', 'arrow', 'autolabeling'",
  1031. Xc_token);
  1032. X    screen_ok = FALSE;
  1033. X    (void) putc('\n',stderr);
  1034. X}
  1035. X
  1036. X
  1037. Xload_offsets (a, b, c, d)
  1038. Xdouble *a, *b, *c, *d;
  1039. X{
  1040. X    *a = real (c_token);  /* loff value */
  1041. X    if (*a >= 100.0 && d)
  1042. X        int_error("value <0,100) expected",c_token);
  1043. X    c_token++;
  1044. X    if (equals(c_token,","))
  1045. X        c_token++;
  1046. X    if (END_OF_COMMAND) 
  1047. X        return;
  1048. X
  1049. X    *b = real (c_token);  /* roff value */
  1050. X    if (*b >= 100.0 && d)
  1051. X        int_error("value <0,100) expected",c_token);        
  1052. X    c_token++;
  1053. X    if (equals(c_token,","))
  1054. X        c_token++;
  1055. X    if (END_OF_COMMAND) 
  1056. X        return;
  1057. X
  1058. X    *c = real (c_token);  /* toff value */
  1059. X    if (*c >= 100.0 && d)
  1060. X        int_error("value <0,100) expected",c_token);
  1061. X    c_token++;
  1062. X
  1063. X    if (!d) return;
  1064. X    if (equals(c_token,","))
  1065. X        c_token++;
  1066. X    if (END_OF_COMMAND) 
  1067. X        return;
  1068. X
  1069. X    *d = real (c_token);  /* boff value */
  1070. X    if (*d >= 100.0)
  1071. X        int_error("value <0,100) expected",c_token);
  1072. X    c_token++;
  1073. X}
  1074. X
  1075. X
  1076. Xload_range(a,b)
  1077. Xint *a, *b;
  1078. X{
  1079. X    if (equals(c_token,"]"))
  1080. X        return;  /* no change */
  1081. X    if (END_OF_COMMAND) {
  1082. X        int_error("starting range value or ':' expected",c_token);
  1083. X    } else if (!equals(c_token,"to") && !equals(c_token,":"))  {
  1084. X        *a = (int)real(c_token);
  1085. X        c_token++;
  1086. X    }
  1087. X    else *a = 0;    /* from the very begining */
  1088. X    if (!equals(c_token,"to") && !equals(c_token,":"))
  1089. X        int_error("':' expected",c_token);
  1090. X    c_token++;
  1091. X    if (!equals(c_token,"]")) {
  1092. X        *b = (int)real(c_token);
  1093. X        c_token++;
  1094. X    }
  1095. X    else *b = -1;    /* to infinity */
  1096. X}
  1097. X
  1098. X
  1099. Xplotrequest(xplot)
  1100. XBOOLEAN xplot;
  1101. X{
  1102. X    
  1103. X    if (!term)                    /* unknown */
  1104. X        int_error("use 'set term' to set terminal type first",c_token);
  1105. X
  1106. X    if (log_y && base<1.0 && data_style != PIECHART)
  1107. X        int_error("base for bars out of range for logscale",NO_CARET);
  1108. X
  1109. X    if (equals(c_token,"[")) {
  1110. X        c_token++;
  1111. X        load_range(&xmin,&xmax);
  1112. X        if (!equals(c_token,"]"))
  1113. X            int_error("']' expected",c_token);
  1114. X        c_token++;
  1115. X        if (xmax != -1 && xmax < xmin)
  1116. X            int_error("given range is empty",NO_CARET);
  1117. X    }
  1118. X
  1119. X    eval_plots(xplot);
  1120. X}
  1121. X
  1122. Xint missing(s)
  1123. Xchar *s;
  1124. X/* check if s represents a missing value (spaces and dot) */
  1125. X{
  1126. X    char *p = s + strlen(s) - 1;
  1127. X    if (!s || !*s)
  1128. X        return(1);
  1129. X    while (isspace(*s)) s++;
  1130. X    if (s == p && *s == '.')
  1131. X        return(1);
  1132. X    else
  1133. X        return(0);
  1134. X}
  1135. X
  1136. Xget_data(this_plot,this_style)
  1137. Xstruct dfile *this_plot;
  1138. Xenum INP_STYLE this_style;
  1139. X{
  1140. X    static char data_file[MAX_LINE_LEN+1], line[MAX_LINE_LEN+1];
  1141. X    register int i, l_num, ob_num, scanval;
  1142. X    register FILE *fp;
  1143. X    double x;
  1144. X    struct chunk *chn;
  1145. X    char *labpt;
  1146. X    int chsiz = CH_INIT_SIZE;
  1147. X    int lablen, aux;
  1148. X
  1149. X    quote_str(data_file, c_token);
  1150. X    m_quote_capture(&(this_plot->fname), c_token, c_token);
  1151. X
  1152. X    chn = (struct chunk *) alloc((unsigned)sizeof(struct chunk), data_file);
  1153. X    chn->next = NULL;    /* in case of further errors */
  1154. X    chn->dval = NULL;
  1155. X    chn->vlbl = (char **) NULL;
  1156. X    this_plot->data = chn;
  1157. X    this_plot->chunks = 1;
  1158. X    if (xmin != -1 && xmax != -1)         /* known number of data */
  1159. X        chsiz = xmax - xmin + 1;
  1160. X    chn->dval = (vreal *) alloc((unsigned)chsiz*sizeof(vreal), data_file);
  1161. X    chn->used = 0;
  1162. X    if (this_style != CUSTOMD || label_plac.from != -1) {    /* labels expected */
  1163. X        chn->vlbl = (char **) alloc((unsigned)chsiz*sizeof(char *), data_file);
  1164. X        for (i=0; i<chsiz; i++)
  1165. X            chn->vlbl[i] = (char *) NULL;
  1166. X    }
  1167. X    this_plot->d_min =  VERYLARGE;
  1168. X    this_plot->d_max = -VERYLARGE;
  1169. X    this_plot->points = 0;
  1170. X    this_plot->makeHL = HL_NON;
  1171. X    this_plot->labels = TRUE;        /* label autogenerating may be possible */
  1172. X
  1173. X    if (!(fp = fopen(data_file, "r")))
  1174. X        os_error("can't open data file", c_token);
  1175. X        
  1176. X    l_num = 0;
  1177. X    ob_num = -1;        /* will be incremented before any operation */
  1178. X    i = -1;
  1179. X
  1180. X    while (fgets(line, MAX_LINE_LEN, fp)) {                            /* REWRITE ALL !!! */
  1181. X        l_num++;
  1182. X        if (is_comment(line[0]) && this_style != CUSTOMD)    /* label can be on any position, incl. 1st column */
  1183. X            continue;        /* ignore comments */
  1184. X
  1185. X        i++;
  1186. X        if (i<xmin) continue;    /* still out of range */
  1187. X        if (xmax != -1 && i>xmax) break;    /* don't even read the rest of file */
  1188. X
  1189. X        line[strlen(line)-1] = '\0';    /* get rid of '\n' */
  1190. X        ob_num++;
  1191. X        if (ob_num==chsiz) {    /* open new chunk */
  1192. X            chn->next = (struct chunk *) alloc((unsigned)sizeof(struct chunk), data_file);
  1193. X            chn = chn->next;
  1194. X            chn->next = NULL;    /* in case of further errors */
  1195. X            chn->dval = NULL;
  1196. X            chn->vlbl = (char **) NULL;
  1197. X            this_plot->chunks++;
  1198. X            this_plot->points += chsiz;        /* chunkful of points */
  1199. X            chsiz *= 2;            /* probably the optimal allocation step */
  1200. X            chn->dval = (vreal *) alloc((unsigned)chsiz*sizeof(vreal), (char *)NULL);
  1201. X            if (!chn->dval)
  1202. X                (void) fclose(fp),
  1203. X                int_error("out of memory",c_token);
  1204. X            chn->used = 0;        /* this one */
  1205. X            if (this_style != CUSTOMD || label_plac.from != -1) {    /* labels expected */
  1206. X                chn->vlbl = (char **) alloc((unsigned)chsiz*sizeof(char *), (char *)NULL);
  1207. X                if (!chn->vlbl)
  1208. X                    (void) fclose(fp),
  1209. X                    int_error("out of memory",c_token++);
  1210. X                else {
  1211. X                    int ii;
  1212. X                    for (ii=0; ii<chsiz; ii++)
  1213. X                        chn->vlbl[ii] = (char *) NULL;
  1214. X                }
  1215. X            }
  1216. X            ob_num = 0;
  1217. X        }
  1218. X
  1219. X        if (!*line && this_style != CUSTOMD) {     /* empty data == missing value. not in SAS */
  1220. X            chn->dval[ob_num] = VERYLARGE;    
  1221. X            if (chn->vlbl)
  1222. X                chn->vlbl[ob_num] = (char *) NULL;
  1223. X            chn->used++;
  1224. X            continue;
  1225. X        }
  1226. X
  1227. X        /* so here we go. now consider input format */
  1228. X        switch (this_style) {
  1229. X            case PRIVATE:
  1230. X                scanval = sscanf(line,"%lf",&x);
  1231. X                if (scanval == 1) {
  1232. X                    for (labpt = line; *labpt && isspace(*labpt); labpt++) ;
  1233. X                    while (*labpt && !isspace(*labpt)) labpt++;
  1234. X                    lablen = strlen(labpt);        /* initialy */
  1235. X                }
  1236. X                break;
  1237. X            case GNUPLOT:
  1238. X                scanval = sscanf(line,"%*lf %lf",&x);
  1239. X                if (scanval == 1) {
  1240. X                    for (aux=0; isspace(line[aux]); aux++);
  1241. X                    labpt = line + aux;
  1242. X                    for (lablen=0; !isspace(line[aux++]); lablen++) ;
  1243. X                }
  1244. X                else labpt=NULL, scanval = sscanf(line,"%lf",&x);
  1245. X                break;
  1246. X            case CUSTOMD:
  1247. X                if (strlen(line) < data_place.from) {
  1248. X                    scanval = 0;        /* generate error */
  1249. X                    break;
  1250. X                }
  1251. X                labpt = line + data_place.from;
  1252. X                if (data_place.upto == -1 || data_place.upto >= strlen(line))
  1253. X                    if (missing(labpt))
  1254. X                        x = VERYLARGE;
  1255. X                    else
  1256. X                        scanval = sscanf(labpt,"%lf",&x);
  1257. X                else {
  1258. X                    aux = line[data_place.upto];
  1259. X                    line[data_place.upto] = '\0';
  1260. X                    if (missing(labpt))
  1261. X                        x = VERYLARGE;
  1262. X                    else
  1263. X                        scanval = sscanf(labpt,"%lf",&x);
  1264. X                    line[data_place.upto] = aux;
  1265. X                }
  1266. X                if (x == VERYLARGE) {         /* missing value detected, or unplottable anyway */
  1267. X                    chn->dval[ob_num] = VERYLARGE;
  1268. X                    if (chn->vlbl)
  1269. X                        chn->vlbl[ob_num] = (char *) NULL;
  1270. X                    chn->used++;
  1271. X                    continue;
  1272. X                }
  1273. X                if (label_plac.from >= strlen(line) || label_plac.from == -1) 
  1274. X                    labpt = NULL;
  1275. X                else {
  1276. X                    labpt = line + label_plac.from;
  1277. X                    if (label_plac.upto == -1 || label_plac.upto >= strlen(line))
  1278. X                        lablen = strlen(labpt);
  1279. X                    else
  1280. X                        lablen = label_plac.upto - label_plac.from - 1;
  1281. X                }
  1282. X                break;
  1283. X            }
  1284. X
  1285. X        if (scanval != 1) {        /* can be also EOF for empty line */
  1286. X            (void) sprintf(line, "bad data on line %d", l_num);
  1287. X            (void) fclose(fp);
  1288. X            int_error(line,c_token);
  1289. X        }
  1290. X
  1291. X        if (x<0.0 && data_style == PIECHART ||
  1292. X            x<1.0 && data_style != PIECHART && log_y) {
  1293. X            (void) fclose(fp);
  1294. X            (void) sprintf(line,"unplotable data on line %d",l_num);
  1295. X            int_error(line,c_token);
  1296. X        }
  1297. X
  1298. X        if (log_y) x = log10(x);
  1299. X        
  1300. X        chn->dval[ob_num] = (vreal) x;
  1301. X        if (x<this_plot->d_min) this_plot->d_min = (vreal) x;
  1302. X        if (x>this_plot->d_max) this_plot->d_max = (vreal) x;  /* without 'else', I know */
  1303. X        
  1304. X        if (labpt && *labpt && lablen && strunc!=0) {    /* copy existing label -- ignore if empty */
  1305. X            char *q;
  1306. X            /* remove meaningless spaces */
  1307. X            while (isspace(*labpt)) labpt++, lablen--;
  1308. X            while (isspace(labpt[lablen])) lablen--;
  1309. X            if (strunc>0 && strunc<lablen)
  1310. X                lablen = strunc;
  1311. X            if (!lablen)    /* truncated to zero */
  1312. X                chn->vlbl[ob_num] = (char *) NULL;
  1313. X            else {
  1314. X                if (!(q = alloc((unsigned) lablen+1, (char *)NULL))) {
  1315. X                    (void) fclose(fp);
  1316. X                    int_error("out of memory",c_token);
  1317. X                }
  1318. X                (void) strncpy(q,labpt,lablen);
  1319. X                q[lablen] = '\0';
  1320. X                chn->vlbl[ob_num] = q;
  1321. X                this_plot->labels = FALSE;    /* cannot autogenerate labels if some exist */
  1322. X            }
  1323. X        }
  1324. X        else
  1325. X            chn->vlbl[ob_num] = (char *) NULL;
  1326. X
  1327. X        chn->used++;
  1328. X    } /* while */
  1329. X
  1330. X    (void) fclose(fp);
  1331. X    if (i<xmin)
  1332. X        int_error("too few data",c_token);
  1333. X
  1334. X    this_plot->points += chn->used;
  1335. X
  1336. X}
  1337. X
  1338. Xeval_plots(xplot)
  1339. XBOOLEAN xplot;
  1340. X{
  1341. X    struct dfile *dp = &data_head, *tail;
  1342. X    enum INP_STYLE in_st;
  1343. X
  1344. X    data_head.d_min = VERYLARGE; data_head.d_max = -VERYLARGE;
  1345. X    data_head.points = data_head.chunks = 0;
  1346. X    if (data_head.data) free((char *)data_head.data);
  1347. X    data_head.data = NULL;
  1348. X    destroy(data_head.dnxt);
  1349. X    data_head.dnxt = (struct dfile *) NULL;
  1350. X    data_head.makeHL = HLitem;
  1351. X    data_head.labels = auto_label;
  1352. X
  1353. X    while (TRUE) {
  1354. X        if (END_OF_COMMAND)
  1355. X            int_error("data file to plot expected",c_token);
  1356. X        if (equals(c_token,"(")) {
  1357. X            c_token++;
  1358. X            in_st = get_input();
  1359. X            if (END_OF_COMMAND || !equals(c_token,")"))
  1360. X                int_error("expected ')'",c_token);
  1361. X            c_token++;
  1362. X        }
  1363. X        else
  1364. X            in_st = inp_style;
  1365. X        if (in_st == CUSTOMD && data_place.from == -1)
  1366. X            int_error("Customized input format not defined. Use 'set customized'",NO_CARET);
  1367. X        
  1368. X        if (END_OF_COMMAND || !isstring(c_token)) 
  1369. X            int_error("data file to plot expected",c_token);
  1370. X        tail = (struct dfile *) alloc((unsigned int) sizeof(struct dfile), "data");
  1371. X        tail->fname = NULL;
  1372. X        tail->data  = NULL;
  1373. X        tail->dnxt  = NULL;
  1374. X        dp->dnxt    = tail;    /* to free all memory on error */
  1375. X
  1376. X        get_data(tail,in_st);
  1377. X
  1378. X        c_token++;
  1379. X        dp             = tail;
  1380. X        data_head.chunks++;  /* here we count overall number of files */
  1381. X        if (data_style != ABARS && data_style != PIECHART || xplot)    /* if (ABARS || PIECHART => xplot) */
  1382. X            data_head.labels = data_head.labels && dp->labels;    /* is making labels sensible or not ? */
  1383. X        /* else this serves different purpose */
  1384. X        if (data_head.points < dp->points)
  1385. X            data_head.points = dp->points;  /* ... and maximal number of points */
  1386. X        if (data_head.d_min > dp->d_min)
  1387. X            data_head.d_min = dp->d_min;    /* minimum ... */
  1388. X        if (data_head.d_max < dp->d_max)
  1389. X            data_head.d_max = dp->d_max;    /* and maximum */
  1390. X
  1391. X        if (almost_equals(c_token,"a$s")) {
  1392. X            c_token++;
  1393. X            if (END_OF_COMMAND || !isstring(c_token))
  1394. X                int_error("name in quotes expected", c_token);
  1395. X            else {
  1396. X                m_quote_capture(&(dp->fname), c_token, c_token);
  1397. X                c_token++;
  1398. X            }
  1399. X        }
  1400. X        
  1401. X        if (almost_equals(c_token,"h$ighlighting")) {
  1402. X            c_token++;
  1403. X            dp->makeHL = get_HL();
  1404. X        }
  1405. X
  1406. X        if (END_OF_COMMAND)
  1407. X            break;
  1408. X        else if (equals(c_token,","))
  1409. X            c_token++;
  1410. X        else
  1411. X            int_error("expected ','",c_token);
  1412. X    }
  1413. X
  1414. X    if (data_head.d_min == VERYLARGE || data_head.d_max == -VERYLARGE)
  1415. X        int_error("all points undefined, nothing to draw",NO_CARET);
  1416. X
  1417. X    if (data_head.chunks > 1) {        /* reserve space for xpointers structure */
  1418. X        /* do it here, to avoid memory management in graphics.c */
  1419. X        data_head.data = (struct chunk *) alloc((unsigned)data_head.chunks*sizeof(struct xptr), "data");
  1420. X    }
  1421. X
  1422. X    capture(replot_line,plot_token,c_token);
  1423. X    do_plot(xplot,data_style,xmin<=0?0:xmin);
  1424. X}
  1425. X
  1426. Xdone(status)
  1427. Xint status;
  1428. X{
  1429. X    if (term && term_init)
  1430. X        (*term_tbl[term].reset)();
  1431. X#ifdef VMS
  1432. X    vms_reset();
  1433. X#endif
  1434. X    exit(status);
  1435. X}
  1436. X
  1437. X#ifdef MSDOS
  1438. X#ifndef __TURBOC__  /* Turbo C already has sleep() */
  1439. X#ifndef __ZTC__     /* ZTC already has usleep() */
  1440. X/* kludge to provide sleep() for msc 5.1 */
  1441. Xvoid sleep(delay)
  1442. Xunsigned int delay;
  1443. X{
  1444. Xunsigned long time_is_up;
  1445. X    time_is_up = time(NULL) + (unsigned long) delay;
  1446. X    while (time(NULL)<time_is_up)
  1447. X        /* wait */ ;
  1448. X}
  1449. X#endif /* not ZTC */
  1450. X#endif /* not TURBOC */
  1451. X#endif /* MSDOS */
  1452. X
  1453. X
  1454. X/* Support for input, shell, and help for various systems */
  1455. X
  1456. X#ifdef vms
  1457. X
  1458. X#include <descrip.h>
  1459. X#include <rmsdef.h>
  1460. X#include <errno.h>
  1461. X
  1462. Xextern lib$get_input(), lib$put_output();
  1463. X
  1464. Xint vms_len;
  1465. X
  1466. Xunsigned int status[2] = {1, 0};
  1467. X
  1468. Xstatic char help[MAX_LINE_LEN+1] = "fchart";
  1469. X
  1470. X$DESCRIPTOR(prompt_desc,PROMPT);
  1471. X$DESCRIPTOR(line_desc,input_line);
  1472. X
  1473. X$DESCRIPTOR(help_desc,help);
  1474. X$DESCRIPTOR(helpfile_desc,"FCHART$HELP");
  1475. X
  1476. Xread_line(prompt)
  1477. Xchar *prompt;
  1478. X{
  1479. X    int more, start=0;
  1480. X    char exp_prompt = EXP_PROMPT;
  1481. X    prompt_desc.dsc$w_length = strlen (prompt);
  1482. X    prompt_desc.dsc$a_pointer = prompt;
  1483. X    do {
  1484. X        line_desc.dsc$w_length = MAX_LINE_LEN - start;
  1485. X        line_desc.dsc$a_pointer = &input_line[start];
  1486. X        switch(status[1] = lib$get_input(&line_desc, &prompt_desc, &vms_len)){
  1487. X            case RMS$_EOF:
  1488. X                done(IO_SUCCESS);    /* ^Z isn't really an error */
  1489. X                break;
  1490. X            case RMS$_TNS:            /* didn't press return in time */
  1491. X                vms_len--;        /* skip the last character */
  1492. X                break;            /* and parse anyway */
  1493. X            case RMS$_BES:            /* Bad Escape Sequence */
  1494. X            case RMS$_PES:            /* Partial Escape Sequence */
  1495. X                sys$putmsg(status);
  1496. X                vms_len = 0;        /* ignore the line */
  1497. X                break;
  1498. X            case SS$_NORMAL:
  1499. X                break;            /* everything's fine */
  1500. X            default:
  1501. X                done(status[1]);    /* give the error message */
  1502. X        }
  1503. X        start += vms_len;
  1504. X        input_line[start] = '\0';
  1505. X        if (input_line[start-1] == '\\') {
  1506. X          /* Allow for a continuation line. */
  1507. X          prompt_desc.dsc$w_length = strlen (exp_prompt);
  1508. X          prompt_desc.dsc$a_pointer = exp_prompt;
  1509. X          more = 1;
  1510. X          --start;
  1511. X        }
  1512. X        else {
  1513. X          line_desc.dsc$w_length = strlen(input_line);
  1514. X          line_desc.dsc$a_pointer = input_line;
  1515. X          more = 0;
  1516. X        }
  1517. X    } while (more);        
  1518. X}
  1519. X
  1520. X
  1521. Xdo_help()
  1522. X{
  1523. X    help_desc.dsc$w_length = strlen(help);
  1524. X    if ((vaxc$errno = lbr$output_help(lib$put_output,0,&help_desc,
  1525. X        &helpfile_desc,0,lib$get_input)) != SS$_NORMAL)
  1526. X            os_error("can't open FCHART$HELP");
  1527. X}
  1528. X
  1529. X
  1530. Xdo_shell()
  1531. X{
  1532. X    if ((vaxc$errno = lib$spawn()) != SS$_NORMAL) {
  1533. X        os_error("spawn error",NO_CARET);
  1534. X    }
  1535. X}
  1536. X
  1537. X
  1538. Xdo_system()
  1539. X{
  1540. X    input_line[0] = ' ';    /* an embarrassment, but... */
  1541. X
  1542. X    if ((vaxc$errno = lib$spawn(&line_desc)) != SS$_NORMAL)
  1543. X        os_error("spawn error",NO_CARET);
  1544. X
  1545. X    (void) putc('\n',stderr);
  1546. X}
  1547. X
  1548. X#else /* vms */
  1549. X
  1550. X/* do_help: (not VMS, although it would work)
  1551. X * Give help to the user.
  1552. X * It parses the command line into helpbuf and supplies help for that
  1553. X * string. Then, if there are subtopics available for that key,
  1554. X * it prompts the user with this string. If more input is
  1555. X * given, do_help is called recursively, with the argument the index of
  1556. X * null character in the string. Thus a more specific help can be
  1557. X * supplied. This can be done repeatedly.
  1558. X * If null input is given, the function returns, effecting a
  1559. X * backward climb up the tree.
  1560. X * David Kotz (dfk@cs.duke.edu) 10/89
  1561. X */
  1562. Xdo_help()
  1563. X{
  1564. X    static char helpbuf[MAX_LINE_LEN] = "";
  1565. X    static char prompt[MAX_LINE_LEN] = "";
  1566. X    int base;               /* index of first char AFTER help string */
  1567. X    int len;                /* length of current help string */
  1568. X    BOOLEAN more_help;
  1569. X    BOOLEAN only;           /* TRUE if only printing subtopics */
  1570. X    int subtopics;          /* 0 if no subtopics for this topic */
  1571. X    int start;              /* starting token of help string */
  1572. X    char *help_ptr;         /* name of help file */
  1573. X    
  1574. X    if ( (help_ptr = getenv("FCHARTHELP")) == (char *)NULL )
  1575. X        /* if can't find environment variable then just use HELPFILE */
  1576. X        help_ptr = HELPFILE;
  1577. X    
  1578. X    len = base = strlen(helpbuf);
  1579. X    
  1580. X    /* find the end of the help command */
  1581. X    for (start = c_token; !(END_OF_COMMAND); c_token++) ;
  1582. X    /* copy new help input into helpbuf */
  1583. X    if (len > 0)
  1584. X        helpbuf[len++] = ' ';  /* add a space */
  1585. X    capture(helpbuf+len, start, c_token-1);
  1586. X    squash_spaces(helpbuf+base); /* only bother with new stuff */
  1587. X    lower_case(helpbuf+base); /* only bother with new stuff */
  1588. X    len = strlen(helpbuf);
  1589. X    
  1590. X    /* now, a lone ? will print subtopics only */
  1591. X    if (strcmp(helpbuf + (base ? base+1 : 0), "?") == 0) {
  1592. X        /* subtopics only */
  1593. X        subtopics = 1;
  1594. X        only = TRUE;
  1595. X        helpbuf[base] = '\0';    /* cut off question mark */
  1596. X    } else {
  1597. X        /* normal help request */
  1598. X        subtopics = 0;
  1599. X        only = FALSE;
  1600. X    }
  1601. X    
  1602. X    switch ( help(helpbuf, help_ptr, &subtopics)) {
  1603. X        case H_FOUND: {
  1604. X            /* already printed the help info */
  1605. X            /* subtopics now is true if there were any subtopics */
  1606. X            screen_ok = FALSE;
  1607. X            
  1608. X            do {
  1609. X                if (subtopics && !only) {
  1610. X                    /* prompt for subtopic with current help string */
  1611. X                    if (len > 0)
  1612. X                        (void) sprintf(prompt, "Subtopic of %s: ", helpbuf);
  1613. X                    else
  1614. X                        (void) strcpy(prompt, "Help topic: ");
  1615. X                    read_line(prompt);
  1616. X                    num_tokens = scanner(input_line);
  1617. X                    c_token = 0;
  1618. X                    more_help = !(END_OF_COMMAND);
  1619. X                    if (more_help)
  1620. X                        /* base for next level is all of current helpbuf */
  1621. X                        do_help();
  1622. X                } else
  1623. X                    more_help = FALSE;
  1624. X            } while(more_help);
  1625. X            
  1626. X            break;
  1627. X        }
  1628. X        case H_NOTFOUND: {
  1629. X            printf("Sorry, no help for '%s'\n", helpbuf);
  1630. X            break;
  1631. X        }
  1632. X        case H_ERROR: {
  1633. X            perror(help_ptr);
  1634. X            break;
  1635. X        }
  1636. X        default: {       /* defensive programming */
  1637. X            int_error("Impossible case in switch\n", NO_CARET);
  1638. X            /* NOTREACHED */
  1639. X        }
  1640. X    }
  1641. X    
  1642. X    helpbuf[base] = '\0';   /* cut it off where we started */
  1643. X}
  1644. X
  1645. Xdo_system()
  1646. X{
  1647. X    if (system(input_line + 1))
  1648. X        os_error("system() failed",NO_CARET);
  1649. X}
  1650. X
  1651. X#ifdef MSDOS
  1652. X
  1653. Xread_line(prompt)
  1654. Xchar *prompt;
  1655. X{
  1656. X    int last, start = 0;
  1657. X    BOOLEAN more;
  1658. X
  1659. X#ifndef __ZTC__
  1660. X    if (interactive) { /* if interactive use console IO so CED will work */
  1661. X        cputs(prompt);
  1662. X        do {
  1663. X            input_line[start] = MAX_LINE_LEN - start - 1;
  1664. X            cgets(&(input_line[start]));
  1665. X            (void) putc('\n',stderr);
  1666. X            if (input_line[start+2] == 26) {
  1667. X                /* end-of-file */
  1668. X                (void) putc('\n',stderr);
  1669. X                input_line[start] = '\0';
  1670. X                if (start > 0)    /* don't quit yet - process what we have */
  1671. X                    more = FALSE;
  1672. X                else {
  1673. X                    (void) putc('\n',stderr);
  1674. X                    done(IO_SUCCESS);
  1675. X                    /* NOTREACHED */
  1676. X                }
  1677. X            } else {
  1678. X                /* normal line input */
  1679. X                register i = start;
  1680. X                while ( (input_line[i] = input_line[i+2]) != (char)NULL )
  1681. X                    i++;        /* yuck!  move everything down two characters */
  1682. X                
  1683. X                last = strlen(input_line) - 1;
  1684. X                if (last + 1 >= MAX_LINE_LEN)
  1685. X                    int_error("Input line too long",NO_CARET);
  1686. X                
  1687. X                if (input_line[last] == '\\') { /* line continuation */
  1688. X                    start = last;
  1689. X                    more = TRUE;
  1690. X                } else
  1691. X                    more = FALSE;
  1692. X            }
  1693. X            if (more && isatty(fileno(stdin)))
  1694. X                cputs(EXP_PROMPT);
  1695. X        } while(more);
  1696. X    }
  1697. X    else { /* not interactive */
  1698. X#endif /* not ZTC */
  1699. X        if (interactive) 
  1700. X            fputs(prompt,stderr);
  1701. X        do {
  1702. X            /* grab some input */
  1703. X            if ( fgets(&(input_line[start]), MAX_LINE_LEN - start, stdin)
  1704. X                == (char *)NULL ) {
  1705. X                /* end-of-file */
  1706. X                if (interactive)
  1707. X                    (void) putc('\n',stderr);
  1708. X                input_line[start] = '\0';
  1709. X                if (start > 0)    /* don't quit yet - process what we have */
  1710. X                    more = FALSE;
  1711. X                else
  1712. X                    done(IO_SUCCESS); /* no return */
  1713. X            } else {
  1714. X                /* normal line input */
  1715. X                last = strlen(input_line) - 1;
  1716. X                if (input_line[last] == '\n') { /* remove any newline */
  1717. X                    input_line[last] = '\0';
  1718. X                    /* Watch out that we don't backup beyond 0 (1-1-1) */
  1719. X                    if (last > 0) --last;
  1720. X                } else if (last+1 >= MAX_LINE_LEN)
  1721. X                    int_error("Input line too long",NO_CARET);
  1722. X                
  1723. X                if (input_line[last] == '\\') { /* line continuation */
  1724. X                    start = last;
  1725. X                    more = TRUE;
  1726. X                } else
  1727. X                    more = FALSE;
  1728. X            }
  1729. X            if (more && interactive)
  1730. X                fputs(EXP_PROMPT, stderr);
  1731. X        } while(more);
  1732. X#ifndef __ZTC
  1733. X    }
  1734. X#endif
  1735. X    
  1736. X#ifdef FILIP
  1737. X    input_line[0] = MAX_LINE_LEN - 1;
  1738. X    cputs(PROMPT);
  1739. X    cgets(input_line);            /* console input so CED will work */
  1740. X    (void) putc('\n',stderr);
  1741. X    if (input_line[2] == 26) {
  1742. X        (void) putc('\n',stderr);        /* end-of-file */
  1743. X        done(IO_SUCCESS);
  1744. X    }
  1745. X    
  1746. X    i = 0;
  1747. X    while (input_line[i] = input_line[i+2])
  1748. X        i++;        /* yuck!  move everything down two characters */
  1749. X#endif
  1750. X}
  1751. X
  1752. X
  1753. Xdo_shell()
  1754. X{
  1755. X    register char *comspec;
  1756. X    if (!(comspec = getenv("COMSPEC")))
  1757. X        comspec = "\command.com";
  1758. X    if (spawnl(P_WAIT,comspec,NULL) == -1)
  1759. X        os_error("unable to spawn shell",NO_CARET);
  1760. X}
  1761. X
  1762. X#else /* MSDOS */
  1763. X/* plain old Unix */
  1764. X
  1765. Xread_line(prompt)
  1766. Xchar *prompt;
  1767. X{
  1768. X    int start=0, last=0;
  1769. X    BOOLEAN more;
  1770. X    
  1771. X    if (interactive) fputs(prompt,stderr);
  1772. X    do {
  1773. X        if (!fgets(&input_line[start], MAX_LINE_LEN-start, stdin)) {
  1774. X            if (interactive)
  1775. X                (void) putc('\n',stderr);        /* end-of-file */
  1776. X            input_line[start] = '\0';
  1777. X            if (start > 0)    /* don't quit yet - process what we have */
  1778. X                more = FALSE;
  1779. X            else
  1780. X                done(IO_SUCCESS); /* no return */
  1781. X        }
  1782. X        else {    /* normal line input */
  1783. X            last = strlen(input_line)-1;
  1784. X            if (input_line[last] == '\n') { /* remove any newline */
  1785. X                input_line[last] = '\0';
  1786. X                /* Watch out that we don't backup beyond 0 (1-1-1) */
  1787. X                if (last > 0) --last;
  1788. X            }
  1789. X            else if (last+1 >= MAX_LINE_LEN)
  1790. X                int_error("Input line too long",NO_CARET);
  1791. X            
  1792. X            if (input_line[last] == '\\') { /* line continuation */
  1793. X                start = last;
  1794. X                more = TRUE;
  1795. X            } else
  1796. X                more = FALSE;
  1797. X        }
  1798. X        if (more && interactive) fputs(EXP_PROMPT,stderr);
  1799. X    } while (more);
  1800. X}
  1801. X
  1802. X#ifdef VFORK
  1803. X
  1804. Xdo_shell()
  1805. X{
  1806. Xregister char *shell;
  1807. Xregister int p;
  1808. Xstatic int execstat;
  1809. X    if (!(shell = getenv("SHELL")))
  1810. X        shell = SHELL;
  1811. X    if ((p = vfork()) == 0) {
  1812. X        execstat = execl(shell,shell,NULL);
  1813. X        _exit(1);
  1814. X    } else if (p == -1)
  1815. X        os_error("vfork failed",c_token);
  1816. X    else
  1817. X        while (wait(NULL) != p)
  1818. X            ;
  1819. X    if (execstat == -1)
  1820. X        os_error("shell exec failed",c_token);
  1821. X    (void) putc('\n',stderr);
  1822. X}
  1823. X#else /* VFORK */
  1824. X
  1825. X#define EXEC "exec "
  1826. Xdo_shell()
  1827. X{
  1828. Xstatic char exec[100] = EXEC;
  1829. Xregister char *shell;
  1830. X    if (!(shell = getenv("SHELL")))
  1831. X        shell = SHELL;
  1832. X
  1833. X    if (system(strncpy(&exec[sizeof(EXEC)-1],shell,
  1834. X        sizeof(exec)-sizeof(EXEC)-1)))
  1835. X        os_error("system() failed",NO_CARET);
  1836. X
  1837. X    (void) putc('\n',stderr);
  1838. X}
  1839. X#endif /* VFORK */
  1840. X#endif /* MSDOS */
  1841. X#endif /* vms */
  1842. SHAR_EOF
  1843. $TOUCH -am 0604152590 fcmd.c &&
  1844. chmod 0666 fcmd.c ||
  1845. echo "restore of fcmd.c failed"
  1846. set `wc -c fcmd.c`;Wc_c=$1
  1847. if test "$Wc_c" != "45623"; then
  1848.     echo original size 45623, current size $Wc_c
  1849. fi
  1850. # ============= fgraf.c ==============
  1851. echo "x - extracting fgraf.c (Text)"
  1852. sed 's/^X//' << 'SHAR_EOF' > fgraf.c &&
  1853. X/*
  1854. X *
  1855. X *  Fchart  --  fgraf.c
  1856. X *
  1857. X *  Copyright (C) 1990 Piotr Filip Sawicki
  1858. X *
  1859. X *  WARNING:
  1860. X *    Included "fstyles.i" is an older version of already rewritten graphics
  1861. X *    module. Please, don't change anything, rather mail me suggestions.
  1862. X *    It emerged like a ball of mud -- don't be shocked with this code.
  1863. X *    Writing program I jjust have been adding here new styles, parameters,
  1864. X *    bells and whistles -- so it looks like it looks.
  1865. X *
  1866. X *  Rest of the code can be freely modified and used, as long as this message
  1867. X *  is retained and modified code is not redistributed.
  1868. X *
  1869. X *  Please e-mail any useful additions to fs@uwasa.fi so they may be
  1870. X *  included in later releases.
  1871. X *
  1872. X *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  1873. X */
  1874. X
  1875. X#include <stdio.h>
  1876. X#include <math.h>
  1877. X#include "plot.h"
  1878. X#include "fchart.h"
  1879. X
  1880. X/***********************************************************************/
  1881. X
  1882. X#define MARGIN 0.95            /* margin within frame */
  1883. X
  1884. X/***********************************************************************/
  1885. X  
  1886. X
  1887. Xchar *strcpy(),*strncpy(),*strcat(),*sprintf();    /* for lint only */
  1888. X
  1889. Xchar *make_labl();
  1890. X
  1891. Xextern BOOLEAN autoscale;
  1892. Xextern FILE *outfile;
  1893. Xextern BOOLEAN log_y;
  1894. Xextern int term;
  1895. Xextern BOOLEAN draw_border;
  1896. X
  1897. Xextern BOOLEAN screen_ok;
  1898. Xextern BOOLEAN term_init;
  1899. X
  1900. Xextern double loff,roff,toff,boff;
  1901. Xextern double zero;
  1902. X
  1903. Xextern enum GRAV_DIR   gravity, explode;
  1904. Xextern int             samples;
  1905. Xextern double          base;
  1906. Xextern BOOLEAN         p_clockwise, b_clockwise;
  1907. Xextern double          radexp, treshold;
  1908. Xextern double          b_wid, b_spc, b_int;
  1909. Xextern char            thrname[];
  1910. X
  1911. Xextern float           xsize, ysize;
  1912. X
  1913. Xextern char tic_form[];
  1914. X
  1915. Xextern enum FONT_STYLE vect_font;
  1916. X    
  1917. Xextern struct termentry term_tbl[];
  1918. Xextern struct dfile data_head;    /* static head of data list */
  1919. X
  1920. Xextern struct label_def *first_label;    /* defined in flblarr.c */
  1921. Xextern struct linearrow_def *first_arrow;    /* defined in flblarr.c */
  1922. X
  1923. X#ifndef toascii
  1924. X#define toascii(A) (((int)(A)) & 0x7F)
  1925. X#endif
  1926. X
  1927. X#define SIGN(A) (A>=0 ? 1 : -1)
  1928. X
  1929. Xextern struct Char trt[];    /* font translation table */
  1930. X
  1931. Xstatic struct termentry *t;                /* faster */
  1932. Xstatic int xbase, ybase, xmaxp, ymaxp;    /* viewport */
  1933. Xstatic struct xptr *across;                /* used for xplot */
  1934. Xstatic int first_element;                /* first element for autolabeling */
  1935. Xstatic BOOLEAN trotate;                    /* whether terminal can rotate text or not */
  1936. Xstatic int tstate;                        /* state of terminal text rotation */
  1937. Xstatic int howmuch;                        /* how much space takes as text the longest used value */
  1938. X
  1939. Xdo_plot(xplot,style,fel)
  1940. XBOOLEAN xplot;
  1941. Xenum DRAW_STYLE style;
  1942. Xint fel;
  1943. X{
  1944. X    /**This bloody part of code initializes graphic *
  1945. X     * environment, draws borders, outputs trailer, *
  1946. X     * etc. Before calling drawing fuctions it cal- *
  1947. X     * culates  viewport  (see toff,boff,roff,loff) *
  1948. X     * and some other variables used in any style.  *
  1949. X     *   Ough,  how I long to Pascal's nested local *
  1950. X     * procedures !!!                               */
  1951. X
  1952. X    BOOLEAN dolabel = (data_head.fname != (char *)NULL);
  1953. X    int effect, x, y, x0, dx, y0, dy;
  1954. X    struct label_def *lb;
  1955. X    struct linearrow_def *ar;
  1956. X    
  1957. X    t = &term_tbl[term];
  1958. X    if (!(*t->scale)(xsize, ysize)) {
  1959. X        x = t->xmax * xsize;
  1960. X        y = t->ymax * ysize;
  1961. X    }
  1962. X    else {
  1963. X        x = t->xmax;
  1964. X        y = t->ymax;
  1965. X    }
  1966. X    
  1967. X    y0 = ybase = (int) ((boff>1.0 ? boff/100.0 : boff)*y) + 1;
  1968. X    dy = ymaxp = (int) ((1.0-(toff>1.0 ? toff/100.0 : toff))*(y-2)) - (dolabel ? 3*t->v_char : 0);
  1969. X    if (ymaxp <= ybase)
  1970. X        int_error("no space to put title, change offsets", NO_CARET);
  1971. X    x0 = xbase = (int) ((loff>1.0 ? loff/100.0 : loff)*x) + 1;
  1972. X    dx = xmaxp = (int) ((1.0-(roff>1.0 ? roff/100.0 : roff))*(x-2));
  1973. X
  1974. X    across = (struct xptr *) data_head.data;
  1975. X    first_element = fel;
  1976. X    
  1977. X    if (!term_init) {
  1978. X        (*t->init)();
  1979. X        term_init = TRUE;
  1980. X    }
  1981. X    screen_ok = FALSE;
  1982. X    (*t->graphics)();
  1983. X    trotate = (*t->text_angle)(0);        /* mostly harmless */
  1984. X    tstate  = 0;
  1985. X
  1986. X    switch (style) {
  1987. X        case ABARS    : effect = dr_abar(xplot);
  1988. X            break;
  1989. X        case SBAR     : effect = dr_sbar(xplot);
  1990. X            break;
  1991. X        case LAYB     : effect = dr_lbar(xplot);
  1992. X            break;
  1993. X        case PIECHART : effect = dr_pies(xplot);
  1994. X            break;
  1995. X        default :
  1996. X            (*t->text)();
  1997. X            (void) fflush(outfile);
  1998. X            int_error("style not yet implemented",NO_CARET);
  1999. X    }
  2000. X
  2001. X    if (!effect) {
  2002. X        (*t->text)();
  2003. X        (void) fflush(outfile);
  2004. X        int_error("too many data to make sensible picture", NO_CARET);
  2005. X    }
  2006. X    
  2007. X    (*t->linetype)(-2); /* border linetype */
  2008. X    if (draw_border) {    /* draw plot border */
  2009. X        (*t->move)(0,0);    
  2010. X        (*t->vector)(x-1,0);    
  2011. X        (*t->vector)(x-1,y-1);    
  2012. X        (*t->vector)(0,y-1);    
  2013. X        (*t->vector)(0,0);
  2014. X    }
  2015. X
  2016. X    (*t->linetype)(0);    /* only one guaranted to be solid */
  2017. X    if (dolabel)        /* put title */
  2018. X        put_txt((x0+dx)/2, (int)(dy+3*t->v_char/2), data_head.fname, CENTRE, 0);
  2019. X
  2020. X    for (lb=first_label; lb; lb=lb->next) {        /* process and put labels */
  2021. X        double c_x = lb->x <= 1.0 ? lb->x : lb->x/RESOLUTION;
  2022. X        double c_y = lb->y <= 1.0 ? lb->y : lb->y/RESOLUTION;
  2023. X        double c_h = lb->h <= 1.0 ? lb->h : lb->h/RESOLUTION;
  2024. X        double c_w = lb->w <= 1.0 ? lb->w : lb->w/RESOLUTION;
  2025. X        int lx, ly, r_x, r_y, r0x, r0y;
  2026. X        if (!*lb->text)
  2027. X            continue;
  2028. X
  2029. X        if (lb->paged) {
  2030. X            r0x =  r0y   = 0;
  2031. X            r_x = x; r_y = y;
  2032. X        }
  2033. X        else {
  2034. X            r0x = x0;    r0y = y0;
  2035. X            r_x = dx-x0; r_y = dy-y0;
  2036. X        }
  2037. X        lx = r0x + c_x*r_x;
  2038. X        ly = r0y + c_y*r_y;
  2039. X
  2040. X        if ((lb->rot == L_NORMAL || lb->rot == L_BOTTOM) &&
  2041. X            !lb->h && !lb->w)                    /* try to put it as a normal text */
  2042. X            put_txt(lx, ly, lb->text, lb->pos, lb->rot==L_NORMAL ? 0 : 1);
  2043. X        else {
  2044. X            double an = (int)lb->rot * Pi/2;
  2045. X            if (!lb->h && !lb->w)                /* use standard size */
  2046. X                (void) draw_text(lx, ly, lb->text, (int)t->v_char, 0, -1, lb->pos, lb->rot==L_RANDOM ? lb->a : an);
  2047. X            else                                /* draw_text will worry */
  2048. X                (void) draw_text(lx, ly, lb->text, (int)(c_h*r_y), (int)(c_w*r_x),
  2049. X                          -1, lb->pos, lb->rot==L_RANDOM ? lb->a : an);
  2050. X        }
  2051. X    }
  2052. X
  2053. X    for (ar=first_arrow; ar; ar=ar->next) {        /* process and put arrows/lines */
  2054. X        double c_sx = ar->sx <= 1.0 ? ar->sx : ar->sx/RESOLUTION;
  2055. X        double c_sy = ar->sy <= 1.0 ? ar->sy : ar->sy/RESOLUTION;
  2056. X        double c_ex = ar->ex <= 1.0 ? ar->ex : ar->ex/RESOLUTION;
  2057. X        double c_ey = ar->ey <= 1.0 ? ar->ey : ar->ey/RESOLUTION;
  2058. X        int sx,sy,ex,ey;
  2059. X        if (ar->startp) {
  2060. X            sx = x*c_sx;
  2061. X            sy = y*c_sy;
  2062. X        }
  2063. X        else {
  2064. X            sx = x0 + (dx-x0)*c_sx;
  2065. X            sy = y0 + (dy-y0)*c_sy;
  2066. X        }
  2067. X        if (ar->endp) {
  2068. X            ex = x*c_ex;
  2069. X            ey = y*c_ey;
  2070. X        }
  2071. X        else {
  2072. X            ex = x0 + (dx-x0)*c_ex;
  2073. X            ey = y0 + (dy-y0)*c_ey;
  2074. X        }
  2075. X
  2076. X        if (ar->arrow)
  2077. X            (*t->arrow)(sx, sy, ex, ey);
  2078. X        else {
  2079. X            (*t->move)(sx, sy);
  2080. X            (*t->vector)(ex, ey);
  2081. X        }
  2082. X    }
  2083. X            
  2084. X    (*t->text)();
  2085. X    (void) fflush(outfile);
  2086. X}
  2087. X
  2088. X#define MCx(PT,R,AN) nint((PT)+(R)*cos(AN))
  2089. X#define MCy(PT,R,AN) nint((PT)+(R)*sin(AN))
  2090. X
  2091. Xput_arc(x,y,r,a0,da)
  2092. Xint x,y,r;
  2093. Xdouble a0,da;
  2094. X/* draw arc from a0, da long */
  2095. X{
  2096. X    double step, drto;
  2097. X    int iter;
  2098. X
  2099. X    (*t->move)(MCx(x,r,a0),MCy(y,r,a0)); 
  2100. X    step = 2*Pi/samples * (da>0.0 ? 1 : -1);    /* angle step */
  2101. X    iter = nint(floor(da/step));                /* number of iterations - makes loop faster */
  2102. X    drto = a0 + step;                            /* next place to draw */
  2103. X    while (iter--) {
  2104. X        (*t->vector)(MCx(x,r,drto),MCy(y,r,drto));
  2105. X        drto += step;
  2106. X    }
  2107. X    (*t->vector)(MCx(x,r,a0+da),MCy(y,r,a0+da));    /* last part - prob. shorter */
  2108. X}
  2109. X              
  2110. Xput_bar(x0,y0,dx,dy,turn)
  2111. Xint x0,y0,dx,dy,turn;
  2112. X/* put single bar (opened rectangle) */
  2113. X{
  2114. X    if (turn) (*t->move)(x0,y0+dy);
  2115. X    else {
  2116. X        (*t->move)(x0,y0);
  2117. X        (*t->vector)(x0,y0+dy);
  2118. X    }
  2119. X    (*t->vector)(x0+dx,y0+dy);
  2120. X    (*t->vector)(x0+dx,y0);
  2121. X    if (turn) 
  2122. X        (*t->vector)(x0,y0);
  2123. X}
  2124. X
  2125. XBOOLEAN find_ran(min, max, sum, lab)
  2126. Xdouble *min, *max, *sum;
  2127. Xchar **lab;        /* NULL if all labels undefined; "" if labels different; else pointer to the good label */
  2128. X/**find function used for stacked bars: find min, max and total sum across all data. *
  2129. X * Check also possibility of labelling across etc. */
  2130. X{
  2131. X    int i;
  2132. X    vreal w;
  2133. X    static char nothing[] = "";
  2134. X    int labfound = 1;
  2135. X    char *good = NULL, *aux;
  2136. X    
  2137. X    *min = VERYLARGE;
  2138. X    *max = -VERYLARGE;
  2139. X    *sum = 0.0;
  2140. X    for (i=0; i<data_head.chunks; i++) {
  2141. X        if (!across[i].chnp || (w=across[i].chnp->dval[across[i].vindex]) == VERYLARGE) continue;
  2142. X        if (*min > w) *min = w;
  2143. X        if (*max < w) *max = w;
  2144. X        *sum += w;
  2145. X        if (labfound && across[i].chnp->vlbl && (aux = across[i].chnp->vlbl[across[i].vindex]))
  2146. X            if (!good)    /* first found */
  2147. X                good = aux;
  2148. X            else
  2149. X                labfound = !strcmp(good,aux);
  2150. X    }
  2151. X
  2152. X    if (!good)            /* no label found, all undefined */
  2153. X        *lab = NULL;
  2154. X    else if (labfound)    /* all labels are the same -- return any */
  2155. X        *lab = good;
  2156. X    else                 /* different -- return fake label (will be processed in function, but rejected later) */
  2157. X        *lab = nothing;
  2158. X    
  2159. X    if (*min == VERYLARGE || *max == -VERYLARGE)        /* all points undefined */
  2160. X        return(FALSE);
  2161. X    else
  2162. X        return(TRUE);
  2163. X}
  2164. X
  2165. Xchar *comm_lget()
  2166. X/* check labels (like find_ran above), but also advance pointers */
  2167. X{
  2168. X    int i, j;
  2169. X    static char nothing[] = "";
  2170. X    int labfound = 1;
  2171. X    char *good = NULL, *aux;
  2172. X
  2173. X    for (i=0; i<data_head.chunks; i++) {
  2174. X        if (!across[i].chnp) continue;
  2175. X        j = across[i].vindex;
  2176. X        if (across[i].chnp->dval[j] != VERYLARGE && across[i].chnp->vlbl && (aux = across[i].chnp->vlbl[j]))
  2177. X            if (!good)    /* first found */
  2178. X                good = aux;
  2179. X            else
  2180. X                labfound = !strcmp(good,aux);
  2181. X        if (++across[i].vindex == across[i].chnp->used) {
  2182. X            across[i].chnp = across[i].chnp->next;
  2183. X            across[i].vindex = 0;
  2184. X        }
  2185. X    }
  2186. X
  2187. X    if (!good)        /* no label found, all undefined */
  2188. X        return (NULL);
  2189. X    else if (labfound)        /* all labels are the same -- return any */
  2190. X        return (good);
  2191. X    else
  2192. X        return (nothing);
  2193. X}
  2194. X    
  2195. Xdo_axis(a1,a2,xb,xm,yb,ym,reserved)
  2196. Xdouble *a1, *a2;
  2197. Xint xb, xm, yb, ym;
  2198. XBOOLEAN reserved;        /* should we shrink drawing area, or there's enough space ? */
  2199. X/* draws axis for bars, reserve space for values, put tickmarks with labels */
  2200. X{
  2201. X    double minv = *a1, maxv = *a2, tick, minpl, maxpl, unit;
  2202. X    int dirNS = !((int)gravity&1);
  2203. X    int i, j, space;
  2204. X
  2205. X    space = dirNS ? (ym-yb)/t->v_char : (xm-xb)/t->h_char;
  2206. X    if (minv == maxv)
  2207. X        tick=0;
  2208. X    else if (log_y) {
  2209. X        minpl = minv = floor(minv)+log10(2.0)<minv ? floor(minv)+log10(2.0) : floor(minv);
  2210. X        maxpl = maxv = ceil(maxv)-log10(2.0)>maxv ? ceil(maxv)-log10(2.0) : ceil(maxv);
  2211. X        tick = floor(log10(maxv-minv))+1;
  2212. X    }
  2213. X    else {
  2214. X        double aux = fabs(minv)>fabs(maxv) ? fabs(minv) : fabs(maxv);
  2215. X        tick = exp10(floor(log10(aux)));
  2216. X        aux  = exp10(floor(log10(aux)-1));
  2217. X        minpl = tick * ceil(minv/tick);
  2218. X        maxpl = tick * floor(maxv/tick);
  2219. X        minv = aux * floor(minv/aux);
  2220. X        maxv = aux * ceil(maxv/aux);
  2221. X        if ((maxv-minv)/tick <= 3.0) {
  2222. X            int flip = 1;
  2223. X            do {
  2224. X                tick /= flip ? 2.0 : 5.0;
  2225. X                flip = 1-flip;
  2226. X                minpl = tick * ceil(minv/tick);
  2227. X                maxpl = tick * floor(maxv/tick);
  2228. X            } while ((maxv-minv)/tick <= 3.0);
  2229. X        }
  2230. X        if ((maxpl-minpl)/tick >= (double)space) {
  2231. X            int flip = 1;
  2232. X            do {
  2233. X                tick *= flip ? 5.0 : 2.0;
  2234. X                flip = 1-flip;
  2235. X                minpl = tick * ceil(minv/tick);
  2236. X                maxpl = tick * floor(maxv/tick);
  2237. X            } while ((maxpl-minpl)/tick >= (double)space);
  2238. X        }
  2239. X    }
  2240. X
  2241. X    if (!tick) return(0);
  2242. X
  2243. X    unit = (dirNS ? ym-yb : xm-xb)/(maxv-minv);
  2244. X    (*t->linetype)(0);        /* solid linetype */
  2245. X    switch (gravity) {
  2246. X        case SOUTH:
  2247. X            if (!reserved)
  2248. X                xb += t->h_char*howmuch + 2*t->h_tic;
  2249. X            j = xb - 2*t->h_tic;
  2250. X            (*t->move)(xb,yb);
  2251. X            (*t->vector)(xb,ym);
  2252. X            (*t->linetype)(0);        /* the only type solid for sure */
  2253. X            while (minpl<=maxpl) {
  2254. X                (*t->move)(xb,i=yb+nint((minpl-minv)*unit));
  2255. X                (*t->vector)(xb-t->h_tic,i);
  2256. X                put_txt(j, i, make_labl((double) (log_y ? exp10(minpl) : minpl)), RIGHT, 0);
  2257. X                minpl += tick;
  2258. X            }
  2259. X            break;
  2260. X        case NORTH:
  2261. X            if (!reserved)
  2262. X                xm -= t->h_char*howmuch + 2*t->h_tic;
  2263. X            j = xm + 2*t->h_tic;
  2264. X            (*t->move)(xm,yb);
  2265. X            (*t->vector)(xm,ym);
  2266. X            (*t->linetype)(0);        /* the only type solid for sure */
  2267. X            while (minpl<=maxpl) {
  2268. X                (*t->move)(xm,i=ym-nint((minpl-minv)*unit));
  2269. X                (*t->vector)(xm+t->h_tic,i);
  2270. X                put_txt(j, i, make_labl((double) (log_y ? exp10(minpl) : minpl)), LEFT, 0);
  2271. X                minpl += tick;
  2272. X            }
  2273. X            break;
  2274. X        case WEST:
  2275. X            if (!reserved)
  2276. X                ym -= t->v_char*howmuch + 2*t->v_tic;
  2277. X            j = ym + 2*t->v_tic;
  2278. X            (*t->move)(xb,ym);
  2279. X            (*t->vector)(xm,ym);
  2280. X            (*t->linetype)(0);        /* the only type solid for sure */
  2281. X            while (minpl<=maxpl) {
  2282. X                (*t->move)(i=xb+nint((minpl-minv)*unit),ym);
  2283. X                (*t->vector)(i,ym+t->v_tic);
  2284. X                put_txt(i, j, make_labl((double) (log_y ? exp10(minpl) : minpl)), LEFT, 1);
  2285. X                minpl += tick;
  2286. X            }
  2287. X            break;
  2288. X        case EAST:
  2289. X            if (!reserved)
  2290. X                yb += t->v_char*howmuch + 2*t->v_tic;
  2291. X            j = yb - 2*t->v_tic;
  2292. X            (*t->move)(xm,yb);
  2293. X            (*t->vector)(xb,yb);
  2294. X            (*t->linetype)(0);        /* the only type solid for sure */
  2295. X            while (minpl<=maxpl) {
  2296. X                (*t->move)(i=xm-nint((minpl-minv)*unit),yb);
  2297. X                (*t->vector)(i,yb-t->v_tic);
  2298. X                put_txt(i, j, make_labl((double) (log_y ? exp10(minpl) : minpl)), RIGHT, 1); 
  2299. X                minpl += tick;
  2300. X            }
  2301. X            break;
  2302. X    }
  2303. X
  2304. X    *a1 = minv; *a2 = maxv;
  2305. X    return ( (int) (2*(dirNS ? t->h_tic : t->v_tic) + howmuch*(dirNS ? t->h_char : t->v_char)) );
  2306. X        /* if (reserved), return value is rejected, so it doesn't matter */
  2307. X}
  2308. X
  2309. X/* from hereon go different labeling functions. The basic one is the first */
  2310. X
  2311. Xint draw_text(x, y, s, h, w, tc, just, an)
  2312. Xint x, y, h, w, tc;
  2313. Xchar *s;
  2314. Xenum JUSTIFY just;
  2315. Xdouble an;
  2316. X/* draw text in vector font and return useful info - complementary of h parameter */
  2317. X{
  2318. X    int wid, k, retv, rwid;
  2319. X    char *p;
  2320. X    double sc;
  2321. X    int *d;
  2322. X    MATRIX R, S, A;
  2323. X
  2324. X    if (!s || !*s || !tc || !h && !w)
  2325. X        return(0);        /* nothing useful can be done */
  2326. X    if (tc>0 && tc < strlen(s))
  2327. X        s[tc] = '\0';    /* truncate */
  2328. X    
  2329. X    for (p=s, wid=0; *p; p++)
  2330. X        if (!trt[*p=toascii(*p)].wid)
  2331. X            wid += trt[0].wid + CHAR_OFF;
  2332. X        else
  2333. X            wid += trt[*p].wid + CHAR_OFF;
  2334. X    rwid = wid;
  2335. X    
  2336. X    rotat(-an, R);                            /* rotate object system (!) */
  2337. X    
  2338. X    if (h) {
  2339. X        sc = (double)(h) / (double)CHAR_GRD;
  2340. X        wid *= sc;
  2341. X        retv = wid;
  2342. X    }
  2343. X    else
  2344. X        wid = 0;
  2345. X    if (!wid || w && wid > w) {                /* can't with with desired height -- try to schrink */
  2346. X        sc = (double)(w)/(double)(rwid);
  2347. X        wid = w;
  2348. X        retv = CHAR_GRD*sc;                    /* return text height */
  2349. X    }
  2350. X    scale(sc, sc, S);
  2351. X    multi(S, R, A);
  2352. X    
  2353. X    switch (just) {
  2354. X        case LEFT: break;
  2355. X        case CENTRE: {
  2356. X            wid /= 2;    /* and no break */
  2357. X        }
  2358. X        case RIGHT: {
  2359. X            x -= (double)wid*cos(an);        /* rotate within coordinate system */
  2360. X            y -= (double)wid*sin(an);
  2361. X        }
  2362. X    }    
  2363. X    if (x<0 || y<0) 
  2364. X        return(0);    /* nothing useful - failed */
  2365. X
  2366. X#ifdef NO_ROMAN_FONT
  2367. X
  2368. X    x += (CHAR_OFF/2)*A[0][0]+A[0][2];
  2369. X    y += (CHAR_OFF/2)*A[1][0]+A[1][2]; 
  2370. X
  2371. X#define MX(v) nint( (*(v))*A[0][0] + (*(v+1))*A[0][1] + A[0][2] )
  2372. X#define MY(v) nint( (*(v))*A[1][0] + (*(v+1))*A[1][1] + A[1][2] )
  2373. X
  2374. X    {
  2375. X        unsigned char *u;
  2376. X        int i,j;
  2377. 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++) {
  2378. X            if (!trt[c=*s].wid) c='\0';
  2379. X            for (i=0; i<3 && (u=trt[c].def[i]); i++) {
  2380. X                (*t->move) (x+MX(u), y+MY(u));
  2381. X                while (*(u+=2))
  2382. X                    (*t->vector) (x+MX(u), y+MY(u));
  2383. X            }
  2384. X        }
  2385. X    }
  2386. X
  2387. X#undef MX
  2388. X#undef MY
  2389. X
  2390. X#else        /* another algorithm: for roman font */
  2391. X
  2392. X    x -= (CHAR_OFF/2)*A[0][0]+A[0][2];
  2393. X    y -= (CHAR_OFF/2)*A[1][0]+A[1][2]; 
  2394. X
  2395. X#define MX(v) nint( ((v)/100)*A[0][0] + ((v)%100)*A[0][1] + A[0][2] )
  2396. X#define MY(v) nint( ((v)/100)*A[1][0] + ((v)%100)*A[1][1] + A[1][2] )
  2397. X
  2398. 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++)
  2399. X        for (d=trt[*s].def; *d; d++)
  2400. X            if ((k=*d)<0) {
  2401. X                k = abs(k);
  2402. X                (*t->move)(x+MX(k), y+MY(k));
  2403. X            }
  2404. X            else
  2405. X                (*t->vector)(x+MX(k), y+MY(k));
  2406. X    
  2407. X#undef MX
  2408. X#undef MY
  2409. X    
  2410. X#endif    
  2411. X
  2412. X    return(retv);
  2413. X}
  2414. X
  2415. Xmake_just(x, y, j, l, d)
  2416. Xint *x, *y;
  2417. Xint l, d;                /* l != 0 */
  2418. Xenum JUSTIFY j;
  2419. X/* set terminal justification */
  2420. X{
  2421. X    if (!d) { 
  2422. X        if (j == LEFT) 
  2423. X            (void) (*t->justify_text)(LEFT);
  2424. X        else if ((*t->justify_text)(j)) ;
  2425. X        else if (j == CENTRE)
  2426. X            *x -= t->h_char * l/2;
  2427. X        else if (j == RIGHT)
  2428. X            *x -= t->h_char * l;
  2429. X        else /* impossible */ return;
  2430. X    }
  2431. X    else {
  2432. X        if (j == LEFT) 
  2433. X            (void) (*t->justify_text)(LEFT);
  2434. X        else if ((*t->justify_text)(j)) ;
  2435. X        else if (j == CENTRE)
  2436. X            *y -= t->h_char * l/2;
  2437. X        else if (j == RIGHT)
  2438. X            *y -= t->h_char * l;
  2439. X        else /* impossible */ return;
  2440. X    }
  2441. X}
  2442. X
  2443. Xput_txt(x,y,s,j,d)
  2444. Xint x, y, d;
  2445. Xchar *s;
  2446. Xenum JUSTIFY j;
  2447. X/* put any text on given position, with standard size, sideways or rotated +Pi/2 */
  2448. X{
  2449. X    if (!s || !*s) return;
  2450. X    if ((trotate || !d) && vect_font == F_WHENN ||        /* terminal can or need not rotate */
  2451. X        vect_font == F_NEVER) {                            /* never use vector font, regardles of anything */
  2452. X        if (tstate != d)
  2453. X            (*t->text_angle)(tstate = d);
  2454. X        make_just(&x, &y, j, strlen(s), d);
  2455. X        (*t->put_text)(x, y, s);
  2456. X    }            
  2457. X    else {        /* use vector font */
  2458. X        int i = t->v_char;
  2459. X        if (d)
  2460. X            x += t->h_char/2;    /* draw_text takes lower-left corner */
  2461. X        else
  2462. X            y -= t->h_char/2;
  2463. X        (void) draw_text(x, y, s, i, 0, -1, j, d*Pi/2);
  2464. X    }
  2465. X}
  2466. X
  2467. Xput_lab(x,y,s,d,size)
  2468. Xint x, y, d, size;
  2469. Xchar *s;
  2470. X/* put label centered around (x,y), fitting it within given size, use vector font if only allowed */
  2471. X{
  2472. X    int i, j, l;
  2473. X
  2474. X    if (!s || !*s || size<=0)
  2475. X        return;        /* nothing useful */
  2476. X
  2477. X    j = size / t->h_char;                            /* number of standard chars that can fit */
  2478. X    i = (l=strlen(s)) < howmuch ? howmuch : l;        /* how many chars should we fit ? */
  2479. X
  2480. X    if (vect_font == F_NEVER ||                     /* never use vector font */
  2481. X        !d && i <= j && vect_font != F_ALWYS) {        /* horizontal, fits within req. size, no need for font */
  2482. X        if (tstate != d)
  2483. X            (*t->text_angle)(tstate = d);
  2484. X        make_just(&x, &y, CENTRE, strlen(s), d);
  2485. X        (*t->put_text)(x, y, s);
  2486. X    }
  2487. X    else {                                            /* pain in the ass */
  2488. X        if (d)
  2489. X            x += t->h_char/2;                        /* draw_text takes lower-left corner */
  2490. X        else
  2491. X            y -= t->v_char/2;
  2492. X        i = t->v_char;
  2493. X        (void) draw_text(x, y, s, i, size, -1, CENTRE, d*Pi/2);
  2494. X    }
  2495. X}
  2496. X
  2497. Xchar *make_labl(d)
  2498. Xdouble d;
  2499. X{
  2500. X    static char buf[200];
  2501. X    if (d == VERYLARGE || d== -VERYLARGE)
  2502. X        return(NULL);    /* will be rejected later */
  2503. X    sprintf(buf, tic_form, (float) d);    /* it's float from user point of view, and compatibility with Gnuplot */
  2504. X    return(buf);
  2505. X}
  2506. X
  2507. Xset_hm(min, max)
  2508. Xdouble min, max;
  2509. X/* find space needed for ticks */
  2510. X{
  2511. X    char buf[200];
  2512. X    int i;
  2513. X    sprintf(buf, tic_form, (float) min);
  2514. X    howmuch = strlen(buf);
  2515. X    sprintf(buf, tic_form, (float) max);
  2516. X    if (howmuch < (i=strlen(buf)))
  2517. X        howmuch = i;
  2518. X}
  2519. X
  2520. Xinit_acrs()
  2521. X/* init across pointer structure */
  2522. X{
  2523. X    struct dfile *f = &data_head;
  2524. X    int i = 0;
  2525. X
  2526. X    while (f = f->dnxt) {
  2527. X        across[i].chnp = f->data;
  2528. X        across[i++].vindex = 0;
  2529. X    }
  2530. X}
  2531. X
  2532. X/* test terminal by drawing border and text */
  2533. X/* called from command test */
  2534. Xterm_test()
  2535. X/* don't use original test_term() from term.c */
  2536. X{
  2537. X    char *str;
  2538. X    int x,y, xl,yl, i;
  2539. X    char label[MAX_LINE_LEN];
  2540. X
  2541. X    t = &term_tbl[term];
  2542. X    if (!term_init) {
  2543. X       (*t->init)();
  2544. X       term_init = TRUE;
  2545. X    }
  2546. X    screen_ok = FALSE;
  2547. X    (*t->graphics)();
  2548. X    /* border linetype */
  2549. X    (*t->linetype)(-2);
  2550. X    (*t->move)(0,0);
  2551. X    (*t->vector)(t->xmax-1,0);
  2552. X    (*t->vector)(t->xmax-1,t->ymax-1);
  2553. X    (*t->vector)(0,t->ymax-1);
  2554. X    (*t->vector)(0,0);
  2555. X    (void) (*t->justify_text)(LEFT);
  2556. X    (*t->put_text)(t->h_char*5,t->ymax-t->v_char*3,"Terminal Test");
  2557. X    (*t->linetype)(0);
  2558. X    (*t->arrow)(t->h_char*5, t->ymax-t->v_char*5, t->h_char*5, t->ymax/2+t->v_char);
  2559. X    /* axis linetype */
  2560. X    (*t->linetype)(-1);
  2561. X    (*t->move)(t->xmax/2,0);
  2562. X    (*t->vector)(t->xmax/2,t->ymax-1);
  2563. X    (*t->move)(0,t->ymax/2);
  2564. X    (*t->vector)(t->xmax-1,t->ymax/2);
  2565. X    /* test width and height of characters */
  2566. X    (*t->linetype)(-2);
  2567. X    (*t->move)(  t->xmax/2-t->h_char*10,t->ymax/2+t->v_char/2);
  2568. X    (*t->vector)(t->xmax/2+t->h_char*10,t->ymax/2+t->v_char/2);
  2569. X    (*t->vector)(t->xmax/2+t->h_char*10,t->ymax/2-t->v_char/2);
  2570. X    (*t->vector)(t->xmax/2-t->h_char*10,t->ymax/2-t->v_char/2);
  2571. X    (*t->vector)(t->xmax/2-t->h_char*10,t->ymax/2+t->v_char/2);
  2572. X    (*t->put_text)(t->xmax/2-t->h_char*10,t->ymax/2,
  2573. X        "12345678901234567890");
  2574. X    /* test justification */
  2575. X    (void) (*t->justify_text)(LEFT);
  2576. X    (*t->put_text)(t->xmax/2,t->ymax/2+t->v_char*5,"left justified");
  2577. X    str = "centre+d text";
  2578. X    if ((*t->justify_text)(CENTRE))
  2579. X        (*t->put_text)(t->xmax/2,
  2580. X                t->ymax/2+t->v_char*4,str);
  2581. X    else
  2582. X        (*t->put_text)(t->xmax/2-strlen(str)*t->h_char/2,
  2583. X                t->ymax/2+t->v_char*4,str);
  2584. X    str = "right justified";
  2585. X    if ((*t->justify_text)(RIGHT))
  2586. X        (*t->put_text)(t->xmax/2,
  2587. X                t->ymax/2+t->v_char*3,str);
  2588. X    else
  2589. X        (*t->put_text)(t->xmax/2-strlen(str)*t->h_char,
  2590. X                t->ymax/2+t->v_char*3,str);
  2591. X    /* test text angle */
  2592. X    str = "rotated ce+ntred text";
  2593. X    if ((*t->text_angle)(1)) {
  2594. X        if ((*t->justify_text)(CENTRE))
  2595. X            (*t->put_text)(t->v_char,
  2596. X                t->ymax/2,str);
  2597. X        else
  2598. X            (*t->put_text)(t->v_char,
  2599. X                t->ymax/2-strlen(str)*t->h_char/2,str);
  2600. X    }
  2601. X    else {
  2602. X        (void) (*t->justify_text)(LEFT);
  2603. X        (*t->put_text)(t->h_char*2,t->ymax/2-t->v_char*2,"Can't rotate text");
  2604. X    }
  2605. X    (void) (*t->justify_text)(LEFT);
  2606. X    (void) (*t->text_angle)(0);
  2607. X    /* test tic size */
  2608. X    (*t->move)(t->xmax/2+t->h_tic*2,0);
  2609. X    (*t->vector)(t->xmax/2+t->h_tic*2,t->v_tic);
  2610. X    (*t->move)(t->xmax/2,t->v_tic*2);
  2611. X    (*t->vector)(t->xmax/2+t->h_tic,t->v_tic*2);
  2612. X    (*t->put_text)(t->xmax/2+t->h_tic*2,t->v_tic*2+t->v_char/2,"test tics");
  2613. X    /* test line and point types */
  2614. X    x = t->xmax - t->h_char*4 - t->h_tic*4;
  2615. X    y = t->ymax - t->v_char;
  2616. X    for ( i = -2; y > t->v_char; i++ ) {
  2617. X        (*t->linetype)(i);
  2618. X        (void) sprintf(label,"%d",i);
  2619. X        if ((*t->justify_text)(RIGHT))
  2620. X            (*t->put_text)(x,y,label);
  2621. X        else
  2622. X            (*t->put_text)(x-strlen(label)*t->h_char,y,label);
  2623. X        (*t->move)(x+t->h_char,y);
  2624. X        (*t->vector)(x+t->h_char*4,y);
  2625. X        y -= t->v_char;
  2626. X    }
  2627. X    /* test bars */
  2628. X    (*t->linetype)(-1);
  2629. X    x = t->xmax/2 + t->xmax/12;
  2630. X    y = t->ymax/6;
  2631. X    xl = t->xmax/32;
  2632. X    yl = t->ymax/32;
  2633. X    (*t->move)(x,y);
  2634. X    (*t->vector)(x+xl*6,y);
  2635. X    x += xl/4;
  2636. X    for (i=1; i<=4; i++, x+=xl*3/2) {
  2637. X        (*t->linetype)(i-1);
  2638. X        put_bar(x,y,xl,i*yl,FALSE);
  2639. X    }
  2640. X    /* test pies */
  2641. X    (*t->linetype)(0);
  2642. X    x = t->xmax/4;
  2643. X    y = t->ymax/4;
  2644. X    i = 3*(t->xmax < t->ymax ? t->xmax : t->ymax)/32;
  2645. X    xl = MCx(0,i,Pi/4);
  2646. X    yl = MCy(0,i,Pi/4);
  2647. X    (*t->move)(x+xl,y+yl);
  2648. X    (*t->vector)(x-xl,y-yl);
  2649. X    (*t->move)(x-xl,y+yl);
  2650. X    (*t->vector)(x+xl,y-yl);
  2651. X    put_arc(x,y,i,Pi/4,3*Pi/2);
  2652. X    sprintf(label,"(pie sampling is %d)",samples);
  2653. X    put_txt(x,y-yl-2*(int)(t->v_char),label,CENTRE,0);
  2654. X    x += t->xmax/32;
  2655. X    (*t->move)(x+xl,y-yl);
  2656. X    (*t->vector)(x,y);
  2657. X    (*t->vector)(x+xl,y+yl);
  2658. X    put_arc(x,y,i,Pi/4,-Pi/2);
  2659. X
  2660. X    /* experimental code */
  2661. X    (*t->linetype)(0);
  2662. X    x = t->xmax/2 + t->xmax/32;
  2663. X    y = t->ymax*9/10;
  2664. X    i = t->v_char;
  2665. X    x += draw_text(x, y, "experimental", i, 0, -1, LEFT, 0.0);
  2666. X    i = draw_text(x, y, "scalable", i*2, 0, -1, LEFT, -Pi/4);
  2667. X    x += i*cos(-Pi/4); y += i*sin(-Pi/4);
  2668. X    (void) draw_text(x, y, "vector font", 0, (int)(t->xmax/16), -1, LEFT, -Pi/2);
  2669. X    y -= (int)(t->xmax/16);
  2670. X    (void) draw_text(x, y, "0123456789", 0, (int)(t->xmax/8), -1, LEFT, -Pi); 
  2671. X    
  2672. X    /* and back into text mode */
  2673. X    (*t->text)();
  2674. X    (void) fflush(outfile);
  2675. X}
  2676. X
  2677. X
  2678. X
  2679. X
  2680. X
  2681. X
  2682. X
  2683. X
  2684. X
  2685. X
  2686. X/* included file contains an old version of graphics routines */
  2687. X
  2688. X#include "fstyles.i"
  2689. X
  2690. X
  2691. X
  2692. X
  2693. X
  2694. SHAR_EOF
  2695. $TOUCH -am 0604152590 fgraf.c &&
  2696. chmod 0666 fgraf.c ||
  2697. echo "restore of fgraf.c failed"
  2698. set `wc -c fgraf.c`;Wc_c=$1
  2699. if test "$Wc_c" != "22428"; then
  2700.     echo original size 22428, current size $Wc_c
  2701. fi
  2702. echo "End of part 2, continue with part 3"
  2703. exit 0
  2704.