home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / fchart.lzh / fchart.2 < prev    next >
Encoding:
Text File  |  1990-06-09  |  69.8 KB  |  2,698 lines

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