home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / gnuplot / part12 < prev    next >
Encoding:
Text File  |  1993-10-21  |  78.8 KB  |  2,392 lines

  1. Newsgroups: comp.sources.misc
  2. From: woo@playfair.stanford.edu ("Alexander Woo")
  3. Subject: v40i024:  gnuplot - interactive function plotting utility, Part12/33
  4. Message-ID: <1993Oct21.144602.2174@sparky.sterling.com>
  5. X-Md4-Signature: 769b306f285bcadc75b0c8ed3ab97410
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Thu, 21 Oct 1993 14:46:02 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: woo@playfair.stanford.edu ("Alexander Woo")
  12. Posting-number: Volume 40, Issue 24
  13. Archive-name: gnuplot/part12
  14. Environment: UNIX, MS-DOS, VMS
  15. Supersedes: gnuplot3: Volume 24, Issue 23-48
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  gnuplot/buildvms.com gnuplot/contour.c gnuplot/gplt_x11.c
  22. # Wrapped by kent@sparky on Wed Oct 20 17:14:45 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 12 (of 33)."'
  26. if test -f 'gnuplot/buildvms.com' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'gnuplot/buildvms.com'\"
  28. else
  29.   echo shar: Extracting \"'gnuplot/buildvms.com'\" \(1534 characters\)
  30.   sed "s/^X//" >'gnuplot/buildvms.com' <<'END_OF_FILE'
  31. X$ ! buildvms.com  (Command file to compile/link gnuplot and doc2hlp)
  32. X$ CFLAGS = "/nowarn/NOOP/define=(NOGAMMA,MEMSET)"
  33. X$ TERMFLAGS = "/define=(X11,VMS)"
  34. X$ LINK_OPT=",linkopt.vms/opt"
  35. X$ IF F$EXTRACT(0, 3, F$GETSYI("HW_NAME")) .NES. "VAX"
  36. X$ THEN        ! Probably Alpha.
  37. X$    LINK_OPT = ""
  38. X$    CFLAGS = CFLAGS + "/PREFIX=ALL"
  39. X$ ENDIF
  40. X$! For DECwindows:
  41. X$ DEFINE X11 DECW$INCLUDE
  42. X$ set verify
  43. X$ cc 'CFLAGS' binary.c
  44. X$ cc 'CFLAGS' gnubin.c
  45. X$ cc 'CFLAGS' specfun.c
  46. X$ cc 'CFLAGS' bitmap.c
  47. X$ cc 'CFLAGS' command.c
  48. X$ cc 'CFLAGS' contour.c
  49. X$ cc 'CFLAGS' eval.c
  50. X$ cc 'CFLAGS' graphics.c
  51. X$ cc 'CFLAGS' graph3d.c
  52. X$ cc 'CFLAGS' internal.c
  53. X$ cc 'CFLAGS' 'TERMFLAGS' misc.c
  54. X$ cc 'CFLAGS' parse.c
  55. X$ cc 'CFLAGS' plot.c
  56. X$ cc 'CFLAGS' scanner.c
  57. X$ cc 'CFLAGS' setshow.c
  58. X$ cc 'CFLAGS' standard.c
  59. X$ cc 'CFLAGS' 'TERMFLAGS' term.c
  60. X$ cc 'CFLAGS' util.c
  61. X$ cc 'CFLAGS' version.c
  62. X$ link /exe=gnuplot -
  63. X   bitmap.obj,command.obj,contour.obj,eval.obj,graphics.obj,graph3d.obj, -
  64. X   binary,gnubin,specfun, -
  65. X   internal.obj,misc.obj,parse.obj,plot.obj,scanner.obj,setshow.obj, -
  66. X   standard.obj,term.obj,util.obj,version.obj 'LINK_OPT'
  67. X$ cc 'CFLAGS' bf_test.c
  68. X$ link /exe=bf_test bf_test.obj,binary.obj 'LINK_OPT'
  69. X$ ren bf_test.exe [.demo]
  70. X$ CC/nowarn/DEFINE=VMS GPLT_X11
  71. X$ LINK /exe=GNUPLOT_X11 gplt_x11,SYS$INPUT:/OPT
  72. XSYS$SHARE:DECW$XLIBSHR/SHARE
  73. X$ cc [.docs]doc2hlp.c
  74. X$ link doc2hlp 'LINK_OPT'
  75. X$ @[.docs]doc2hlp.com
  76. X$ library/create/help gnuplot.hlb gnuplot.hlp
  77. X$ run [.demo]bf_test
  78. X$ write sys$output "%define GNUPLOT_X11 :== $Disk:[directory]GNUPLOT_X11"
  79. X$ set noverify
  80. END_OF_FILE
  81.   if test 1534 -ne `wc -c <'gnuplot/buildvms.com'`; then
  82.     echo shar: \"'gnuplot/buildvms.com'\" unpacked with wrong size!
  83.   fi
  84.   # end of 'gnuplot/buildvms.com'
  85. fi
  86. if test -f 'gnuplot/contour.c' -a "${1}" != "-c" ; then 
  87.   echo shar: Will not clobber existing file \"'gnuplot/contour.c'\"
  88. else
  89.   echo shar: Extracting \"'gnuplot/contour.c'\" \(43000 characters\)
  90.   sed "s/^X//" >'gnuplot/contour.c' <<'END_OF_FILE'
  91. X#ifndef lint
  92. Xstatic char *RCSid = "$Id: contour.c%v 3.50 1993/07/09 05:35:24 woo Exp $";
  93. X#endif
  94. X
  95. X
  96. X/* GNUPLOT - contour.c */
  97. X/*
  98. X * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  99. X *
  100. X * Permission to use, copy, and distribute this software and its
  101. X * documentation for any purpose with or without fee is hereby granted, 
  102. X * provided that the above copyright notice appear in all copies and 
  103. X * that both that copyright notice and this permission notice appear 
  104. X * in supporting documentation.
  105. X *
  106. X * Permission to modify the software is granted, but not the right to
  107. X * distribute the modified code.  Modifications are to be distributed 
  108. X * as patches to released version.
  109. X *  
  110. X * This software is provided "as is" without express or implied warranty.
  111. X * 
  112. X *
  113. X * AUTHORS
  114. X * 
  115. X *   Original Software:
  116. X *       Gershon Elber
  117. X * 
  118. X * There is a mailing list for gnuplot users. Note, however, that the
  119. X * newsgroup 
  120. X *    comp.graphics.gnuplot 
  121. X * is identical to the mailing list (they
  122. X * both carry the same set of messages). We prefer that you read the
  123. X * messages through that newsgroup, to subscribing to the mailing list.
  124. X * (If you can read that newsgroup, and are already on the mailing list,
  125. X * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  126. X * removed from the mailing list.)
  127. X *
  128. X * The address for mailing to list members is
  129. X *       info-gnuplot@dartmouth.edu
  130. X * and for mailing administrative requests is 
  131. X *       info-gnuplot-request@dartmouth.edu
  132. X * The mailing list for bug reports is 
  133. X *       bug-gnuplot@dartmouth.edu
  134. X * The list of those interested in beta-test versions is
  135. X *       info-gnuplot-beta@dartmouth.edu
  136. X */
  137. X
  138. X#include <stdio.h>
  139. X#include "plot.h"
  140. X
  141. X#define DEFAULT_NUM_OF_ZLEVELS  10  /* Some dflt values (setable via flags). */
  142. X#define DEFAULT_NUM_APPROX_PTS  5
  143. X#define DEFAULT_BSPLINE_ORDER  3
  144. X#define MAX_NUM_OF_ZLEVELS      100 /* Some max. values (setable via flags). */
  145. X#define MAX_NUM_APPROX_PTS      100
  146. X#define MAX_BSPLINE_ORDER      10
  147. X
  148. X#define INTERP_NOTHING   0            /* Kind of interpolations on contours. */
  149. X#define INTERP_CUBIC     1                           /* Cubic spline interp. */
  150. X#define APPROX_BSPLINE   2                         /* Bspline interpolation. */
  151. X
  152. X#define LEVELS_AUTO            0        /* How contour levels are set */
  153. X#define LEVELS_INCREMENTAL    1        /* user specified start & incremnet */
  154. X#define LEVELS_DISCRETE        2        /* user specified discrete levels */
  155. X#define ACTIVE   1                    /* Status of edges at certain Z level. */
  156. X#define INACTIVE 2
  157. X
  158. X#define OPEN_CONTOUR     1                                 /* Contour kinds. */
  159. X#define CLOSED_CONTOUR   2
  160. X
  161. X#define EPSILON  1e-5              /* Used to decide if two float are equal. */
  162. X#define INFINITY 1e10
  163. X
  164. X#ifndef TRUE
  165. X#define TRUE     -1
  166. X#define FALSE    0
  167. X#endif
  168. X
  169. X#define DEFAULT_NUM_CONTOURS    10
  170. X#define MAX_POINTS_PER_CNTR     100
  171. X#define SHIFT_Z_EPSILON        0.000301060 /* Dec. change of poly bndry hit.*/
  172. X
  173. X#define abs(x)  ((x) > 0 ? (x) : (-(x)))
  174. X#define sqr(x)  ((x) * (x))
  175. X
  176. X#ifndef AMIGA_AC_5
  177. Xextern double sqrt();
  178. X#endif /* not AMIGA_AC_5 */
  179. Xtypedef double tri_diag[3];         /* Used to allocate the tri-diag matrix. */
  180. Xtypedef double table_entry[4];           /* Cubic spline interpolation 4 coef. */
  181. X
  182. Xstruct vrtx_struct {
  183. X    double X, Y, Z;                       /* The coordinates of this vertex. */
  184. X    struct vrtx_struct *next;                             /* To chain lists. */
  185. X};
  186. X
  187. Xstruct edge_struct {
  188. X    struct poly_struct *poly[2];   /* Each edge belongs to up to 2 polygons. */
  189. X    struct vrtx_struct *vertex[2]; /* The two extreme points of this vertex. */
  190. X    struct edge_struct *next;                             /* To chain lists. */
  191. X    int status, /* Status flag to mark edges in scanning at certain Z level. */
  192. X    boundary;                   /* True if this edge is on the boundary. */
  193. X};
  194. X
  195. Xstruct poly_struct {
  196. X    struct edge_struct *edge[3];           /* As we do triangolation here... */
  197. X    struct poly_struct *next;                             /* To chain lists. */
  198. X};
  199. X
  200. Xstruct cntr_struct {           /* Contours are saved using this struct list. */
  201. X    double X, Y;                          /* The coordinates of this vertex. */
  202. X    struct cntr_struct *next;                             /* To chain lists. */
  203. X};
  204. X
  205. Xstatic int test_boundary;    /* If TRUE look for contours on boundary first. */
  206. Xstatic struct gnuplot_contours *contour_list = NULL;
  207. Xstatic double crnt_cntr[MAX_POINTS_PER_CNTR * 2];
  208. Xstatic int crnt_cntr_pt_index = 0;
  209. Xstatic double contour_level = 0.0;
  210. Xstatic table_entry *hermit_table = NULL;    /* Hold hermite table constants. */
  211. Xstatic int num_of_z_levels = DEFAULT_NUM_OF_ZLEVELS;  /* # Z contour levels. */
  212. Xstatic int num_approx_pts = DEFAULT_NUM_APPROX_PTS;/* # pts per approx/inter.*/
  213. Xstatic int bspline_order = DEFAULT_BSPLINE_ORDER;   /* Bspline order to use. */
  214. Xstatic int interp_kind = INTERP_NOTHING;  /* Linear, Cubic interp., Bspline. */
  215. Xstatic int levels_kind = LEVELS_AUTO;  /* auto, incremental, discrete */
  216. X
  217. X
  218. Xstatic void gen_contours();
  219. Xstatic int update_all_edges();
  220. Xstatic struct cntr_struct *gen_one_contour();
  221. Xstatic struct cntr_struct *trace_contour();
  222. Xstatic struct cntr_struct *update_cntr_pt();
  223. Xstatic int fuzzy_equal();
  224. Xstatic void gen_triangle();
  225. Xstatic struct vrtx_struct *gen_vertices();
  226. Xstatic struct edge_struct *gen_edges_middle();
  227. Xstatic struct edge_struct *gen_edges();
  228. Xstatic struct poly_struct *gen_polys();
  229. Xstatic void free_contour();
  230. Xstatic void put_contour();
  231. Xstatic put_contour_nothing();
  232. Xstatic put_contour_cubic();
  233. Xstatic put_contour_bspline();
  234. Xstatic calc_tangent();
  235. Xstatic int count_contour();
  236. Xstatic complete_spline_interp();
  237. Xstatic calc_hermit_table();
  238. Xstatic hermit_interp();
  239. Xstatic prepare_spline_interp();
  240. Xstatic int solve_tri_diag();
  241. Xstatic gen_bspline_approx();
  242. Xstatic double fetch_knot();
  243. Xstatic eval_bspline();
  244. X
  245. X/*
  246. X * Entry routine to this whole set of contouring module.
  247. X */
  248. Xstruct gnuplot_contours *contour(num_isolines, iso_lines,
  249. X                 ZLevels, approx_pts, int_kind, order1,
  250. X                 levels_kind, levels_list)
  251. Xint num_isolines;
  252. Xstruct iso_curve *iso_lines;
  253. Xint ZLevels, approx_pts, int_kind, order1;
  254. Xint levels_kind;
  255. Xdouble *levels_list;
  256. X{
  257. X    int i;
  258. X    struct poly_struct *p_polys, *p_poly;
  259. X    struct edge_struct *p_edges, *p_edge;
  260. X    struct vrtx_struct *p_vrts, *p_vrtx;
  261. X    double x_min, y_min, z_min, x_max, y_max, z_max, z, dz;
  262. X     struct gnuplot_contours *save_contour_list;
  263. X
  264. X    num_of_z_levels = ZLevels;
  265. X    num_approx_pts = approx_pts;
  266. X    bspline_order = order1 - 1;
  267. X    interp_kind = int_kind;
  268. X
  269. X    contour_list = NULL;
  270. X
  271. X    if (interp_kind == INTERP_CUBIC) calc_hermit_table();
  272. X
  273. X    gen_triangle(num_isolines, iso_lines, &p_polys, &p_edges, &p_vrts,
  274. X        &x_min, &y_min, &z_min, &x_max, &y_max, &z_max);
  275. X    crnt_cntr_pt_index = 0;
  276. X
  277. X    dz = (z_max - z_min) / (num_of_z_levels + 1);
  278. X    z = z_min;
  279. X    for (i = 0; i < num_of_z_levels; i++) {
  280. X        switch(levels_kind) {
  281. X            case LEVELS_AUTO:
  282. X                /* Step from z_min+dz upto z_max-dz in num_of_z_levels times. */
  283. X                z += dz;
  284. X                break;
  285. X            case LEVELS_INCREMENTAL:
  286. X                z = levels_list[0] + i * levels_list[1];
  287. X                break;
  288. X            case LEVELS_DISCRETE:
  289. X                z = levels_list[i];
  290. X                break;
  291. X        }
  292. X        contour_level = z;
  293. X         save_contour_list = contour_list;
  294. X        gen_contours(p_edges, z + dz * SHIFT_Z_EPSILON, x_min, x_max,
  295. X                                y_min, y_max);
  296. X         if(contour_list != save_contour_list) {
  297. X             contour_list->isNewLevel = 1;
  298. X             sprintf(contour_list->label, "%8.3g", z);
  299. X         }
  300. X    }
  301. X
  302. X    /* Free all contouring related temporary data. */
  303. X    while (p_polys) {
  304. X    p_poly = p_polys -> next;
  305. X    free (p_polys);
  306. X    p_polys = p_poly;
  307. X    }
  308. X    while (p_edges) {
  309. X    p_edge = p_edges -> next;
  310. X    free (p_edges);
  311. X    p_edges = p_edge;
  312. X    }
  313. X    while (p_vrts) {
  314. X    p_vrtx = p_vrts -> next;
  315. X    free (p_vrts);
  316. X    p_vrts = p_vrtx;
  317. X    }
  318. X
  319. X    if (interp_kind == INTERP_CUBIC) free(hermit_table);
  320. X
  321. X    return contour_list;
  322. X}
  323. X
  324. X/*
  325. X * Adds another point to the currently build contour.
  326. X */
  327. Xadd_cntr_point(x, y)
  328. Xdouble x, y;
  329. X{
  330. X    int index;
  331. X
  332. X    if (crnt_cntr_pt_index >= MAX_POINTS_PER_CNTR-1) {
  333. X    index = crnt_cntr_pt_index - 1;
  334. X    end_crnt_cntr();
  335. X    crnt_cntr[0] = crnt_cntr[index * 2];
  336. X    crnt_cntr[1] = crnt_cntr[index * 2 + 1];
  337. X    crnt_cntr_pt_index = 1; /* Keep the last point as first of this one. */
  338. X    }
  339. X    crnt_cntr[crnt_cntr_pt_index * 2] = x;
  340. X    crnt_cntr[crnt_cntr_pt_index * 2 + 1] = y;
  341. X    crnt_cntr_pt_index++;
  342. X}
  343. X
  344. X/*
  345. X * Done with current contour - create gnuplot data structure for it.
  346. X */
  347. Xend_crnt_cntr()
  348. X{
  349. X    int i;
  350. X    struct gnuplot_contours *cntr = (struct gnuplot_contours *)
  351. X                    alloc((unsigned long)sizeof(struct gnuplot_contours),
  352. X                          "gnuplot_contour");
  353. X
  354. X    cntr->coords = (struct coordinate GPHUGE *) gpfaralloc((unsigned long)sizeof(struct coordinate) *
  355. X                              ( unsigned long)crnt_cntr_pt_index,
  356. X                           "contour coords");
  357. X    for (i=0; i<crnt_cntr_pt_index; i++) {
  358. X    cntr->coords[i].x = crnt_cntr[i * 2];
  359. X    cntr->coords[i].y = crnt_cntr[i * 2 + 1];
  360. X    cntr->coords[i].z = contour_level;
  361. X    }
  362. X    cntr->num_pts = crnt_cntr_pt_index;
  363. X
  364. X    cntr->next = contour_list;
  365. X    contour_list = cntr;
  366. X     contour_list->isNewLevel = 0;
  367. X
  368. X    crnt_cntr_pt_index = 0;
  369. X}
  370. X
  371. X/*
  372. X * Generates all contours by tracing the intersecting triangles.
  373. X */
  374. Xstatic void gen_contours(p_edges, z_level, x_min, x_max, y_min, y_max)
  375. Xstruct edge_struct *p_edges;
  376. Xdouble z_level, x_min, x_max, y_min, y_max;
  377. X{
  378. X    int num_active,                        /* Number of edges marked ACTIVE. */
  379. X    contour_kind;                /* One of OPEN_CONTOUR, CLOSED_CONTOUR. */
  380. X    struct cntr_struct *p_cntr;
  381. X
  382. X    num_active = update_all_edges(p_edges, z_level);           /* Do pass 1. */
  383. X
  384. X    test_boundary = TRUE;        /* Start to look for contour on boundaries. */
  385. X
  386. X    while (num_active > 0) {                                   /* Do Pass 2. */
  387. X        /* Generate One contour (and update MumActive as needed): */
  388. X    p_cntr = gen_one_contour(p_edges, z_level, &contour_kind, &num_active);
  389. X    put_contour(p_cntr, z_level, x_min, x_max, y_min, y_max,
  390. X                  contour_kind); /* Emit it in requested format. */
  391. X    }
  392. X}
  393. X
  394. X/*
  395. X * Does pass 1, or marks the edges which are active (crosses this z_level)
  396. X * as ACTIVE, and the others as INACTIVE:
  397. X * Returns number of active edges (marked ACTIVE).
  398. X */
  399. Xstatic int update_all_edges(p_edges, z_level)
  400. Xstruct edge_struct *p_edges;
  401. Xdouble z_level;
  402. X{
  403. X    int count = 0;
  404. X
  405. X    while (p_edges) {
  406. X    if (((p_edges -> vertex[0] -> Z >= z_level) &&
  407. X         (p_edges -> vertex[1] -> Z <= z_level)) ||
  408. X        ((p_edges -> vertex[1] -> Z >= z_level) &&
  409. X         (p_edges -> vertex[0] -> Z <= z_level))) {
  410. X        p_edges -> status = ACTIVE;
  411. X        count++;
  412. X    }
  413. X    else p_edges -> status = INACTIVE;
  414. X    p_edges = p_edges -> next;
  415. X    }
  416. X
  417. X    return count;
  418. X}
  419. X
  420. X/*
  421. X * Does pass 2, or find one complete contour out of the triangolation data base:
  422. X * Returns a pointer to the contour (as linked list), contour_kind is set to
  423. X * one of OPEN_CONTOUR, CLOSED_CONTOUR, and num_active is updated.
  424. X */
  425. Xstatic struct cntr_struct *gen_one_contour(p_edges, z_level, contour_kind,
  426. X                                num_active)
  427. Xstruct edge_struct *p_edges;
  428. Xdouble z_level;
  429. Xint *contour_kind, *num_active;
  430. X{
  431. X    struct edge_struct *pe_temp;
  432. X
  433. X    if (test_boundary) {    /* Look for something to start with on boundary: */
  434. X    pe_temp = p_edges;
  435. X    while (pe_temp) {
  436. X        if ((pe_temp -> status == ACTIVE) && (pe_temp -> boundary)) break;
  437. X        pe_temp = pe_temp -> next;
  438. X    }
  439. X    if (!pe_temp) test_boundary = FALSE;/* No more contours on boundary. */
  440. X    else {
  441. X        *contour_kind = OPEN_CONTOUR;
  442. X        return trace_contour(pe_temp, z_level, num_active, *contour_kind);
  443. X    }
  444. X    }
  445. X
  446. X    if (!test_boundary) {        /* Look for something to start with inside: */
  447. X    pe_temp = p_edges;
  448. X    while (pe_temp) {
  449. X        if ((pe_temp -> status == ACTIVE) && (!(pe_temp -> boundary)))
  450. X        break;
  451. X        pe_temp = pe_temp -> next;
  452. X    }
  453. X    if (!pe_temp) {
  454. X        *num_active = 0;
  455. X        return NULL;
  456. X    }
  457. X    else {
  458. X        *contour_kind = CLOSED_CONTOUR;
  459. X        return trace_contour(pe_temp, z_level, num_active, *contour_kind);
  460. X    }
  461. X    }
  462. X    return NULL;             /* We should never be here, but lint... */
  463. X}
  464. X
  465. X/*
  466. X * Search the data base along a contour starts at the edge pe_start until
  467. X * a boundary edge is detected or until we close the loop back to pe_start.
  468. X * Returns a linked list of all the points on the contour
  469. X * Also decreases num_active by the number of points on contour.
  470. X */
  471. Xstatic struct cntr_struct *trace_contour(pe_start, z_level, num_active,
  472. X                                contour_kind)
  473. Xstruct edge_struct *pe_start;
  474. Xdouble z_level;
  475. Xint *num_active, contour_kind;
  476. X{
  477. X    int i, in_middle;       /* If TRUE the z_level is in the middle of edge. */
  478. X    struct cntr_struct *p_cntr, *pc_tail;
  479. X    struct edge_struct *p_edge = pe_start, *p_next_edge;
  480. X    struct poly_struct *p_poly, *PLastpoly = NULL;
  481. X
  482. X    /* Generate the header of the contour - the point on pe_start. */
  483. X    if (contour_kind == OPEN_CONTOUR) pe_start -> status = INACTIVE;
  484. X    (*num_active)--;
  485. X    p_cntr = pc_tail = update_cntr_pt(pe_start, z_level, &in_middle);
  486. X    if (!in_middle) {
  487. X    return NULL;
  488. X    }
  489. X
  490. X    do {
  491. X    /* Find polygon to continue (Not where we came from - PLastpoly): */
  492. X    if (p_edge -> poly[0] == PLastpoly) p_poly = p_edge -> poly[1];
  493. X    else p_poly = p_edge -> poly[0];
  494. X    p_next_edge = NULL;          /* In case of error, remains NULL. */
  495. X    for (i=0; i<3; i++)              /* Test the 3 edges of the polygon: */
  496. X        if (p_poly -> edge[i] != p_edge)
  497. X            if (p_poly -> edge[i] -> status == ACTIVE)
  498. X            p_next_edge = p_poly -> edge[i];
  499. X    if (!p_next_edge) {
  500. X        pc_tail -> next = NULL;
  501. X        free_contour(p_cntr);
  502. X        return NULL;
  503. X    }
  504. X    p_edge = p_next_edge;
  505. X    PLastpoly = p_poly;
  506. X    p_edge -> status = INACTIVE;
  507. X    (*num_active)--;
  508. X    pc_tail -> next = update_cntr_pt(p_edge, z_level, &in_middle);
  509. X    if (!in_middle) {
  510. X        pc_tail -> next = NULL;
  511. X        free_contour(p_cntr);
  512. X        return NULL;
  513. X    }
  514. X        pc_tail = pc_tail -> next;
  515. X    }
  516. X    while ((pe_start != p_edge) && (!p_edge -> boundary));
  517. X    pc_tail -> next = NULL;
  518. X
  519. X    return p_cntr;
  520. X}
  521. X
  522. X/*
  523. X * Allocates one contour location and update it to to correct position
  524. X * according to z_level and edge p_edge. if z_level is found to be at
  525. X * one of the extreme points nothing is allocated (NULL is returned)
  526. X * and in_middle is set to FALSE.
  527. X */
  528. Xstatic struct cntr_struct *update_cntr_pt(p_edge, z_level, in_middle)
  529. Xstruct edge_struct *p_edge;
  530. Xdouble z_level;
  531. Xint *in_middle;
  532. X{
  533. X    double t;
  534. X    struct cntr_struct *p_cntr;
  535. X
  536. X    t = (z_level - p_edge -> vertex[0] -> Z) /
  537. X    (p_edge -> vertex[1] -> Z - p_edge -> vertex[0] -> Z);
  538. X
  539. X    if (fuzzy_equal(t, 1.0) || fuzzy_equal(t, 0.0)) {
  540. X        *in_middle = FALSE;
  541. X        return NULL;
  542. X    }
  543. X    else {
  544. X    *in_middle = TRUE;
  545. X    p_cntr = (struct cntr_struct *) alloc((unsigned long)sizeof(struct cntr_struct),
  546. X                            "contour cntr_struct");
  547. X    p_cntr -> X = p_edge -> vertex[1] -> X * t +
  548. X             p_edge -> vertex[0] -> X * (1-t);
  549. X    p_cntr -> Y = p_edge -> vertex[1] -> Y * t +
  550. X             p_edge -> vertex[0] -> Y * (1-t);
  551. X    return p_cntr;
  552. X    }
  553. X}
  554. X
  555. X/*
  556. X * Simple routine to decide if two real values are equal by simply
  557. X * calculating the relative/absolute error between them (< EPSILON).
  558. X */
  559. Xstatic int fuzzy_equal(x, y)
  560. Xdouble x, y;
  561. X{
  562. X    if (abs(x) > EPSILON)            /* Calculate relative error: */
  563. X        return (abs((x - y) / x) < EPSILON);
  564. X    else                    /* Calculate absolute error: */
  565. X    return (abs(x - y) < EPSILON);
  566. X}
  567. X
  568. X/*
  569. X * Generate the triangles.
  570. X * Returns the lists (vrtxs edges & polys) via pointers to their heads.
  571. X */
  572. Xstatic void gen_triangle(num_isolines, iso_lines, p_polys, p_edges,
  573. X    p_vrts, x_min, y_min, z_min, x_max, y_max, z_max)
  574. Xint num_isolines;
  575. Xstruct iso_curve *iso_lines;
  576. Xstruct poly_struct **p_polys;
  577. Xstruct edge_struct **p_edges;
  578. Xstruct vrtx_struct **p_vrts;
  579. Xdouble *x_min, *y_min, *z_min, *x_max, *y_max, *z_max;
  580. X{
  581. X    int i, grid_x_max = iso_lines->p_count;
  582. X    struct vrtx_struct *p_vrtx1, *p_vrtx2, *pv_temp;
  583. X    struct edge_struct *p_edge1, *p_edge2, *pe_tail1, *pe_tail2, *pe_temp,
  584. X              *p_edge_middle, *pe_m_tail;
  585. X    struct poly_struct *p_poly, *pp_tail;
  586. X
  587. X    *p_polys = NULL;
  588. X    *p_edges = NULL;
  589. X    *p_vrts = NULL;
  590. X    *z_min = INFINITY;
  591. X    *y_min = INFINITY;
  592. X    *x_min = INFINITY;
  593. X    *z_max = -INFINITY;
  594. X    *y_max = -INFINITY;
  595. X    *x_max = -INFINITY;
  596. X
  597. X    /* Read 1st row. */
  598. X    p_vrtx1 = gen_vertices(grid_x_max, iso_lines->points,
  599. X               x_min, y_min, z_min, x_max, y_max, z_max);
  600. X    *p_vrts = p_vrtx1;
  601. X    /* Gen. its edges.*/
  602. X    pe_temp = p_edge1 = gen_edges(grid_x_max, p_vrtx1, &pe_tail1);
  603. X    for (i = 1; i < grid_x_max; i++) {/* Mark one side of edges as boundary. */
  604. X    pe_temp -> poly[1] = NULL;
  605. X    pe_temp = pe_temp -> next;
  606. X    }
  607. X    for (i = 1; i < num_isolines; i++) { /* Read next column and gen. polys. */
  608. X    iso_lines = iso_lines->next;
  609. X        /* Get row into list. */
  610. X        p_vrtx2 = gen_vertices(grid_x_max, iso_lines->points,
  611. X                   x_min, y_min, z_min, x_max, y_max, z_max);
  612. X        /* Generate its edges. */
  613. X        p_edge2 = gen_edges(grid_x_max, p_vrtx2, &pe_tail2);
  614. X    /* Generate edges from one vertex list to the other one: */
  615. X    p_edge_middle = gen_edges_middle(grid_x_max, p_vrtx1, p_vrtx2,
  616. X                                 &pe_m_tail);
  617. X
  618. X    /* Now we can generate the polygons themselves (triangles). */
  619. X    p_poly = gen_polys(grid_x_max, p_edge1, p_edge_middle, p_edge2,
  620. X                                 &pp_tail);
  621. X        pe_tail1 -> next = (*p_edges);      /* Chain new edges to main list. */
  622. X        pe_m_tail -> next = p_edge1;
  623. X    *p_edges = p_edge_middle;
  624. X    pe_tail1 = pe_tail2;
  625. X    p_edge1 = p_edge2;
  626. X
  627. X    pv_temp = p_vrtx2;
  628. X    while (pv_temp -> next) pv_temp = pv_temp -> next;
  629. X    pv_temp -> next = *p_vrts;
  630. X    *p_vrts = p_vrtx1 = p_vrtx2;
  631. X
  632. X        pp_tail -> next = (*p_polys);       /* Chain new polys to main list. */
  633. X    *p_polys = p_poly;
  634. X    }
  635. X
  636. X    pe_temp = p_edge1;
  637. X    for (i = 1; i < grid_x_max; i++) {/* Mark one side of edges as boundary. */
  638. X    pe_temp -> poly[0] = NULL;
  639. X    pe_temp = pe_temp -> next;
  640. X    }
  641. X
  642. X    pe_tail1 -> next = (*p_edges);    /* Chain last edges list to main list. */
  643. X    *p_edges = p_edge1;
  644. X
  645. X    /* Update the boundary flag, saved in each edge, and update indexes: */
  646. X    pe_temp = (*p_edges);
  647. X    i = 1;
  648. X
  649. X    while (pe_temp) {
  650. X    pe_temp -> boundary = (!(pe_temp -> poly[0])) ||
  651. X                  (!(pe_temp -> poly[1]));
  652. X    pe_temp = pe_temp -> next;
  653. X    }
  654. X}
  655. X
  656. X/*
  657. X * Handles grid_x_max 3D points (One row) and generate linked list for them.
  658. X */
  659. Xstatic struct vrtx_struct *gen_vertices(grid_x_max, points,
  660. X                      x_min, y_min, z_min, x_max, y_max, z_max)
  661. Xint grid_x_max;
  662. Xstruct coordinate GPHUGE *points;
  663. Xdouble *x_min, *y_min, *z_min, *x_max, *y_max, *z_max;
  664. X{
  665. X    int i;
  666. X    struct vrtx_struct *p_vrtx, *pv_tail, *pv_temp;
  667. X
  668. X    for (i=0; i<grid_x_max; i++) {/* Get a point and generate the structure. */
  669. X        pv_temp = (struct vrtx_struct *) alloc((unsigned long)sizeof(struct vrtx_struct),
  670. X                        "contour vertex");
  671. X    pv_temp -> X = points[i].x;
  672. X    pv_temp -> Y = points[i].y;
  673. X    pv_temp -> Z = points[i].z;
  674. X
  675. X    if (pv_temp -> X > *x_max) *x_max = pv_temp -> X; /* Update min/max. */
  676. X    if (pv_temp -> Y > *y_max) *y_max = pv_temp -> Y;
  677. X    if (pv_temp -> Z > *z_max) *z_max = pv_temp -> Z;
  678. X    if (pv_temp -> X < *x_min) *x_min = pv_temp -> X;
  679. X    if (pv_temp -> Y < *y_min) *y_min = pv_temp -> Y;
  680. X    if (pv_temp -> Z < *z_min) *z_min = pv_temp -> Z;
  681. X
  682. X    if (i == 0)                              /* First vertex in row: */
  683. X        p_vrtx = pv_tail = pv_temp;
  684. X    else {
  685. X        pv_tail -> next = pv_temp;   /* Stick new record as last one. */
  686. X        pv_tail = pv_tail -> next;    /* And continue to last record. */
  687. X    }
  688. X    }
  689. X    pv_tail -> next = NULL;
  690. X
  691. X    return p_vrtx;
  692. X}
  693. X
  694. X/*
  695. X * Combines N vertices in pair to form N-1 edges.
  696. X * Returns pointer to the edge list (pe_tail will point on last edge in list).
  697. X */
  698. Xstatic struct edge_struct *gen_edges(grid_x_max, p_vrtx, pe_tail)
  699. Xint grid_x_max;
  700. Xstruct vrtx_struct *p_vrtx;
  701. Xstruct edge_struct **pe_tail;
  702. X{
  703. X    int i;
  704. X    struct edge_struct *p_edge, *pe_temp;
  705. X
  706. X    for (i=0; i<grid_x_max-1; i++) {         /* Generate grid_x_max-1 edges: */
  707. X    pe_temp = (struct edge_struct *) alloc((unsigned long)sizeof(struct edge_struct),
  708. X                        "contour edge");
  709. X    pe_temp -> vertex[0] = p_vrtx;              /* First vertex of edge. */
  710. X    p_vrtx = p_vrtx -> next;                     /* Skip to next vertex. */
  711. X    pe_temp -> vertex[1] = p_vrtx;             /* Second vertex of edge. */
  712. X        if (i == 0)                                    /* First edge in row: */
  713. X        p_edge = (*pe_tail) = pe_temp;
  714. X    else {
  715. X        (*pe_tail) -> next = pe_temp;   /* Stick new record as last one. */
  716. X        *pe_tail = (*pe_tail) -> next;   /* And continue to last record. */
  717. X     }
  718. X    }
  719. X    (*pe_tail) -> next = NULL;
  720. X
  721. X    return p_edge;
  722. X}
  723. X
  724. X/*
  725. X * Combines 2 lists of N vertices each into edge list:
  726. X * The dots (.) are the vertices list, and the              .  .  .  .
  727. X *  edges generated are alternations of vertical edges      |\ |\ |\ |
  728. X *  (|) and diagonal ones (\).                              | \| \| \|
  729. X *  A pointer to edge list (alternate | , \) is returned    .  .  .  .
  730. X * Note this list will have (2*grid_x_max-1) edges (pe_tail points on last
  731. X * record).
  732. X */
  733. Xstatic struct edge_struct *gen_edges_middle(grid_x_max, p_vrtx1, p_vrtx2,
  734. X                                pe_tail)
  735. Xint grid_x_max;
  736. Xstruct vrtx_struct *p_vrtx1, *p_vrtx2;
  737. Xstruct edge_struct **pe_tail;
  738. X{
  739. X    int i;
  740. X    struct edge_struct *p_edge, *pe_temp;
  741. X
  742. X    /* Gen first (|). */
  743. X    pe_temp = (struct edge_struct *) alloc((unsigned long)sizeof(struct edge_struct),
  744. X                            "contour edge");
  745. X    pe_temp -> vertex[0] = p_vrtx2;                 /* First vertex of edge. */
  746. X    pe_temp -> vertex[1] = p_vrtx1;                /* Second vertex of edge. */
  747. X    p_edge = (*pe_tail) = pe_temp;
  748. X
  749. X    /* Advance in vrtx list grid_x_max-1 times, and gen. 2 edges /| for each.*/
  750. X    for (i=0; i<grid_x_max-1; i++) {
  751. X    /* The / edge. */
  752. X    pe_temp = (struct edge_struct *) alloc((unsigned long)sizeof(struct edge_struct),
  753. X                            "contour edge");
  754. X    pe_temp -> vertex[0] = p_vrtx1;             /* First vertex of edge. */
  755. X    pe_temp -> vertex[1] = p_vrtx2 -> next;    /* Second vertex of edge. */
  756. X        (*pe_tail) -> next = pe_temp;       /* Stick new record as last one. */
  757. X    *pe_tail = (*pe_tail) -> next;       /* And continue to last record. */
  758. X
  759. X    /* The | edge. */
  760. X    pe_temp = (struct edge_struct *) alloc((unsigned long)sizeof(struct edge_struct),
  761. X                            "contour edge");
  762. X    pe_temp -> vertex[0] = p_vrtx2 -> next;     /* First vertex of edge. */
  763. X    pe_temp -> vertex[1] = p_vrtx1 -> next;    /* Second vertex of edge. */
  764. X        (*pe_tail) -> next = pe_temp;       /* Stick new record as last one. */
  765. X    *pe_tail = (*pe_tail) -> next;       /* And continue to last record. */
  766. X
  767. X        p_vrtx1 = p_vrtx1 -> next;   /* Skip to next vertices in both lists. */
  768. X        p_vrtx2 = p_vrtx2 -> next;
  769. X    }
  770. X    (*pe_tail) -> next = NULL;
  771. X
  772. X    return p_edge;
  773. X}
  774. X
  775. X/*
  776. X * Combines 3 lists of edges into triangles:
  777. X * 1. p_edge1: Top horizontal edge list:        -----------------------
  778. X * 2. p_edge_middge: middle edge list:         |\  |\  |\  |\  |\  |\  |
  779. X *                                             |  \|  \|  \|  \|  \|  \|
  780. X * 3. p_edge2: Bottom horizontal edge list:     -----------------------
  781. X * Note that p_edge1/2 lists has grid_x_max-1 edges, while p_edge_middle has
  782. X * (2*grid_x_max-1) edges.
  783. X * The routine simple scans the two list    Upper 1         Lower
  784. X * and generate two triangle upper one        ----         | \
  785. X * and lower one from the lists:             0\   |2      0|   \1
  786. X * (Nums. are edges order in polys)             \ |         ----
  787. X * The routine returns a pointer to a                         2
  788. X * polygon list (pp_tail points on last polygon).          1
  789. X *                                                   -----------
  790. X * In addition, the edge lists are updated -        | \   0     |
  791. X * each edge has two pointers on the two            |   \       |
  792. X * (one active if boundary) polygons which         0|1   0\1   0|1
  793. X * uses it. These two pointer to polygons           |       \   |
  794. X * are named: poly[0], poly[1]. The diagram         |    1    \ |
  795. X * on the right show how they are used for the       -----------
  796. X * upper and lower polygons.                             0
  797. X */
  798. Xstatic struct poly_struct *gen_polys(grid_x_max, p_edge1, p_edge_middle,
  799. X                            p_edge2, pp_tail)
  800. Xint grid_x_max;
  801. Xstruct edge_struct *p_edge1, *p_edge_middle, *p_edge2;
  802. Xstruct poly_struct **pp_tail;
  803. X{
  804. X    int i;
  805. X    struct poly_struct *p_poly, *pp_temp;
  806. X
  807. X    p_edge_middle -> poly[0] = NULL;                /* Its boundary! */
  808. X
  809. X    /* Advance in vrtx list grid_x_max-1 times, and gen. 2 polys for each. */
  810. X    for (i=0; i<grid_x_max-1; i++) {
  811. X    /* The Upper. */
  812. X    pp_temp = (struct poly_struct *) alloc((unsigned long)sizeof(struct poly_struct),
  813. X                            "contour poly");
  814. X    /* Now update polys about its edges, and edges about the polygon. */
  815. X    pp_temp -> edge[0] = p_edge_middle -> next;
  816. X    p_edge_middle -> next -> poly[1] = pp_temp;
  817. X    pp_temp -> edge[1] = p_edge1;
  818. X    p_edge1 -> poly[0] = pp_temp;
  819. X    pp_temp -> edge[2] = p_edge_middle -> next -> next;
  820. X    p_edge_middle -> next -> next -> poly[0] = pp_temp;
  821. X    if (i == 0)                   /* Its first one in list: */
  822. X        p_poly = (*pp_tail) = pp_temp;
  823. X    else {
  824. X        (*pp_tail) -> next = pp_temp;
  825. X        *pp_tail = (*pp_tail) -> next;
  826. X    }
  827. X
  828. X    /* The Lower. */
  829. X    pp_temp = (struct poly_struct *) alloc((unsigned long)sizeof(struct poly_struct),
  830. X                            "contour poly");
  831. X    /* Now update polys about its edges, and edges about the polygon. */
  832. X    pp_temp -> edge[0] = p_edge_middle;
  833. X    p_edge_middle -> poly[1] = pp_temp;
  834. X    pp_temp -> edge[1] = p_edge_middle -> next;
  835. X    p_edge_middle -> next -> poly[0] = pp_temp;
  836. X    pp_temp -> edge[2] = p_edge2;
  837. X    p_edge2 -> poly[1] = pp_temp;
  838. X    (*pp_tail) -> next = pp_temp;
  839. X    *pp_tail = (*pp_tail) -> next;
  840. X
  841. X        p_edge1 = p_edge1 -> next;
  842. X        p_edge2 = p_edge2 -> next;
  843. X        p_edge_middle = p_edge_middle -> next -> next;
  844. X    }
  845. X    p_edge_middle -> poly[1] = NULL;                /* Its boundary! */
  846. X    (*pp_tail) -> next = NULL;
  847. X
  848. X    return p_poly;
  849. X}
  850. X
  851. X/*
  852. X * Calls the (hopefully) desired interpolation/approximation routine.
  853. X */
  854. Xstatic void put_contour(p_cntr, z_level, x_min, x_max, y_min, y_max, contr_kind)
  855. Xstruct cntr_struct *p_cntr;
  856. Xdouble z_level, x_min, x_max, y_min, y_max;
  857. Xint contr_kind;
  858. X{
  859. X    if (!p_cntr) return;            /* Nothing to do if it is empty contour. */
  860. X
  861. X    switch (interp_kind) {
  862. X    case INTERP_NOTHING:              /* No interpolation/approximation. */
  863. X        put_contour_nothing(p_cntr);
  864. X        break;
  865. X    case INTERP_CUBIC:                    /* Cubic spline interpolation. */
  866. X        put_contour_cubic(p_cntr, z_level, x_min, x_max, y_min, y_max,
  867. X                                contr_kind);
  868. X        break;
  869. X    case APPROX_BSPLINE:                       /* Bspline approximation. */
  870. X        put_contour_bspline(p_cntr, z_level, x_min, x_max, y_min, y_max,
  871. X                                    contr_kind);
  872. X        break;
  873. X    }
  874. X
  875. X    free_contour(p_cntr);
  876. X}
  877. X
  878. X/*
  879. X * Simply puts contour coordinates in order with no interpolation or
  880. X * approximation.
  881. X */
  882. Xstatic put_contour_nothing(p_cntr)
  883. Xstruct cntr_struct *p_cntr;
  884. X{
  885. X    while (p_cntr) {
  886. X    add_cntr_point(p_cntr -> X, p_cntr -> Y);
  887. X    p_cntr = p_cntr -> next;
  888. X    }
  889. X    end_crnt_cntr();
  890. X}
  891. X
  892. X/*
  893. X * Find Complete Cubic Spline Interpolation.
  894. X */
  895. Xstatic put_contour_cubic(p_cntr, z_level, x_min, x_max, y_min, y_max,
  896. X                                 contr_kind)
  897. Xstruct cntr_struct *p_cntr;
  898. Xdouble z_level, x_min, x_max, y_min, y_max;
  899. Xint contr_kind;
  900. X{
  901. X    int num_pts, i;
  902. X    double tx1, ty1, tx2, ty2;                    /* Tangents at end points. */
  903. X    struct cntr_struct *pc_temp;
  904. X
  905. X    num_pts = count_contour(p_cntr);         /* Number of points in contour. */
  906. X
  907. X    if (num_pts > 2) {  /* Take into account 3 points in tangent estimation. */
  908. X    calc_tangent(3, p_cntr -> X, p_cntr -> next -> X,
  909. X            p_cntr -> next -> next -> X,
  910. X            p_cntr -> Y, p_cntr -> next -> Y,
  911. X            p_cntr -> next -> next -> Y, &tx1, &ty1);
  912. X    pc_temp = p_cntr;
  913. X    for (i=3; i<num_pts; i++) pc_temp = pc_temp -> next;/* Go to the end.*/
  914. X    calc_tangent(3, pc_temp -> next -> next -> X,
  915. X             pc_temp -> next -> X, pc_temp -> X,
  916. X            pc_temp -> next -> next -> Y,
  917. X            pc_temp -> next -> Y, pc_temp -> Y, &tx2, &ty2);
  918. X        tx2 = (-tx2);   /* Inverse the vector as we need opposite direction. */
  919. X        ty2 = (-ty2);
  920. X    }
  921. X    /* If following (num_pts > 1) is TRUE then exactly 2 points in contour.  */
  922. X    else if (num_pts > 1) {/* Take into account 2 points in tangent estimat. */
  923. X    calc_tangent(2, p_cntr -> X, p_cntr -> next -> X, 0.0,
  924. X            p_cntr -> Y, p_cntr -> next -> Y, 0.0, &tx1, &ty1);
  925. X    calc_tangent(2, p_cntr -> next -> X, p_cntr -> X, 0.0,
  926. X            p_cntr -> next -> Y, p_cntr -> Y, 0.0, &tx2, &ty2);
  927. X        tx2 = (-tx2);   /* Inverse the vector as we need opposite direction. */
  928. X        ty2 = (-ty2);
  929. X    }
  930. X    else return(0);            /* Only one point (???) - ignore it. */
  931. X
  932. X    switch (contr_kind) {
  933. X    case OPEN_CONTOUR:
  934. X        break;
  935. X    case CLOSED_CONTOUR:
  936. X        tx1 = tx2 = (tx1 + tx2) / 2.0;         /* Make tangents equal. */
  937. X        ty1 = ty2 = (ty1 + ty2) / 2.0;
  938. X        break;
  939. X    }
  940. X    complete_spline_interp(p_cntr, num_pts, 0.0, 1.0, tx1, ty1, tx2, ty2);
  941. X    end_crnt_cntr();
  942. X}
  943. X
  944. X/*
  945. X * Find Bspline approximation for this data set.
  946. X * Uses global variable num_approx_pts to determine number of samples per
  947. X * interval, where the knot vector intervals are assumed to be uniform, and
  948. X * Global variable bspline_order for the order of Bspline to use.
  949. X */
  950. Xstatic put_contour_bspline(p_cntr, z_level, x_min, x_max, y_min, y_max,
  951. X                                contr_kind)
  952. Xstruct cntr_struct *p_cntr;
  953. Xdouble z_level, x_min, x_max,  y_min, y_max;
  954. Xint contr_kind;
  955. X{
  956. X    int num_pts, order = bspline_order;
  957. X
  958. X    num_pts = count_contour(p_cntr);         /* Number of points in contour. */
  959. X    if (num_pts < 2) return(0);     /* Can't do nothing if empty or one points! */
  960. X    /* Order must be less than number of points in curve - fix it if needed. */
  961. X    if (order > num_pts - 1) order = num_pts - 1;
  962. X
  963. X    gen_bspline_approx(p_cntr, num_pts, order, contr_kind);
  964. X    end_crnt_cntr();
  965. X}
  966. X
  967. X/*
  968. X * Estimate the tangents according to the n last points where n might be
  969. X * 2 or 3 (if 2 onlt x1, x2).
  970. X */
  971. Xstatic calc_tangent(n, x1, x2, x3, y1, y2, y3, tx, ty)
  972. Xint n;
  973. Xdouble x1, x2, x3, y1, y2, y3, *tx, *ty;
  974. X{
  975. X    double v1[2], v2[2], v1_magnitude, v2_magnitude;
  976. X
  977. X    switch (n) {
  978. X    case 2:
  979. X        *tx = (x2 - x1) * 0.3;
  980. X        *ty = (y2 - y1) * 0.3;
  981. X        break;
  982. X    case 3:
  983. X        v1[0] = x2 - x1;   v1[1] = y2 - y1;
  984. X        v2[0] = x3 - x2;   v2[1] = y3 - y2;
  985. X        v1_magnitude = sqrt(sqr(v1[0]) + sqr(v1[1]));
  986. X        v2_magnitude = sqrt(sqr(v2[0]) + sqr(v2[1]));
  987. X        *tx = (v1[0] / v1_magnitude) - (v2[0] / v2_magnitude) * 0.1;
  988. X        *tx *= v1_magnitude * 0.1;  /* Make tangent less than magnitude. */
  989. X        *ty = (v1[1] / v1_magnitude) - (v2[1] / v2_magnitude) * 0.1;
  990. X        *ty *= v1_magnitude * 0.1;  /* Make tangent less than magnitude. */
  991. X        break;
  992. X    default:                       /* Should not happen! */
  993. X        (*ty) = 0.1;
  994. X        *tx = 0.1;
  995. X        break;
  996. X    }
  997. X}
  998. X
  999. X/*
  1000. X * Free all elements in the contour list.
  1001. X */
  1002. Xstatic void free_contour(p_cntr)
  1003. Xstruct cntr_struct *p_cntr;
  1004. X{
  1005. X    struct cntr_struct *pc_temp;
  1006. X
  1007. X    while (p_cntr) {
  1008. X    pc_temp = p_cntr;
  1009. X    p_cntr = p_cntr -> next;
  1010. X    free((char *) pc_temp);
  1011. X    }
  1012. X}
  1013. X
  1014. X/*
  1015. X * Counts number of points in contour.
  1016. X */
  1017. Xstatic int count_contour(p_cntr)
  1018. Xstruct cntr_struct *p_cntr;
  1019. X{
  1020. X    int count = 0;
  1021. X
  1022. X    while (p_cntr) {
  1023. X    count++;
  1024. X    p_cntr = p_cntr -> next;
  1025. X    }
  1026. X    return count;
  1027. X}
  1028. X
  1029. X/*
  1030. X * Interpolate given point list (defined via p_cntr) using Complete
  1031. X * Spline interpolation.
  1032. X */
  1033. Xstatic complete_spline_interp(p_cntr, n, t_min, t_max, tx1, ty1, tx2, ty2)
  1034. Xstruct cntr_struct *p_cntr;
  1035. Xint n;
  1036. Xdouble t_min, t_max, tx1, ty1, tx2, ty2;
  1037. X{
  1038. X    double dt, *tangents_x, *tangents_y;
  1039. X    int i;
  1040. X
  1041. X    tangents_x = (double *) alloc((unsigned long) (sizeof(double) * n),
  1042. X                        "contour c_s_intr");
  1043. X    tangents_y = (double *) alloc((unsigned long) (sizeof(double) * n),
  1044. X                        "contour c_s_intr");
  1045. X
  1046. X    if (n > 1) prepare_spline_interp(tangents_x, tangents_y, p_cntr, n,
  1047. X                    t_min, t_max, tx1, ty1, tx2, ty2);
  1048. X    else {
  1049. X    free((char *) tangents_x);
  1050. X    free((char *) tangents_y);
  1051. X    return(0);
  1052. X    }
  1053. X
  1054. X    dt = (t_max-t_min)/(n-1);
  1055. X
  1056. X    add_cntr_point(p_cntr -> X, p_cntr -> Y);           /* First point. */
  1057. X
  1058. X    for (i=0; i<n-1; i++) {
  1059. X        hermit_interp(p_cntr -> X, p_cntr -> Y,
  1060. X                     tangents_x[i], tangents_y[i],
  1061. X             p_cntr -> next -> X, p_cntr -> next -> Y,
  1062. X                     tangents_x[i+1], tangents_y[i+1], dt);
  1063. X
  1064. X        p_cntr = p_cntr -> next;
  1065. X    }
  1066. X
  1067. X    free((char *) tangents_x);
  1068. X    free((char *) tangents_y);
  1069. X}
  1070. X
  1071. X/*
  1072. X * Routine to calculate intermidiate value of the Hermit Blending function:
  1073. X * This routine should be called only ONCE at the beginning of the program.
  1074. X */
  1075. Xstatic calc_hermit_table()
  1076. X{
  1077. X    int i;
  1078. X    double t, dt;
  1079. X
  1080. X    hermit_table = (table_entry *) alloc ((unsigned long) (sizeof(table_entry) *
  1081. X                        (num_approx_pts + 1)),
  1082. X                        "contour hermit table");
  1083. X    t = 0;
  1084. X    dt = 1.0/num_approx_pts;
  1085. X    for (i=0; i<=num_approx_pts; i++) {
  1086. X        hermit_table[i][0] = (t-1)*(t-1)*(2*t+1);             /* h00. */
  1087. X        hermit_table[i][1] = t*t*(-2*t+3);                 /* h10. */
  1088. X        hermit_table[i][2] = t*(t-1)*(t-1);                 /* h01. */
  1089. X        hermit_table[i][3] = t*t*(t-1);                     /* h11. */
  1090. X        t = t + dt;
  1091. X    }
  1092. X}
  1093. X
  1094. X/*
  1095. X * Routine to generate an hermit interpolation between two points given as
  1096. X * two InterpStruct structures. Assume hermit_table is already calculated.
  1097. X * Currently the points generated are printed to stdout as two reals (X, Y).
  1098. X */
  1099. Xstatic hermit_interp(x1, y1, tx1, ty1, x2, y2, tx2, ty2, dt)
  1100. Xdouble x1, y1, tx1, ty1, x2, y2, tx2, ty2, dt;
  1101. X{
  1102. X    int i;
  1103. X    double x, y, vec_size, tang_size;
  1104. X
  1105. X    tx1 *= dt;  ty1 *= dt; /* Normalize the tangents according to param. t.  */
  1106. X    tx2 *= dt;  ty2 *= dt;
  1107. X
  1108. X    /* Normalize the tangents so that their magnitude will be 1/3 of the     */
  1109. X    /* segment length. This tumb rule guaranteed no cusps or loops!          */
  1110. X    /* Note that this normalization keeps continuity to be G1 (but not C1).  */
  1111. X    vec_size = sqrt(sqr(x1 - x2) + sqr(y2 - y1));
  1112. X    tang_size = sqrt(sqr(tx1) + sqr(ty1));                  /* Normalize T1. */
  1113. X    if (tang_size * 3 > vec_size) {
  1114. X    tx1 *= vec_size / (tang_size * 3);
  1115. X    ty1 *= vec_size / (tang_size * 3);
  1116. X    }
  1117. X    tang_size = sqrt(sqr(tx2) + sqr(ty2));                  /* Normalize T2. */
  1118. X    if (tang_size * 3 > vec_size) {
  1119. X    tx2 *= vec_size / (tang_size * 3);
  1120. X    ty2 *= vec_size / (tang_size * 3);
  1121. X    }
  1122. X
  1123. X    for (i=1; i<=num_approx_pts; i++) {      /* Note we start from 1 - first */
  1124. X        x = hermit_table[i][0] * x1 +       /* point is not printed as it is */
  1125. X            hermit_table[i][1] * x2 +   /* redundent (last on last section). */
  1126. X            hermit_table[i][2] * tx1 +
  1127. X            hermit_table[i][3] * tx2;
  1128. X        y = hermit_table[i][0] * y1 +
  1129. X            hermit_table[i][1] * y2 +
  1130. X            hermit_table[i][2] * ty1 +
  1131. X            hermit_table[i][3] * ty2;
  1132. X    add_cntr_point(x, y);
  1133. X    }
  1134. X}
  1135. X
  1136. X/*
  1137. X * Routine to Set up the 3*N mat for solve_tri_diag routine used in the
  1138. X * Complete Spline Interpolation. Returns TRUE of calc O.K.
  1139. X * Gets the points list in p_cntr (Of length n) and with tangent vectors tx1,
  1140. X * ty1 at starting point and tx2, ty2 and end point.
  1141. X */
  1142. Xstatic prepare_spline_interp(tangents_x, tangents_y, p_cntr, n, t_min, t_max,
  1143. X               tx1, ty1, tx2, ty2)
  1144. Xdouble tangents_x[], tangents_y[];
  1145. Xstruct cntr_struct *p_cntr;
  1146. Xint n;
  1147. Xdouble t_min, t_max, tx1, ty1, tx2, ty2;
  1148. X{
  1149. X    int i;
  1150. X    double *r, t, dt;
  1151. X    tri_diag *m;           /* The tri-diagonal matrix is saved here. */
  1152. X    struct cntr_struct *p;
  1153. X
  1154. X    m = (tri_diag *) alloc((unsigned long) (sizeof(tri_diag) * n),
  1155. X                        "contour tri_diag");
  1156. X    r = (double *) alloc((unsigned long) (sizeof(double) * n),
  1157. X                        "contour tri_diag2");
  1158. X    n--;
  1159. X
  1160. X    p = p_cntr;
  1161. X    m[0][0] = 0.0;    m[0][1] = 1.0;    m[0][2] = 0.0;
  1162. X    m[n][0] = 0.0;    m[n][1] = 1.0;    m[n][2] = 0.0;
  1163. X    r[0] = tx1;                           /* Set start tangent. */
  1164. X    r[n] = tx2;                         /* Set end tangent. */
  1165. X    t = t_min;
  1166. X    dt = (t_max-t_min)/n;
  1167. X    for (i=1; i<n; i++) {
  1168. X       t = t + dt;
  1169. X       m[i][0] = dt;
  1170. X       m[i][2] = dt;
  1171. X       m[i][1] = 2 * (m[i][0] + m[i][2]);
  1172. X       r[i] = m[i][0] * ((p -> next -> X) - (p -> X)) / m[i][2]
  1173. X            + m[i][2] * ((p -> next -> next -> X) - 
  1174. X                         (p -> next -> X)) / m[i][0];
  1175. X       r[i] *= 3.0;
  1176. X       p = p -> next;
  1177. X    }
  1178. X
  1179. X    if (!solve_tri_diag(m, r, tangents_x, n+1)) { /* Find the X(t) tangents. */
  1180. X        free((char *) m);
  1181. X        free((char *) r);
  1182. X    int_error("Cannt interpolate X using complete splines", NO_CARET);
  1183. X    }
  1184. X
  1185. X    p = p_cntr;
  1186. X    m[0][0] = 0.0;    m[0][1] = 1.0;    m[0][2] = 0.0;
  1187. X    m[n][0] = 0.0;    m[n][1] = 1.0;    m[n][2] = 0.0;
  1188. X    r[0] = ty1;                           /* Set start tangent. */
  1189. X    r[n] = ty2;                         /* Set end tangent. */
  1190. X    t = t_min;
  1191. X    dt = (t_max-t_min)/n;
  1192. X    for (i=1; i<n; i++) {
  1193. X       t = t + dt;
  1194. X       m[i][0] = dt;
  1195. X       m[i][2] = dt;
  1196. X       m[i][1] = 2 * (m[i][0] + m[i][2]);
  1197. X       r[i] = m[i][0] * ((p -> next -> Y) - (p -> Y)) / m[i][2]
  1198. X            + m[i][2] * ((p -> next -> next -> Y) -
  1199. X                         (p -> next -> Y)) / m[i][0];
  1200. X       r[i] *= 3.0;
  1201. X       p = p -> next;
  1202. X    }
  1203. X
  1204. X    if (!solve_tri_diag(m, r, tangents_y, n+1)) { /* Find the Y(t) tangents. */
  1205. X        free((char *) m);
  1206. X        free((char *) r);
  1207. X    int_error("Cannt interpolate Y using complete splines", NO_CARET);
  1208. X    }
  1209. X    free((char *) m);
  1210. X    free((char *) r);
  1211. X}
  1212. X
  1213. X/*
  1214. X * Solve tri diagonal linear system equation. The tri diagonal matrix is
  1215. X * defined via matrix M, right side is r, and solution X i.e. M * X = R.
  1216. X * Size of system given in n. Return TRUE if solution exist.
  1217. X */
  1218. Xstatic int solve_tri_diag(m, r, x, n)
  1219. Xtri_diag m[];
  1220. Xdouble r[], x[];
  1221. Xint n;
  1222. X{
  1223. X    int i;
  1224. X    double t;
  1225. X
  1226. X    for (i=1; i<n; i++) {   /* Eliminate element m[i][i-1] (lower diagonal). */
  1227. X    if (m[i-1][1] == 0) return FALSE;
  1228. X    t = m[i][0] / m[i-1][1];        /* Find ratio between the two lines. */
  1229. X    m[i][0] = m[i][0] - m[i-1][1] * t;
  1230. X    m[i][1] = m[i][1] - m[i-1][2] * t;
  1231. X    r[i] = r[i] - r[i-1] * t;
  1232. X    }
  1233. X    /* Now do back subtitution - update the solution vector X: */
  1234. X    if (m[n-1][1] == 0) return FALSE;
  1235. X    x[n-1] = r[n-1] / m[n-1][1];               /* Find last element. */
  1236. X    for (i=n-2; i>=0; i--) {
  1237. X    if (m[i][1] == 0) return FALSE;
  1238. X    x[i] = (r[i] - x[i+1] * m[i][2]) / m[i][1];
  1239. X    }
  1240. X    return TRUE;
  1241. X}
  1242. X
  1243. X/*
  1244. X * Generate a Bspline curve defined by all the points given in linked list p:
  1245. X * Algorithm: using deBoor algorithm
  1246. X * Note: if Curvekind is OPEN_CONTOUR than Open end knot vector is assumed,
  1247. X *       else (CLOSED_CONTOUR) Float end knot vector is assumed.
  1248. X * It is assumed that num_of_points is at list 2, and order of Bspline is less
  1249. X * than num_of_points!
  1250. X */
  1251. Xstatic gen_bspline_approx(p_cntr, num_of_points, order, contour_kind)
  1252. Xstruct cntr_struct *p_cntr;
  1253. Xint num_of_points, order, contour_kind;
  1254. X{
  1255. X    int i, knot_index = 0, pts_count = 1;
  1256. X    double dt, t, next_t, t_min, t_max, x, y;
  1257. X    struct cntr_struct *pc_temp = p_cntr, *pc_tail;
  1258. X
  1259. X    /* If the contour is Closed one we must update few things:               */
  1260. X    /* 1. Make the list temporary circular, so we can close the contour.     */
  1261. X    /* 2. Update num_of_points - increase it by "order-1" so contour will be */
  1262. X    /*    closed. This will evaluate order more sections to close it!        */
  1263. X    if (contour_kind == CLOSED_CONTOUR) {
  1264. X    pc_tail = p_cntr;
  1265. X    while (pc_tail -> next) pc_tail = pc_tail -> next;/* Find last point.*/
  1266. X    pc_tail -> next = p_cntr;   /* Close contour list - make it circular.*/
  1267. X    num_of_points += order;
  1268. X    }
  1269. X
  1270. X    /* Find first (t_min) and last (t_max) t value to eval: */
  1271. X    t = t_min = fetch_knot(contour_kind, num_of_points, order, order);
  1272. X    t_max = fetch_knot(contour_kind, num_of_points, order, num_of_points);
  1273. X    next_t = t_min + 1.0;
  1274. X    knot_index = order;
  1275. X    dt = 1.0/num_approx_pts;            /* Number of points per one section. */
  1276. X
  1277. X
  1278. X    while (t<t_max) {
  1279. X    if (t > next_t) {
  1280. X        pc_temp = pc_temp -> next;     /* Next order ctrl. pt. to blend. */
  1281. X            knot_index++;
  1282. X        next_t += 1.0;
  1283. X    }
  1284. X        eval_bspline(t, pc_temp, num_of_points, order, knot_index,
  1285. X                        contour_kind, &x, &y);   /* Next pt. */
  1286. X    add_cntr_point(x, y);
  1287. X    pts_count++;
  1288. X    /* As we might have some real number round off problems we must      */
  1289. X    /* test if we dont produce too many points here...                   */
  1290. X    if (pts_count + 1 == num_approx_pts * (num_of_points - order) + 1)
  1291. X            break;
  1292. X        t += dt;
  1293. X    }
  1294. X
  1295. X    eval_bspline(t_max - EPSILON, pc_temp, num_of_points, order, knot_index,
  1296. X        contour_kind, &x, &y);
  1297. X    /* If from round off errors we need more than one last point: */
  1298. X    for (i=pts_count; i<num_approx_pts * (num_of_points - order) + 1; i++)
  1299. X    add_cntr_point(x, y);                /* Complete the contour. */
  1300. X
  1301. X    if (contour_kind == CLOSED_CONTOUR)     /* Update list - un-circular it. */
  1302. X    pc_tail -> next = NULL;
  1303. X}
  1304. X
  1305. X/*
  1306. X * The recursive routine to evaluate the B-spline value at point t using
  1307. X * knot vector PKList, and the control points Pdtemp. Returns x, y after the
  1308. X * division by the weight w. Note that Pdtemp points on the first control
  1309. X * point to blend with. The B-spline is of order order.
  1310. X */
  1311. Xstatic eval_bspline(t, p_cntr, num_of_points, order, j, contour_kind, x, y)
  1312. Xdouble t;
  1313. Xstruct cntr_struct *p_cntr;
  1314. Xint num_of_points, order, j, contour_kind;
  1315. Xdouble *x, *y;
  1316. X{
  1317. X    int i, p;
  1318. X    double ti, tikp, *dx, *dy;      /* Copy p_cntr into it to make it faster. */
  1319. X
  1320. X    dx = (double *) alloc((unsigned long) (sizeof(double) * (order + j)),
  1321. X                        "contour b_spline");
  1322. X    dy = (double *) alloc((unsigned long) (sizeof(double) * (order + j)),
  1323. X                        "contour b_spline");
  1324. X    /* Set the dx/dy - [0] iteration step, control points (p==0 iterat.): */
  1325. X    for (i=j-order; i<=j; i++) {
  1326. X        dx[i] = p_cntr -> X;
  1327. X        dy[i] = p_cntr -> Y;
  1328. X        p_cntr = p_cntr -> next;
  1329. X    }
  1330. X
  1331. X    for (p=1; p<=order; p++) {        /* Iteration (b-spline level) counter. */
  1332. X    for (i=j; i>=j-order+p; i--) {           /* Control points indexing. */
  1333. X            ti = fetch_knot(contour_kind, num_of_points, order, i);
  1334. X            tikp = fetch_knot(contour_kind, num_of_points, order, i+order+1-p);
  1335. X        if (ti == tikp) {   /* Should not be a problems but how knows... */
  1336. X        }
  1337. X        else {
  1338. X        dx[i] = dx[i] * (t - ti)/(tikp-ti) +         /* Calculate x. */
  1339. X            dx[i-1] * (tikp-t)/(tikp-ti);
  1340. X        dy[i] = dy[i] * (t - ti)/(tikp-ti) +         /* Calculate y. */
  1341. X            dy[i-1] * (tikp-t)/(tikp-ti);
  1342. X        }
  1343. X    }
  1344. X    }
  1345. X    *x = dx[j]; *y = dy[j];
  1346. X    free((char *) dx);
  1347. X    free((char *) dy);
  1348. X}
  1349. X
  1350. X/*
  1351. X * Routine to get the i knot from uniform knot vector. The knot vector
  1352. X * might be float (Knot(i) = i) or open (where the first and last "order"
  1353. X * knots are equal). contour_kind determines knot kind - OPEN_CONTOUR means
  1354. X * open knot vector, and CLOSED_CONTOUR selects float knot vector.
  1355. X * Note the knot vector is not exist and this routine simulates it existance
  1356. X * Also note the indexes for the knot vector starts from 0.
  1357. X */
  1358. Xstatic double fetch_knot(contour_kind, num_of_points, order, i)
  1359. Xint contour_kind, num_of_points, order, i;
  1360. X{
  1361. X    switch (contour_kind) {
  1362. X    case OPEN_CONTOUR:
  1363. X        if (i <= order) return 0.0;
  1364. X        else if (i <= num_of_points) return (double) (i - order);
  1365. X         else return (double) (num_of_points - order);
  1366. X    case CLOSED_CONTOUR:
  1367. X        return (double) i;
  1368. X    default: /* Should never happen */
  1369. X        return 1.0;
  1370. X    }
  1371. X#ifdef sequent
  1372. X    return 1.0;
  1373. X#endif
  1374. X}
  1375. END_OF_FILE
  1376.   if test 43000 -ne `wc -c <'gnuplot/contour.c'`; then
  1377.     echo shar: \"'gnuplot/contour.c'\" unpacked with wrong size!
  1378.   fi
  1379.   # end of 'gnuplot/contour.c'
  1380. fi
  1381. if test -f 'gnuplot/gplt_x11.c' -a "${1}" != "-c" ; then 
  1382.   echo shar: Will not clobber existing file \"'gnuplot/gplt_x11.c'\"
  1383. else
  1384.   echo shar: Extracting \"'gnuplot/gplt_x11.c'\" \(30922 characters\)
  1385.   sed "s/^X//" >'gnuplot/gplt_x11.c' <<'END_OF_FILE'
  1386. X#ifndef lint
  1387. Xstatic char *RCSid = "$Id: gplt_x11.c%v 3.50.1.9 1993/08/05 05:38:59 woo Exp $";
  1388. X#endif
  1389. X
  1390. X
  1391. X/*-----------------------------------------------------------------------------
  1392. X *   gnuplot_x11 - X11 outboard terminal driver for gnuplot 3.3
  1393. X *
  1394. X *   Requires installation of companion inboard x11 driver in gnuplot/term.c
  1395. X *
  1396. X *   Acknowledgements: 
  1397. X *      Chris Peterson (MIT)
  1398. X *      Dana Chee (Bellcore) 
  1399. X *      Arthur Smith (Cornell)
  1400. X *      Hendri Hondorp (University of Twente, The Netherlands)
  1401. X *      Bill Kucharski (Solbourne)
  1402. X *      Charlie Kline (University of Illinois)
  1403. X *      Yehavi Bourvine (Hebrew University of Jerusalem, Israel)
  1404. X *      Russell Lang (Monash University, Australia)
  1405. X *      O'Reilly & Associates: X Window System - Volumes 1 & 2
  1406. X *
  1407. X *   This code is provided as is and with no warranties of any kind.
  1408. X *       
  1409. X * There is a mailing list for gnuplot users. Note, however, that the
  1410. X * newsgroup 
  1411. X *    comp.graphics.gnuplot 
  1412. X * is identical to the mailing list (they
  1413. X * both carry the same set of messages). We prefer that you read the
  1414. X * messages through that newsgroup, to subscribing to the mailing list.
  1415. X * (If you can read that newsgroup, and are already on the mailing list,
  1416. X * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  1417. X * removed from the mailing list.)
  1418. X *
  1419. X * The address for mailing to list members is
  1420. X *       info-gnuplot@dartmouth.edu
  1421. X * and for mailing administrative requests is 
  1422. X *       info-gnuplot-request@dartmouth.edu
  1423. X * The mailing list for bug reports is 
  1424. X *       bug-gnuplot@dartmouth.edu
  1425. X * The list of those interested in beta-test versions is
  1426. X *       info-gnuplot-beta@dartmouth.edu
  1427. X *---------------------------------------------------------------------------*/
  1428. X
  1429. X#define DEFAULT_X11
  1430. X#if defined(VMS) || defined(CRIPPLED_SELECT)
  1431. X#undef DEFAULT_X11
  1432. X#endif
  1433. X#if defined(VMS) && defined(CRIPPLED_SELECT)
  1434. XError. Incompatible options.
  1435. X#endif
  1436. X
  1437. X#include <X11/Xos.h>
  1438. X#include <X11/Xlib.h>
  1439. X#include <X11/Xutil.h>
  1440. X#include <X11/Xatom.h>
  1441. X#include <X11/Xresource.h>
  1442. X#include <stdio.h>
  1443. X#include <signal.h>
  1444. X
  1445. X#ifdef BSD_TYPES
  1446. X#include <sys/bsdtypes.h>
  1447. X#endif /* BSD_TYPES */
  1448. X
  1449. X#if !defined(VMS) && !defined(FD_SET) && !defined(OLD_SELECT)
  1450. X#include <sys/select.h>
  1451. X#endif /* !VMS && !FD_SET && !OLD_SELECT */
  1452. X#ifndef FD_SET
  1453. X
  1454. X#define FD_SET(n, p)    ((p)->fds_bits[0] |= (1 << ((n) % 32)))
  1455. X#define FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1 << ((n) % 32)))
  1456. X#define FD_ISSET(n, p)  ((p)->fds_bits[0] & (1 << ((n) % 32)))
  1457. X#define FD_ZERO(p)      bzero((char *)(p), sizeof(*(p)))
  1458. X
  1459. X#endif /* !FD_SET */
  1460. X
  1461. X#ifdef SOLARIS
  1462. X#include <sys/systeminfo.h>
  1463. X#endif /* SOLARIS */
  1464. X
  1465. X
  1466. X#include <errno.h>
  1467. Xextern int errno;
  1468. X
  1469. X#define FallbackFont "fixed"
  1470. X
  1471. X#define Ncolors 13
  1472. Xunsigned long colors[Ncolors];
  1473. X
  1474. X#define Nwidths 10
  1475. Xunsigned int widths[Nwidths] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  1476. X
  1477. X#define Ndashes 10
  1478. Xchar dashes[Ndashes][5];
  1479. X
  1480. XDisplay *dpy; int scr; Window win, root;
  1481. XVisual *vis; GC gc = (GC)0; Pixmap pixmap; XFontStruct *font;
  1482. Xunsigned int W = 640, H = 450; int D, gX = 100, gY = 100;
  1483. Xunsigned int BorderWidth = 2;
  1484. Xunsigned User_Size = 0, User_Position = 0; /* User specified? */
  1485. X
  1486. X
  1487. XBool Mono = 0, Gray = 0, Rv = 0, Clear = 0;
  1488. Xchar Name[64] = "gnuplot";
  1489. Xchar Class[64] = "Gnuplot";
  1490. X
  1491. Xint cx=0, cy=0, vchar, nc = 0, ncalloc = 0;
  1492. Xdouble xscale, yscale, pointsize;
  1493. X#define X(x) (int) (x * xscale)
  1494. X#define Y(y) (int) ((4095-y) * yscale)
  1495. Xenum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
  1496. X
  1497. X#define Nbuf 1024
  1498. Xchar buf[Nbuf], **commands = (char **)0;
  1499. X
  1500. XFILE *X11_ipc;
  1501. Xchar X11_ipcpath[32];
  1502. X
  1503. X
  1504. X/*-----------------------------------------------------------------------------
  1505. X *   main program 
  1506. X *---------------------------------------------------------------------------*/
  1507. X
  1508. Xmain(argc, argv) int argc; char *argv[]; {
  1509. X
  1510. X   preset(argc, argv);
  1511. X   mainloop();
  1512. X   exit(0);
  1513. X
  1514. X   }
  1515. X
  1516. X/*-----------------------------------------------------------------------------
  1517. X *   mainloop processing - process X events and input from gnuplot
  1518. X *
  1519. X *   Three different versions of main loop processing are provided to support
  1520. X *   three different platforms.
  1521. X * 
  1522. X *   DEFAULT_X11:     use select() for both X events and input on stdin 
  1523. X *                    from gnuplot inboard driver
  1524. X *
  1525. X *   CRIPPLED_SELECT: use select() to service X events and check during 
  1526. X *                    select timeout for temporary plot file created
  1527. X *                    by inboard driver
  1528. X *
  1529. X *   VMS:             use XNextEvent to service X events and AST to
  1530. X *                    service input from gnuplot inboard driver on stdin 
  1531. X *---------------------------------------------------------------------------*/
  1532. X
  1533. X
  1534. X#ifdef DEFAULT_X11
  1535. X/*-----------------------------------------------------------------------------
  1536. X *    DEFAULT_X11 mainloop
  1537. X *---------------------------------------------------------------------------*/
  1538. X
  1539. Xmainloop() {
  1540. X   int nf, nfds, cn = ConnectionNumber(dpy), in = fileno(stdin);
  1541. X   struct timeval timeout, *timer = (struct timeval *)0;
  1542. X   fd_set rset, tset;
  1543. X   unsigned long all = 0xffffffff;
  1544. X   XEvent xe;
  1545. X
  1546. X   X11_ipc = stdin;
  1547. X
  1548. X   FD_ZERO(&rset);
  1549. X   FD_SET(cn, &rset);
  1550. X
  1551. X   FD_SET(in, &rset);
  1552. X   nfds = (cn > in) ? cn + 1 : in + 1;
  1553. X
  1554. X#ifdef ISC22
  1555. X/* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
  1556. X   timeout.tv_sec  = 0;        /* select() in ISC2.2 needs timeout */
  1557. X   timeout.tv_usec = 300000;    /* otherwise input from gnuplot is */
  1558. X   timer = &timeout;        /* suspended til next X event. */
  1559. X#endif /* ISC22      (0.3s are short enough not to be noticed */
  1560. X
  1561. X   while(1) {
  1562. X      tset = rset;
  1563. X      nf = select(nfds, &tset, (fd_set *)0, (fd_set *)0, timer);
  1564. X      if (nf < 0) {
  1565. X     if (errno == EINTR) continue;
  1566. X     fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
  1567. X     exit(1);
  1568. X     }
  1569. X      nf > 0 && XNoOp(dpy);
  1570. X      if (FD_ISSET(cn, &tset)) {
  1571. X     while (XCheckMaskEvent(dpy, all, &xe)) {
  1572. X        (xe.type == ConfigureNotify)  && resize(&xe); 
  1573. X        }
  1574. X     }
  1575. X      FD_ISSET(in, &tset) && record();
  1576. X      }
  1577. X   }
  1578. X
  1579. X#endif
  1580. X
  1581. X
  1582. X#ifdef CRIPPLED_SELECT
  1583. X/*-----------------------------------------------------------------------------
  1584. X *    CRIPPLED_SELECT mainloop
  1585. X *---------------------------------------------------------------------------*/
  1586. X
  1587. Xmainloop() {
  1588. X   int nf, nfds, cn = ConnectionNumber(dpy);
  1589. X   struct timeval timeout, *timer;
  1590. X   fd_set rset, tset;
  1591. X   unsigned long all = 0xffffffff;
  1592. X   XEvent xe;
  1593. X
  1594. X   FD_ZERO(&rset);
  1595. X   FD_SET(cn, &rset);
  1596. X
  1597. X   timeout.tv_sec = 1;
  1598. X   timeout.tv_usec = 0;
  1599. X   timer = &timeout;
  1600. X   sprintf(X11_ipcpath, "/tmp/Gnuplot_%d", getppid());
  1601. X   nfds = cn + 1;
  1602. X
  1603. X   while(1) {
  1604. X      tset = rset;
  1605. X      nf = select(nfds, &tset, (fd_set *)0, (fd_set *)0, timer);
  1606. X      if (nf < 0) {
  1607. X     if (errno == EINTR) continue;
  1608. X     fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
  1609. X     exit(1);
  1610. X     }
  1611. X      nf > 0 && XNoOp(dpy);
  1612. X      if (FD_ISSET(cn, &tset)) {
  1613. X     while (XCheckMaskEvent(dpy, all, &xe)) {
  1614. X        (xe.type == ConfigureNotify)  && resize(&xe); 
  1615. X        }
  1616. X     }
  1617. X      if ((X11_ipc = fopen(X11_ipcpath, "r"))) {
  1618. X     unlink(X11_ipcpath);
  1619. X     record();
  1620. X     fclose(X11_ipc);
  1621. X     }
  1622. X      }
  1623. X   }
  1624. X#endif /* CRIPPLED_SELECT */
  1625. X
  1626. X
  1627. X#ifdef VMS
  1628. X/*-----------------------------------------------------------------------------
  1629. X *    VMS mainloop - Yehavi Bourvine - YEHAVI@VMS.HUJI.AC.IL
  1630. X *---------------------------------------------------------------------------*/
  1631. X
  1632. X/*  In VMS there is no decent Select(). hence, we have to loop inside
  1633. X *  XGetNextEvent for getting the next X window event. In order to get input
  1634. X *  from the master we assign a channel to SYS$INPUT and use AST's in order to
  1635. X *  receive data. */
  1636. X
  1637. X#include <iodef.h>
  1638. Xchar    STDIIN[] = "SYS$INPUT:";
  1639. Xshort   STDIINchannel, STDIINiosb[4];
  1640. Xstruct  { short size, type; char  *address; } STDIINdesc;
  1641. Xchar    STDIINbuffer[64];
  1642. Xint     status;
  1643. X
  1644. X
  1645. Xmainloop() {
  1646. X   XEvent xe;
  1647. X
  1648. X   STDIINdesc.size = strlen(STDIIN); 
  1649. X   STDIINdesc.type = 0;
  1650. X   STDIINdesc.address = STDIIN;
  1651. X   status = sys$assign(&STDIINdesc, &STDIINchannel, 0, 0, 0);
  1652. X   if((status & 0x1) == 0)  exit(status); 
  1653. X   ast();
  1654. X
  1655. X   for(;;) {
  1656. X      XNextEvent(dpy, &xe);
  1657. X      (xe.type == ConfigureNotify)  && resize(&xe); 
  1658. X      }
  1659. X   }
  1660. X
  1661. Xast() {
  1662. X   int record();
  1663. X   int status = sys$qio(0, STDIINchannel, IO$_READVBLK, STDIINiosb, record,
  1664. X                0, STDIINbuffer, sizeof(STDIINbuffer) -1,0, 0, 0, 0);
  1665. X   if((status & 0x1) == 0) exit(status);
  1666. X   }
  1667. X#endif /* VMS */
  1668. X
  1669. X
  1670. X#ifndef VMS
  1671. X/*-----------------------------------------------------------------------------
  1672. X *   record - record new plot from gnuplot inboard X11 driver (Unix)
  1673. X *---------------------------------------------------------------------------*/
  1674. X
  1675. Xrecord() {
  1676. X
  1677. X   while (fgets(buf, Nbuf, X11_ipc)) {
  1678. X     if (*buf == 'G') {                           /* enter graphics mode */
  1679. X     if (commands) {
  1680. X        int n; for (n=0; n<nc; n++) free(commands[n]);
  1681. X        free(commands);
  1682. X        }
  1683. X     commands = (char **)0; nc = ncalloc = 0;
  1684. X         }
  1685. X      else if (*buf == 'E') { display(); break; } /* leave graphics mode */
  1686. X      else if (*buf == 'R') { exit(0); }          /* leave X11/x11 mode  */
  1687. X      else {                                      /* record command      */
  1688. X     char *p;
  1689. X     if (nc >= ncalloc) {
  1690. X        ncalloc = ncalloc*2 + 1;
  1691. X        commands = (commands)
  1692. X           ? (char **)realloc(commands, ncalloc * sizeof(char *))
  1693. X           : (char **)malloc(sizeof(char *));
  1694. X        }
  1695. X     p = (char *)malloc((unsigned)strlen(buf)+1);
  1696. X     if (!commands || !p) {
  1697. X        fprintf(stderr, "gnuplot: can't get memory. X11 aborted.\n");
  1698. X        exit(1);
  1699. X        }
  1700. X     commands[nc++] = strcpy(p, buf);
  1701. X     }
  1702. X      }
  1703. X   if (feof(X11_ipc) || ferror(X11_ipc)) exit(1);
  1704. X   }
  1705. X
  1706. X#else    /* VMS */
  1707. X/*-----------------------------------------------------------------------------
  1708. X *   record - record new plot from gnuplot inboard X11 driver (VMS)
  1709. X *---------------------------------------------------------------------------*/
  1710. X
  1711. Xrecord() {
  1712. X   int    status;
  1713. X
  1714. X   if((STDIINiosb[0] & 0x1) == 0) exit(STDIINiosb[0]);
  1715. X   STDIINbuffer[STDIINiosb[1]] = '\0';
  1716. X   strcpy(buf, STDIINbuffer);
  1717. X
  1718. X   if (*buf == 'G') {                           /* enter graphics mode */
  1719. X      if (commands) {
  1720. X         int n; for (n=0; n<nc; n++) free(commands[n]);
  1721. X         free(commands);
  1722. X         }
  1723. X       commands = (char **)0; nc = ncalloc = 0;
  1724. X       }
  1725. X   else if (*buf == 'E') {                      /* leave graphics mode */
  1726. X      display(); 
  1727. X      }
  1728. X   else if (*buf == 'R') {                      /* leave x11/X11 mode  */
  1729. X       sys$cancel(STDIINchannel);
  1730. X       XCloseDisplay(dpy);
  1731. X       sys$delprc(0,0);      /* Somehow it doesn't drop itself... */
  1732. X       exit(1); 
  1733. X       }
  1734. X   else {                                       /* record command      */
  1735. X      char *p;
  1736. X      if (nc >= ncalloc) {
  1737. X     ncalloc = ncalloc*2 + 1;
  1738. X     commands = (commands)
  1739. X        ? (char **)realloc(commands, ncalloc * sizeof(char *))
  1740. X        : (char **)malloc(sizeof(char *));
  1741. X     }
  1742. X      p = (char *)malloc((unsigned)strlen(buf)+1);
  1743. X      if (!commands || !p) {
  1744. X     fprintf(stderr, "gnuplot: can't get memory. X11 aborted.\n");
  1745. X     exit(1);
  1746. X     }
  1747. X      commands[nc++] = strcpy(p, buf);
  1748. X      }
  1749. X   ast();
  1750. X   }
  1751. X#endif /* VMS */
  1752. X
  1753. X/*-----------------------------------------------------------------------------
  1754. X *   display - display last plot from gnuplot inboard X11 driver
  1755. X *---------------------------------------------------------------------------*/
  1756. X
  1757. Xdisplay() {
  1758. X   int n, x, y, sw, sl, lt, width, type, point, px, py;
  1759. X   char *buf, *str;
  1760. X
  1761. X   if (!nc) return;
  1762. X
  1763. X   /* set scaling factor between internal driver & window geometry */
  1764. X   xscale = (double)W / 4096.;  yscale = (double)H / 4096.;  
  1765. X
  1766. X   /* create new pixmap & GC */
  1767. X   if (gc) { XFreeGC(dpy, gc); XFreePixmap(dpy, pixmap); }
  1768. X   pixmap = XCreatePixmap(dpy, root, W, H, D);
  1769. X   gc = XCreateGC(dpy, pixmap, 0, (XGCValues *)0);
  1770. X   XSetFont(dpy, gc, font->fid);
  1771. X
  1772. X   /* set pixmap background */
  1773. X   XSetForeground(dpy, gc, colors[0]);
  1774. X   XFillRectangle(dpy, pixmap, gc, 0, 0, W, H);
  1775. X   XSetBackground(dpy, gc, colors[0]);
  1776. X
  1777. X   /* set new pixmap as window background */
  1778. X   XSetWindowBackgroundPixmap(dpy, win, pixmap);
  1779. X
  1780. X   /* top the window but don't put keyboard or mouse focus into it. */
  1781. X   XMapRaised(dpy, win);
  1782. X
  1783. X   /* momentarily clear the window first if requested */
  1784. X   if (Clear) {
  1785. X      XClearWindow(dpy, win);
  1786. X      XFlush(dpy);
  1787. X      }
  1788. X
  1789. X   /* loop over accumulated commands from inboard driver */
  1790. X   for (n=0; n<nc; n++) {
  1791. X      buf = commands[n];
  1792. X
  1793. X      /*   X11_vector(x,y) - draw vector  */
  1794. X      if (*buf == 'V') { 
  1795. X     sscanf(buf, "V%4d%4d", &x, &y);  
  1796. X     XDrawLine(dpy, pixmap, gc, X(cx), Y(cy), X(x), Y(y));
  1797. X     cx = x; cy = y;
  1798. X     }
  1799. X
  1800. X      /*   X11_move(x,y) - move  */
  1801. X      else if (*buf == 'M') 
  1802. X     sscanf(buf, "M%4d%4d", &cx, &cy);  
  1803. X
  1804. X      /*   X11_put_text(x,y,str) - draw text   */
  1805. X      else if (*buf == 'T') { 
  1806. X     sscanf(buf, "T%4d%4d", &x, &y);  
  1807. X     str = buf + 9; sl = strlen(str) - 1;
  1808. X     sw = XTextWidth(font, str, sl);
  1809. X     switch(jmode) {
  1810. X        case LEFT:   sw = 0;     break;
  1811. X        case CENTRE: sw = -sw/2; break;
  1812. X        case RIGHT:  sw = -sw;   break;
  1813. X        }
  1814. X     XSetForeground(dpy, gc, colors[2]);
  1815. X     XDrawString(dpy, pixmap, gc, X(x)+sw, Y(y)+vchar/3, str, sl);
  1816. X     XSetForeground(dpy, gc, colors[lt+3]);
  1817. X     }
  1818. X
  1819. X      /*   X11_justify_text(mode) - set text justification mode  */
  1820. X      else if (*buf == 'J') 
  1821. X     sscanf(buf, "J%4d", &jmode);
  1822. X
  1823. X      /*   X11_linetype(type) - set line type  */
  1824. X      else if (*buf == 'L') { 
  1825. X     sscanf(buf, "L%4d", <);
  1826. X     lt = (lt%8)+2;
  1827. X     width = widths[lt];
  1828. X     if (dashes[lt][0]) {
  1829. X        type = LineOnOffDash;
  1830. X        XSetDashes(dpy, gc, 0, dashes[lt], strlen(dashes[lt]));
  1831. X        }
  1832. X     else {
  1833. X        type = LineSolid;
  1834. X        }
  1835. X     XSetForeground(dpy, gc, colors[lt+3]);
  1836. X     XSetLineAttributes( dpy,gc, width, type, CapButt, JoinBevel);
  1837. X       }
  1838. X
  1839. X      /*   X11_point(number) - draw a point */
  1840. X      else if (*buf == 'P') { 
  1841. X      sscanf(buf, "P%1d%4d%4d", &point, &x, &y);  
  1842. X      if (point==7) {
  1843. X         /* set point size */
  1844. X         px = (int) (x * xscale * pointsize);
  1845. X         py = (int) (y * yscale * pointsize);
  1846. X         }
  1847. X      else {
  1848. X        if (type != LineSolid || width != 0) {  /* select solid line */
  1849. X           XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinBevel);
  1850. X           }
  1851. X        switch(point) {
  1852. X           case 0: /* dot */
  1853. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  1854. X           break;
  1855. X           case 1: /* do diamond */ 
  1856. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x), Y(y)-py);
  1857. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x)+px, Y(y));
  1858. X           XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y), X(x), Y(y)+py);
  1859. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y)+py, X(x)-px, Y(y));
  1860. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  1861. X           break;
  1862. X           case 2: /* do plus */ 
  1863. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x)+px, Y(y));
  1864. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x), Y(y)+py);
  1865. X           break;
  1866. X           case 3: /* do box */ 
  1867. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)-py);
  1868. X           XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y)-py, X(x)+px, Y(y)+py);
  1869. X           XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y)+py, X(x)-px, Y(y)+py);
  1870. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)-px, Y(y)-py);
  1871. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  1872. X           break;
  1873. X           case 4: /* do X */ 
  1874. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)+py);
  1875. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)+px, Y(y)-py);
  1876. X           break;
  1877. X           case 5: /* do triangle */ 
  1878. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y)-(4*px/3), 
  1879. X                 X(x)-(4*px/3), Y(y)+(2*py/3));
  1880. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y)-(4*px/3), 
  1881. X                 X(x)+(4*px/3), Y(y)+(2*py/3));
  1882. X           XDrawLine(dpy,pixmap,gc, X(x)-(4*px/3), Y(y)+(2*py/3), 
  1883. X                 X(x)+(4*px/3), Y(y)+(2*py/3));
  1884. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  1885. X           break;
  1886. X           case 6: /* do star */ 
  1887. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x)+px, Y(y));
  1888. X           XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x), Y(y)+py);
  1889. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)+py);
  1890. X           XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)+px, Y(y)-py);
  1891. X           break;
  1892. X           }
  1893. X        if (type != LineSolid || width != 0) {  /* select solid line */
  1894. X           XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
  1895. X           }
  1896. X        }
  1897. X     }
  1898. X      }
  1899. X
  1900. X   /* trigger exposure of background pixmap */
  1901. X   XClearWindow(dpy,win);
  1902. X   XFlush(dpy);
  1903. X   }
  1904. X
  1905. X/*-----------------------------------------------------------------------------
  1906. X *   resize - rescale last plot if window resized
  1907. X *---------------------------------------------------------------------------*/
  1908. X
  1909. Xresize(xce) XConfigureEvent *xce; {
  1910. X   int w = xce->width, h = xce->height;
  1911. X   
  1912. X   if (w>1 && h>1 && (w != W || h != H)) {
  1913. X      W = w; H = h;
  1914. X      display();
  1915. X      }
  1916. X   }
  1917. X
  1918. X
  1919. X/*-----------------------------------------------------------------------------
  1920. X *   preset - determine options, open display, create window
  1921. X *---------------------------------------------------------------------------*/
  1922. X
  1923. X#define On(v) ( !strcmp(v,"on") || !strcmp(v,"true") || \
  1924. X        !strcmp(v,"On") || !strcmp(v,"True") )
  1925. X
  1926. X#define AppDefDir "/usr/lib/X11/app-defaults"
  1927. X#ifndef MAXHOSTNAMELEN
  1928. X#define MAXHOSTNAMELEN 64
  1929. X#endif
  1930. X
  1931. Xstatic XrmDatabase dbCmd, dbApp, dbDef, dbEnv, db = (XrmDatabase)0;
  1932. X
  1933. Xchar *pr_GetR(), *getenv(), *type[20];
  1934. XXrmValue value;
  1935. X
  1936. X#define Nopt 27
  1937. Xstatic XrmOptionDescRec options[] = {
  1938. X   {"-mono",             ".mono",             XrmoptionNoArg,   "on" },
  1939. X   {"-gray",             ".gray",             XrmoptionNoArg,   "on" },
  1940. X   {"-clear",            ".clear",            XrmoptionNoArg,   "on" },
  1941. X   {"-tvtwm",            ".tvtwm",            XrmoptionNoArg,   "on" },
  1942. X   {"-pointsize",        ".pointsize",        XrmoptionSepArg,  NULL },
  1943. X   {"-display",          ".display",          XrmoptionSepArg,  NULL },
  1944. X   {"-name",             ".name",             XrmoptionSepArg,  NULL },
  1945. X   {"-geometry",         "*geometry",         XrmoptionSepArg,  NULL },
  1946. X   {"-background",       "*background",       XrmoptionSepArg,  NULL },
  1947. X   {"-bg",               "*background",       XrmoptionSepArg,  NULL },
  1948. X   {"-foreground",       "*foreground",       XrmoptionSepArg,  NULL },
  1949. X   {"-fg",               "*foreground",       XrmoptionSepArg,  NULL },
  1950. X   {"-bordercolor",      "*bordercolor",      XrmoptionSepArg,  NULL },
  1951. X   {"-bd",               "*bordercolor",      XrmoptionSepArg,  NULL },
  1952. X   {"-borderwidth",      ".borderwidth",      XrmoptionSepArg,  NULL },
  1953. X   {"-bw",               ".borderwidth",      XrmoptionSepArg,  NULL },
  1954. X   {"-font",             "*font",             XrmoptionSepArg,  NULL },
  1955. X   {"-fn",               "*font",             XrmoptionSepArg,  NULL },
  1956. X   {"-reverse",          "*reverseVideo",     XrmoptionNoArg,   "on" },
  1957. X   {"-rv",               "*reverseVideo",     XrmoptionNoArg,   "on" },
  1958. X   {"+rv",               "*reverseVideo",     XrmoptionNoArg,   "off"},
  1959. X   {"-iconic",           "*iconic",           XrmoptionNoArg,   "on" },
  1960. X   {"-synchronous",      "*synchronous",      XrmoptionNoArg,   "on" },
  1961. X   {"-xnllanguage",      "*xnllanguage",      XrmoptionSepArg,  NULL },
  1962. X   {"-selectionTimeout", "*selectionTimeout", XrmoptionSepArg,  NULL },
  1963. X   {"-title",            ".title",            XrmoptionSepArg,  NULL },
  1964. X   {"-xrm",              NULL,                XrmoptionResArg,  NULL },
  1965. X   };
  1966. X
  1967. Xpreset(argc, argv) int argc; char *argv[]; {
  1968. X   int Argc = argc; char **Argv = argv;
  1969. X
  1970. X#ifdef VMS
  1971. X   char *display = (char *) 0;
  1972. X#else
  1973. X   char *display = getenv("DISPLAY");
  1974. X#endif
  1975. X   char *home = getenv("HOME");
  1976. X   char *server_defaults, *env, buf[256];
  1977. X
  1978. X   /*---set to ignore ^C and ^Z----------------------------------------------*/
  1979. X
  1980. X   signal(SIGINT, SIG_IGN);
  1981. X#ifdef SIGTSTP
  1982. X   signal(SIGTSTP, SIG_IGN);
  1983. X#endif
  1984. X
  1985. X   /*---prescan arguments for "-name"----------------------------------------*/
  1986. X
  1987. X   while(++Argv, --Argc > 0) {
  1988. X      if (!strcmp(*Argv, "-name") && Argc > 1) {
  1989. X     strncpy(Name, Argv[1], 64);
  1990. X     strncpy(Class, Argv[1], 64);
  1991. X     if (Class[0] >= 'a' && Class[0] <= 'z') Class[0] -= 0x20;
  1992. X     }
  1993. X      }
  1994. X   Argc = argc; Argv = argv;
  1995. X
  1996. X   /*---parse command line---------------------------------------------------*/
  1997. X
  1998. X   XrmInitialize();
  1999. X   XrmParseCommand(&dbCmd, options, Nopt, Name, &Argc, Argv);
  2000. X   if (Argc > 1) {
  2001. X      fprintf(stderr, "\ngnuplot: bad option: %s\n", Argv[1]);
  2002. X      fprintf(stderr, "gnuplot: X11 aborted.\n");
  2003. X      exit(1);
  2004. X      }
  2005. X   if (pr_GetR(dbCmd, ".display")) display = value.addr;
  2006. X
  2007. X   /*---open display---------------------------------------------------------*/
  2008. X
  2009. X   dpy = XOpenDisplay(display); 
  2010. X   if (!dpy) {
  2011. X      fprintf(stderr, "\ngnuplot: unable to open display '%s'\n", display);
  2012. X      fprintf(stderr, "gnuplot: X11 aborted.\n");
  2013. X      exit(1);
  2014. X      }
  2015. X   scr = DefaultScreen(dpy);
  2016. X   vis = DefaultVisual(dpy,scr);
  2017. X   D = DefaultDepth(dpy,scr);
  2018. X   root = DefaultRootWindow(dpy);
  2019. X   server_defaults = XResourceManagerString(dpy);
  2020. X
  2021. X   /*---get application defaults--(subset of Xt processing)------------------*/
  2022. X
  2023. X#ifdef VMS
  2024. X   strcpy (buf, "DECW$USER_DEFAULTS:GNUPLOT_X11.INI");
  2025. X#else
  2026. X   sprintf(buf, "%s/%s", AppDefDir, "Gnuplot");
  2027. X#endif
  2028. X   dbApp = XrmGetFileDatabase(buf);
  2029. X   XrmMergeDatabases(dbApp, &db);
  2030. X
  2031. X   /*---get server or ~/.Xdefaults-------------------------------------------*/
  2032. X
  2033. X   if (server_defaults)
  2034. X      dbDef = XrmGetStringDatabase(server_defaults);
  2035. X   else {
  2036. X#ifdef VMS
  2037. X      strcpy(buf,"DECW$USER_DEFAULTS:DECW$XDEFAULTS.DAT");
  2038. X#else
  2039. X      sprintf(buf, "%s/.Xdefaults", home);
  2040. X#endif
  2041. X      dbDef = XrmGetFileDatabase(buf);
  2042. X      }
  2043. X   XrmMergeDatabases(dbDef, &db);
  2044. X
  2045. X   /*---get XENVIRONMENT or  ~/.Xdefaults-hostname---------------------------*/
  2046. X
  2047. X#ifndef VMS
  2048. X   if (env = getenv("XENVIRONMENT")) 
  2049. X      dbEnv = XrmGetFileDatabase(env);
  2050. X   else {
  2051. X      char *p, host[MAXHOSTNAMELEN];
  2052. X#ifdef SOLARIS
  2053. X      if (sysinfo(SI_HOSTNAME, host, MAXHOSTNAMELEN) < 0) {
  2054. X         fprintf(stderr, "gnuplot: sysinfo failed. X11 aborted.\n");
  2055. X#else
  2056. X      if (gethostname(host, MAXHOSTNAMELEN) < 0) {
  2057. X         fprintf(stderr, "gnuplot: gethostname failed. X11 aborted.\n");
  2058. X#endif /* SOLARIS */
  2059. X     exit(1);
  2060. X     }
  2061. X      if (p = index(host, '.')) *p = '\0';
  2062. X      sprintf(buf, "%s/.Xdefaults-%s", home, host);
  2063. X      dbEnv = XrmGetFileDatabase(buf);
  2064. X      }
  2065. X   XrmMergeDatabases(dbEnv, &db);
  2066. X#endif   /* not VMS */
  2067. X
  2068. X   /*---merge command line options-------------------------------------------*/
  2069. X
  2070. X   XrmMergeDatabases(dbCmd, &db);
  2071. X
  2072. X   /*---set geometry, font, colors, line widths, dash styles, point size-----*/
  2073. X
  2074. X   pr_geometry();
  2075. X   pr_font();
  2076. X   pr_color();
  2077. X   pr_width();
  2078. X   pr_dashes();
  2079. X   pr_pointsize();
  2080. X
  2081. X   /*---create window--------------------------------------------------------*/
  2082. X
  2083. X   pr_window();
  2084. X
  2085. X   } 
  2086. X
  2087. X/*-----------------------------------------------------------------------------
  2088. X *   pr_GetR - get resource from database using "-name" option (if any)
  2089. X *---------------------------------------------------------------------------*/
  2090. X
  2091. Xchar *
  2092. Xpr_GetR(db, resource) XrmDatabase db; char *resource; {
  2093. X   char name[128], class[128], *rc;
  2094. X
  2095. X   strcpy(name, Name); strcat(name, resource);
  2096. X   strcpy(class, Class); strcat(class, resource);
  2097. X   rc = XrmGetResource(db, name, class, type, &value)
  2098. X      ? (char *)value.addr 
  2099. X      : (char *)0;
  2100. X   return(rc);
  2101. X   }
  2102. X
  2103. X/*-----------------------------------------------------------------------------
  2104. X *   pr_color - determine color values
  2105. X *---------------------------------------------------------------------------*/
  2106. X
  2107. Xchar color_keys[Ncolors][30] =   { 
  2108. X   "background", "bordercolor", "text", "border", "axis", 
  2109. X   "line1", "line2", "line3",  "line4", 
  2110. X   "line5", "line6", "line7",  "line8" 
  2111. X   };
  2112. Xchar color_values[Ncolors][30] = { 
  2113. X   "white", "black",  "black",  "black",  "black", 
  2114. X   "red",   "green",  "blue",   "magenta", 
  2115. X   "cyan",  "sienna", "orange", "coral" 
  2116. X   };
  2117. Xchar gray_values[Ncolors][30] = { 
  2118. X   "black",   "white",  "white",  "gray50", "gray50",
  2119. X   "gray100", "gray60", "gray80", "gray40", 
  2120. X   "gray90",  "gray50", "gray70", "gray30" 
  2121. X   };
  2122. X
  2123. Xpr_color() {
  2124. X   unsigned long black = BlackPixel(dpy, scr), white = WhitePixel(dpy,scr);
  2125. X   char option[20], color[30], *v, *type; 
  2126. X   XColor xcolor;
  2127. X   Colormap cmap;
  2128. X   double intensity = -1;
  2129. X   int n;
  2130. X
  2131. X   pr_GetR(db, ".mono")         && On(value.addr) && Mono++;
  2132. X   pr_GetR(db, ".gray")         && On(value.addr) && Gray++;
  2133. X   pr_GetR(db, ".reverseVideo") && On(value.addr) && Rv++;
  2134. X
  2135. X   if (!Gray && (vis->class == GrayScale || vis->class == StaticGray)) Mono++;
  2136. X
  2137. X   if (!Mono) {
  2138. X      cmap = DefaultColormap(dpy, scr);
  2139. X      type = (Gray) ? "Gray" : "Color";
  2140. X
  2141. X      for (n=0; n<Ncolors; n++) {
  2142. X     strcpy(option, ".");
  2143. X     strcat(option, color_keys[n]);
  2144. X     (n > 1) && strcat(option, type);
  2145. X     v = pr_GetR(db, option) 
  2146. X         ? value.addr
  2147. X         : ((Gray) ? gray_values[n] : color_values[n]);
  2148. X
  2149. X     if (sscanf(v,"%30[^,],%lf", color, &intensity) == 2) {
  2150. X        if (intensity < 0 || intensity > 1) {
  2151. X           fprintf(stderr, "\ngnuplot: invalid color intensity in '%s'\n",
  2152. X                       color);
  2153. X           intensity = 1;
  2154. X           }
  2155. X        }
  2156. X     else { 
  2157. X        strcpy(color, v);
  2158. X        intensity = 1;
  2159. X        }
  2160. X
  2161. X     if (!XParseColor(dpy, cmap, color, &xcolor)) {
  2162. X        fprintf(stderr, "\ngnuplot: unable to parse '%s'. Using black.\n",
  2163. X                    color);
  2164. X        colors[n] = black;
  2165. X        }
  2166. X     else {
  2167. X        xcolor.red *= intensity;
  2168. X        xcolor.green *= intensity;
  2169. X        xcolor.blue *= intensity;
  2170. X        if (XAllocColor(dpy, cmap, &xcolor)) {
  2171. X           colors[n] = xcolor.pixel;
  2172. X           }
  2173. X        else {
  2174. X           fprintf(stderr, "\ngnuplot: can't allocate '%s'. Using black.\n",
  2175. X                        v);
  2176. X           colors[n] = black;
  2177. X           }
  2178. X        }
  2179. X     }
  2180. X      }
  2181. X   else {
  2182. X      colors[0] = (Rv) ? black : white ;
  2183. X      for (n=1; n<Ncolors; n++)  colors[n] = (Rv) ? white : black;
  2184. X      }
  2185. X   }
  2186. X
  2187. X/*-----------------------------------------------------------------------------
  2188. X *   pr_dashes - determine line dash styles 
  2189. X *---------------------------------------------------------------------------*/
  2190. X
  2191. Xchar dash_keys[Ndashes][10] =   { 
  2192. X   "border", "axis",
  2193. X   "line1", "line2", "line3",  "line4", "line5", "line6", "line7",  "line8" 
  2194. X   };
  2195. X
  2196. Xchar dash_mono[Ndashes][10] =   { 
  2197. X   "0", "16",
  2198. X   "0", "42", "13",  "44", "15", "4441", "42",  "13" 
  2199. X   };
  2200. X
  2201. Xchar dash_color[Ndashes][10] =   { 
  2202. X   "0", "16",
  2203. X   "0", "0", "0", "0", "0", "0", "0", "0" 
  2204. X   };
  2205. X
  2206. Xpr_dashes() {
  2207. X   int n, j, l, ok;
  2208. X   char option[20], *v; 
  2209. X   for (n=0; n<Ndashes; n++) {
  2210. X      strcpy(option, ".");
  2211. X      strcat(option, dash_keys[n]);
  2212. X      strcat(option, "Dashes");
  2213. X      v = pr_GetR(db, option) 
  2214. X      ? value.addr
  2215. X      : ((Mono) ? dash_mono[n] : dash_color[n]);
  2216. X      l = strlen(v);
  2217. X      if (l == 1 && *v == '0') {
  2218. X     dashes[n][0] = (unsigned char)0;
  2219. X     continue;
  2220. X     }
  2221. X      for (ok=0, j=0; j<l; j++) { v[j] >= '1' && v[j] <= '9' && ok++; }
  2222. X      if (ok != l || (ok != 2 && ok != 4)) {
  2223. X     fprintf(stderr, "gnuplot: illegal dashes value %s:%s\n", option, v);
  2224. X     dashes[n][0] = (unsigned char)0;
  2225. X     continue;
  2226. X     }
  2227. X      for(j=0; j<l; j++) {
  2228. X     dashes[n][j] = (unsigned char) (v[j] - '0');
  2229. X     }
  2230. X      dashes[n][l] = (unsigned char)0;
  2231. X      }
  2232. X   }
  2233. X
  2234. X/*-----------------------------------------------------------------------------
  2235. X *   pr_font - determine font          
  2236. X *---------------------------------------------------------------------------*/
  2237. X
  2238. Xpr_font() {
  2239. X   char *fontname = pr_GetR(db, ".font");
  2240. X
  2241. X   if (!fontname) fontname = FallbackFont;
  2242. X   font = XLoadQueryFont(dpy, fontname);
  2243. X   if (!font) {
  2244. X      fprintf(stderr, "\ngnuplot: can't load font '%s'\n", fontname);
  2245. X      fprintf(stderr, "gnuplot: using font '%s' instead.\n", FallbackFont);
  2246. X      font = XLoadQueryFont(dpy, FallbackFont);
  2247. X      if (!font) {
  2248. X     fprintf(stderr, "gnuplot: can't load font '%s'\n", FallbackFont);
  2249. X     fprintf(stderr, "gnuplot: no useable font - X11 aborted.\n");
  2250. X         exit(1);
  2251. X     }
  2252. X      }
  2253. X   vchar = font->ascent + font->descent;
  2254. X   }
  2255. X
  2256. X/*-----------------------------------------------------------------------------
  2257. X *   pr_geometry - determine window geometry      
  2258. X *---------------------------------------------------------------------------*/
  2259. X
  2260. Xpr_geometry() {
  2261. X   char *geometry = pr_GetR(db, ".geometry");
  2262. X   int x, y, flags;
  2263. X   unsigned int w, h; 
  2264. X
  2265. X   if (geometry) {
  2266. X      flags = XParseGeometry(geometry, &x, &y, &w, &h);
  2267. X      if (flags & WidthValue)  User_Size = 1, W = w;
  2268. X      if (flags & HeightValue) User_Size = 1, H = h;
  2269. X      if (flags & XValue) {
  2270. X         if (flags & XNegative)
  2271. X            x += DisplayWidth(dpy,scr) - W - BorderWidth*2;
  2272. X         User_Position = 1, gX = x;
  2273. X         }
  2274. X      if (flags & YValue) {
  2275. X         if (flags & YNegative)
  2276. X            y += DisplayHeight(dpy,scr) - H - BorderWidth*2;
  2277. X         User_Position = 1, gY = y;
  2278. X         }
  2279. X      }
  2280. X   }
  2281. X
  2282. X/*-----------------------------------------------------------------------------
  2283. X *   pr_pointsize - determine size of points for 'points' plotting style
  2284. X *---------------------------------------------------------------------------*/
  2285. X
  2286. Xpr_pointsize() {
  2287. X   char *p = pr_GetR(db, ".pointsize") ? value.addr : "1.0" ;
  2288. X
  2289. X   if (sscanf(p,"%lf", &pointsize) == 1) {
  2290. X      if (pointsize <= 0 || pointsize > 10) {
  2291. X     fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", p);
  2292. X     pointsize = 1;
  2293. X     }
  2294. X      }
  2295. X   else { 
  2296. X      fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", p);
  2297. X      pointsize = 1;
  2298. X      }
  2299. X   }
  2300. X
  2301. X/*-----------------------------------------------------------------------------
  2302. X *   pr_width - determine line width values
  2303. X *---------------------------------------------------------------------------*/
  2304. X
  2305. Xchar width_keys[Nwidths][30] =   { 
  2306. X   "border", "axis",
  2307. X   "line1", "line2", "line3",  "line4", "line5", "line6", "line7",  "line8" 
  2308. X   };
  2309. X
  2310. Xpr_width() {
  2311. X   int n;
  2312. X   char option[20], *v; 
  2313. X   for (n=0; n<Nwidths; n++) {
  2314. X      strcpy(option, ".");
  2315. X      strcat(option, width_keys[n]);
  2316. X      strcat(option, "Width");
  2317. X      if (v = pr_GetR(db, option)) {
  2318. X     if ( *v < '0' || *v > '4' || strlen(v) > 1)
  2319. X        fprintf(stderr, "gnuplot: illegal width value %s:%s\n", option, v);
  2320. X     else 
  2321. X        widths[n] = (unsigned int)atoi(v);
  2322. X     }
  2323. X      }
  2324. X   }
  2325. X
  2326. X/*-----------------------------------------------------------------------------
  2327. X *   pr_window - create window 
  2328. X *---------------------------------------------------------------------------*/
  2329. X
  2330. Xpr_window() {
  2331. X   char *title =  pr_GetR(db, ".title");
  2332. X   static XSizeHints hints;
  2333. X   int Tvtwm = 0;
  2334. X
  2335. X   win = XCreateSimpleWindow(dpy, root, gX, gY, W, H, BorderWidth,
  2336. X                             colors[1], colors[0]);
  2337. X
  2338. X   pr_GetR(db, ".clear") && On(value.addr) && Clear++;
  2339. X   pr_GetR(db, ".tvtwm") && On(value.addr) && Tvtwm++;
  2340. X
  2341. X   if (!Tvtwm) {
  2342. X      hints.flags = (User_Position ? USPosition : PPosition);
  2343. X      hints.flags |= (User_Size ? USSize : PSize);
  2344. X      }
  2345. X   else {
  2346. X      hints.flags = PPosition;
  2347. X      }
  2348. X   hints.x = gX; hints.y = gY;        
  2349. X   hints.width = W; hints.height = H;
  2350. X
  2351. X   XSetNormalHints(dpy, win, &hints);
  2352. X
  2353. X   if (pr_GetR(db, ".iconic") && On(value.addr)) {
  2354. X      XWMHints wmh;
  2355. X
  2356. X      wmh.flags = StateHint ;
  2357. X      wmh.initial_state = IconicState;
  2358. X      XSetWMHints(dpy, win, &wmh);
  2359. X      } 
  2360. X
  2361. X   XStoreName(dpy, win, ((title) ? title : Class));
  2362. X
  2363. X   XSelectInput(dpy, win, StructureNotifyMask);
  2364. X   XMapWindow(dpy, win);
  2365. X   
  2366. X   }
  2367. END_OF_FILE
  2368.   if test 30922 -ne `wc -c <'gnuplot/gplt_x11.c'`; then
  2369.     echo shar: \"'gnuplot/gplt_x11.c'\" unpacked with wrong size!
  2370.   fi
  2371.   # end of 'gnuplot/gplt_x11.c'
  2372. fi
  2373. echo shar: End of archive 12 \(of 33\).
  2374. cp /dev/null ark12isdone
  2375. MISSING=""
  2376. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
  2377.     if test ! -f ark${I}isdone ; then
  2378.     MISSING="${MISSING} ${I}"
  2379.     fi
  2380. done
  2381. if test "${MISSING}" = "" ; then
  2382.     echo You have unpacked all 33 archives.
  2383.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2384. else
  2385.     echo You still must unpack the following archives:
  2386.     echo "        " ${MISSING}
  2387. fi
  2388. exit 0
  2389. exit 0 # Just in case...
  2390.