home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / ephem / part07 < prev    next >
Text File  |  1992-03-15  |  55KB  |  2,128 lines

  1. Newsgroups: comp.sources.misc
  2. From: e_downey@hwking.cca.cr.rockwell.com (Elwood C. Downey)
  3. Subject:  v28i090:  ephem - an interactive astronomical ephemeris, v4.28, Part07/09
  4. Message-ID: <1992Mar10.215921.16270@sparky.imd.sterling.com>
  5. X-Md4-Signature: 96e65b62725b81b7c3d9c10d7ddf4c4a
  6. Date: Tue, 10 Mar 1992 21:59:21 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: e_downey@hwking.cca.cr.rockwell.com (Elwood C. Downey)
  10. Posting-number: Volume 28, Issue 90
  11. Archive-name: ephem/part07
  12. Environment: UNIX, VMS, DOS, MAC
  13. Supersedes: ephem-4.21: Volume 14, Issue 76-81
  14.  
  15. #! /bin/sh
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  19. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  20. # Contents:  altmenus.c flog.c formats.c listing.c plot.c srch.c
  21. # Wrapped by kent@sparky on Tue Mar 10 14:34:08 1992
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 7 (of 9)."'
  25. if test -f 'altmenus.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'altmenus.c'\"
  27. else
  28.   echo shar: Extracting \"'altmenus.c'\" \(11329 characters\)
  29.   sed "s/^X//" >'altmenus.c' <<'END_OF_FILE'
  30. X/* routines for managing the alternative bottom half menus.
  31. X * planet-specific menus are in their own files.
  32. X */
  33. X
  34. X#include <stdio.h>
  35. X#include <math.h>
  36. X#include "astro.h"
  37. X#include "circum.h"
  38. X#include "screen.h"
  39. X
  40. Xstatic int altmenu = F_MNU1;    /* which alternate menu is up; one of F_MNUi */
  41. Xstatic int alt2_stdhzn;    /* whether to use STDHZN (aot ADPHZN) horizon algthm  */
  42. Xstatic int alt3_geoc;    /* whether to use geocentric (aot topocentric) vantage*/
  43. X
  44. X/* table of screen rows given a body #define from astro/h or screen.h */
  45. Xstatic short bodyrow[NOBJ] = {
  46. X    R_MERCURY, R_VENUS, R_MARS, R_JUPITER, R_SATURN,
  47. X    R_URANUS, R_NEPTUNE, R_PLUTO, R_SUN, R_MOON, R_OBJX, R_OBJY
  48. X};
  49. X/* table of screen cols for third menu format, given body #define ... */
  50. Xstatic short bodycol[NOBJ] = {
  51. X    C_MERCURY, C_VENUS, C_MARS, C_JUPITER, C_SATURN,
  52. X    C_URANUS, C_NEPTUNE, C_PLUTO, C_SUN, C_MOON, C_OBJX, C_OBJY
  53. X};
  54. X
  55. X/* initialize altmenu; used by main from cracking the ephem startup file.
  56. X */
  57. Xaltmenu_init (n)
  58. Xint n;
  59. X{
  60. X    altmenu = n;
  61. X}
  62. X
  63. X/* let op decide which alternate menu should be up,
  64. X * including any menu-specific setup they might require.
  65. X * return 0 if things changed to require updating the alt menu; else -1.
  66. X */
  67. Xaltmenu_setup()
  68. X{
  69. X    static char *flds[5] = {
  70. X        "Data", "(Rise/Set", "", "(Separations"
  71. X    };
  72. X    int newmenu = altmenu, newhzn = alt2_stdhzn, newgeoc = alt3_geoc;
  73. X    int new;
  74. X    int fn = altmenu == F_MNU3 ? 3 : altmenu == F_MNU2 ? 1 : 0;
  75. X
  76. X    ask:
  77. X    flds[2]= newhzn ? "Standard hzn)" : "Adaptive hzn)";
  78. X    flds[4]= newgeoc? "Geocentric)" : "Topocentric)";
  79. X
  80. X    switch (popup (flds, fn, 5)) {
  81. X    case 0: newmenu = F_MNU1; break;
  82. X    case 1: newmenu = F_MNU2; break;
  83. X    case 2: newhzn ^= 1; fn = 2; goto ask;
  84. X    case 3: newmenu = F_MNU3; break;
  85. X    case 4: newgeoc ^= 1; fn = 4; goto ask;
  86. X    default: return (-1);
  87. X    }
  88. X
  89. X    new = 0;
  90. X    if (newmenu != altmenu) {
  91. X        altmenu = newmenu;
  92. X        new++;
  93. X    }
  94. X    if (newhzn != alt2_stdhzn) {
  95. X        alt2_stdhzn = newhzn;
  96. X        if (newmenu == F_MNU2)
  97. X        new++;
  98. X    }
  99. X    if (newgeoc != alt3_geoc) {
  100. X        alt3_geoc = newgeoc;
  101. X        if (newmenu == F_MNU3)
  102. X        new++;
  103. X    }
  104. X    return (new ? 0 : -1);
  105. X}
  106. X
  107. X/* erase the info for the given planet */
  108. Xalt_nobody (p)
  109. Xint p;
  110. X{
  111. X    f_eol (bodyrow[p], C_RA);
  112. X}
  113. X
  114. Xalt_body (b, force, np)
  115. Xint b;        /* which body, ala astro.h and screen.h defines */
  116. Xint force;    /* if !0 then draw for sure, else just if changed since last */
  117. XNow *np;
  118. X{
  119. X    switch (altmenu) {
  120. X    case F_MNU1: alt1_body (b, force, np); break;
  121. X    case F_MNU2: alt2_body (b, force, np); break;
  122. X    case F_MNU3: alt3_body (b, force, np); break;
  123. X    }
  124. X}
  125. X
  126. X/* draw the labels for the current alternate menu format */
  127. Xalt_labels ()
  128. X{
  129. X    switch (altmenu) {
  130. X    case F_MNU1: alt1_labels (); break;
  131. X    case F_MNU2: alt2_labels (); break;
  132. X    case F_MNU3: alt3_labels (); break;
  133. X    case F_MNUJ: altj_labels (); break;
  134. X    }
  135. X}
  136. X
  137. Xalt_erase ()
  138. X{
  139. X    int i;
  140. X
  141. X    for (i = R_PLANTAB; i <= NR; i++)
  142. X        f_eol (i, 1);
  143. X    f_string (R_ALTM, C_ALTMV, "             ");
  144. X}
  145. X
  146. Xalt_menumask()
  147. X{
  148. X    return (altmenu);
  149. X}
  150. X
  151. X/* handy function to return the next planet in the order in which they are
  152. X * displayed in the lower half of the screen.
  153. X * input is a given planet, return is the next planet.
  154. X * if input is not legal, then first planet is returned; when input is the
  155. X * last planet, then -1 is returned.
  156. X * typical usage is something like:
  157. X *   for (p = nxtbody(-1); p != -1; p = nxtbody(p))
  158. X */
  159. Xnxtbody(p)
  160. Xint p;
  161. X{
  162. X    static short nxtpl[NOBJ] = {
  163. X        VENUS, MARS, JUPITER, SATURN, URANUS,
  164. X        NEPTUNE, PLUTO, OBJX, MOON, MERCURY, OBJY, -1
  165. X    };
  166. X
  167. X    if (p < MERCURY || p >= NOBJ)
  168. X        return (SUN);
  169. X    else
  170. X        return (nxtpl[p]);
  171. X}
  172. X
  173. Xalt_plnames()
  174. X{
  175. X    f_string (R_PLANTAB,    C_OBJ,    "OCX");
  176. X    f_string (R_SUN,    C_OBJ,    "Su");
  177. X    f_string (R_MOON,    C_OBJ,    "Mo");
  178. X    f_string (R_MERCURY,    C_OBJ,    "Me");
  179. X    f_string (R_VENUS,    C_OBJ,    "Ve");
  180. X    f_string (R_MARS,    C_OBJ,    "Ma");
  181. X    f_string (R_JUPITER,    C_OBJ,    "Ju");
  182. X    f_string (R_SATURN,    C_OBJ,    "Sa");
  183. X    f_string (R_URANUS,    C_OBJ,    "Ur");
  184. X    f_string (R_NEPTUNE,    C_OBJ,    "Ne");
  185. X    f_string (R_PLUTO,    C_OBJ,    "Pl");
  186. X    f_string (R_OBJX,    C_OBJ,    "X");
  187. X    f_string (R_OBJY,    C_OBJ,    "Y");
  188. X}
  189. X
  190. Xstatic
  191. Xalt1_labels()
  192. X{
  193. X    f_string (R_ALTM, C_ALTMV, "  Planet Data");
  194. X
  195. X    alt_plnames();
  196. X    f_string (R_PLANTAB,    C_RA+2,    "R.A.");
  197. X    f_string (R_PLANTAB,    C_DEC+2,"Dec");
  198. X    f_string (R_PLANTAB,    C_AZ+2,    "Az");
  199. X    f_string (R_PLANTAB,    C_ALT+2,"Alt");
  200. X    f_string (R_PLANTAB,    C_HLONG,"H Long");
  201. X    f_string (R_PLANTAB,    C_HLAT,    "H Lat");
  202. X    f_string (R_PLANTAB,    C_EDIST,"Ea Dst");
  203. X    f_string (R_PLANTAB,    C_SDIST,"Sn Dst");
  204. X    f_string (R_PLANTAB,    C_ELONG,"Elong");
  205. X    f_string (R_PLANTAB,    C_SIZE,    "Size");
  206. X    f_string (R_PLANTAB,    C_MAG,    "VMag");
  207. X    f_string (R_PLANTAB,    C_PHASE,"Phs");
  208. X}
  209. X
  210. Xstatic
  211. Xalt2_labels()
  212. X{
  213. X    f_string (R_ALTM, C_ALTMV, "Rise/Set Info");
  214. X
  215. X    alt_plnames();
  216. X    f_string (R_PLANTAB,    C_RISETM-2,    "Rise Time");
  217. X    f_string (R_PLANTAB,    C_RISEAZ,    "Rise Az");
  218. X    f_string (R_PLANTAB,    C_TRANSTM-2,    "Trans Time");
  219. X    f_string (R_PLANTAB,    C_TRANSALT-1,    "Trans Alt");
  220. X    f_string (R_PLANTAB,    C_SETTM-1,    "Set Time");
  221. X    f_string (R_PLANTAB,    C_SETAZ,    "Set Az");
  222. X    f_string (R_PLANTAB,    C_TUP-1,    "Hours Up");
  223. X}
  224. X
  225. Xstatic
  226. Xalt3_labels()
  227. X{
  228. X    f_string (R_ALTM, C_ALTMV, "  Separations");
  229. X
  230. X    alt_plnames();
  231. X    f_string (R_PLANTAB,    C_SUN,        " Sun");
  232. X    f_string (R_PLANTAB,    C_MOON,        "Moon");
  233. X    f_string (R_PLANTAB,    C_MERCURY,    "Merc");
  234. X    f_string (R_PLANTAB,    C_VENUS,    "Venus");
  235. X    f_string (R_PLANTAB,    C_MARS,        "Mars");
  236. X    f_string (R_PLANTAB,    C_JUPITER,    " Jup");
  237. X    f_string (R_PLANTAB,    C_SATURN,    " Sat");
  238. X    f_string (R_PLANTAB,    C_URANUS,    "Uranus");
  239. X    f_string (R_PLANTAB,    C_NEPTUNE,    " Nep");
  240. X    f_string (R_PLANTAB,    C_PLUTO,    "Pluto");
  241. X    f_string (R_PLANTAB,    C_OBJX,        "  X");
  242. X    f_string (R_PLANTAB,    C_OBJY,        "  Y");
  243. X}
  244. X
  245. X/* print body info in first menu format */
  246. Xstatic
  247. Xalt1_body (p, force, np)
  248. Xint p;        /* which body, as in astro.h/screen.h defines */
  249. Xint force;    /* whether to print for sure or only if things have changed */
  250. XNow *np;
  251. X{
  252. X    Sky sky;
  253. X    double as = plot_ison() || srch_ison() ? 0.0 : 60.0;
  254. X    int row = bodyrow[p];
  255. X
  256. X    if (body_cir (p, as, np, &sky) || force) {
  257. X        f_ra (row, C_RA, sky.s_ra);
  258. X        f_angle (row, C_DEC, sky.s_dec);
  259. X        if (sky.s_hlong != NOHELIO) {
  260. X        f_angle (row, C_HLONG, sky.s_hlong);
  261. X        if (p != SUN)
  262. X            f_angle (row, C_HLAT, sky.s_hlat);
  263. X        }
  264. X
  265. X        if (p == MOON) {
  266. X        /* distance is on km, show in miles */
  267. X        f_double (R_MOON, C_EDIST, "%6.0f", sky.s_edist/1.609344);
  268. X        } else if (sky.s_edist > 0.0) {
  269. X        /* show distance in au */
  270. X        f_double (row, C_EDIST,(sky.s_edist>=10.0)?"%6.3f":"%6.4f",
  271. X                                sky.s_edist);
  272. X        }
  273. X        if (sky.s_sdist > 0.0)
  274. X        f_double (row, C_SDIST, (sky.s_sdist>=9.99995)?"%6.3f":"%6.4f",
  275. X                                sky.s_sdist);
  276. X        if (p != SUN)
  277. X        f_double (row, C_ELONG, "%6.1f", sky.s_elong);
  278. X        f_double (row, C_SIZE, sky.s_size >= 99.95 ?"%4.0f":"%4.1f",
  279. X                                sky.s_size);
  280. X        f_double (row, C_MAG, sky.s_mag <= -9.95 ? "%4.0f" : "%4.1f",
  281. X                                sky.s_mag);
  282. X        if (sky.s_sdist > 0.0) {
  283. X        /* some terminals scroll when write a char in low-right corner.
  284. X         * TODO: is there a nicer way to handle this maybe?
  285. X         */
  286. X        int col = row == NR ? C_PHASE - 1 : C_PHASE;
  287. X        /* would just do this if Turbo-C 2.0 "%?.0f" worked:
  288. X         * f_double (row, col, "%3.0f", sky.s_phase);
  289. X         */
  290. X        f_int (row, col, "%3d", sky.s_phase);
  291. X        }
  292. X    }
  293. X
  294. X    f_angle (row, C_AZ, sky.s_az);
  295. X    f_angle (row, C_ALT, sky.s_alt);
  296. X}
  297. X
  298. X/* print body info in the second menu format */
  299. Xstatic
  300. Xalt2_body (p, force, np)
  301. Xint p;        /* which body, as in astro.h/screen.h defines */
  302. Xint force;    /* whether to print for sure or only if things have changed */
  303. XNow *np;
  304. X{
  305. X    double ltr, lts, ltt, azr, azs, altt;
  306. X    int row = bodyrow[p];
  307. X    int status;
  308. X    double tmp;
  309. X    int today_tup = 0;
  310. X
  311. X    /* always recalc OBJX and Y since we don't know it's the same object */
  312. X    if (!riset_cir (p, np, p==OBJX || p==OBJY, alt2_stdhzn?STDHZN:ADPHZN,
  313. X        <r, <s, <t, &azr, &azs, &altt, &status) && !force)
  314. X        return;
  315. X
  316. X    alt_nobody (p);
  317. X
  318. X    if (status & RS_ERROR) {
  319. X        /* can not find where body is! */
  320. X        f_string (row, C_RISETM, "?Error?");
  321. X        return;
  322. X    }
  323. X    if (status & RS_CIRCUMPOLAR) {
  324. X        /* body is up all day */
  325. X        f_string (row, C_RISETM, "Circumpolar");
  326. X        if (status & RS_NOTRANS)
  327. X        f_string (row, C_TRANSTM, "No transit");
  328. X        else {
  329. X        f_mtime (row, C_TRANSTM, ltt);
  330. X        if (status & RS_2TRANS)
  331. X            f_char (row, C_TRANSTM+5, '+');
  332. X        f_angle (row, C_TRANSALT, altt);
  333. X        }
  334. X        f_string (row, C_TUP, "24:00"); /*f_mtime() changes to 0:00 */
  335. X        return;
  336. X    }
  337. X    if (status & RS_NEVERUP) {
  338. X        /* body never up at all today */
  339. X        f_string (row, C_RISETM, "Never up");
  340. X        f_mtime (row, C_TUP, 0.0);
  341. X        return;
  342. X    }
  343. X
  344. X    if (status & RS_NORISE) {
  345. X        /* object does not rise as such today */
  346. X        f_string (row, C_RISETM, "Never rises");
  347. X        ltr = 0.0; /* for TUP */
  348. X        today_tup = 1;
  349. X    } else {
  350. X        f_mtime (row, C_RISETM, ltr);
  351. X        if (status & RS_2RISES) {
  352. X        /* object rises more than once today */
  353. X        f_char (row, C_RISETM+5, '+');
  354. X        }
  355. X        f_angle (row, C_RISEAZ, azr);
  356. X    }
  357. X
  358. X    if (status & RS_NOTRANS)
  359. X        f_string (row, C_TRANSTM, "No transit");
  360. X    else {
  361. X        f_mtime (row, C_TRANSTM, ltt);
  362. X        if (status & RS_2TRANS)
  363. X        f_char (row, C_TRANSTM+5, '+');
  364. X        f_angle (row, C_TRANSALT, altt);
  365. X    }
  366. X
  367. X    if (status & RS_NOSET) {
  368. X        /* object does not set as such today */
  369. X        f_string (row, C_SETTM, "Never sets");
  370. X        lts = 24.0;    /* for TUP */
  371. X        today_tup = 1;
  372. X    } else {
  373. X        f_mtime (row, C_SETTM, lts);
  374. X        if (status & RS_2SETS)
  375. X        f_char (row, C_SETTM+5, '+');
  376. X        f_angle (row, C_SETAZ, azs);
  377. X    }
  378. X
  379. X    tmp = lts - ltr;
  380. X    if (tmp < 0)
  381. X        tmp = 24.0 + tmp;
  382. X    f_mtime (row, C_TUP, tmp);
  383. X    if (today_tup)
  384. X        f_char (row, C_TUP+5, '+');
  385. X}
  386. X
  387. X/* print body info in third menu format. this may be either the geocentric
  388. X *   or topocentric angular separation between object p and each of the others.
  389. X *   the latter, of course, includes effects of refraction and so can change
  390. X *   quite rapidly near the time of each planets rise or set.
  391. X * for now, we don't save old values so we always redo everything and ignore
  392. X *  the "force" argument. this isn't that bad since body_cir() has memory and
  393. X *   will avoid most computations as we hit them again in the lower triangle.
  394. X * we are limited to only 5 columns per object. to make it fit, we display
  395. X *   degrees:minutes if less than 100 degrees, otherwise just whole degrees.
  396. X */
  397. X/*ARGSUSED*/
  398. Xstatic
  399. Xalt3_body (p, force, np)
  400. Xint p;        /* which body, as in astro.h/screen.h defines */
  401. Xint force;    /* whether to print for sure or only if things have changed */
  402. XNow *np;
  403. X{
  404. X    int row = bodyrow[p];
  405. X    Sky skyp, skyq;
  406. X    double spy, cpy, px, *qx, *qy;
  407. X    int wantx = obj_ison(OBJX);
  408. X    int wanty = obj_ison(OBJY);
  409. X    double as = plot_ison() || srch_ison() ? 0.0 : 60.0;
  410. X    int q;
  411. X
  412. X    (void) body_cir (p, as, np, &skyp);
  413. X    if (alt3_geoc) {
  414. X        /* use ra for "x", dec for "y". */
  415. X        spy = sin (skyp.s_dec);
  416. X        cpy = cos (skyp.s_dec);
  417. X        px = skyp.s_ra;
  418. X        qx = &skyq.s_ra;
  419. X        qy = &skyq.s_dec;
  420. X    } else {
  421. X        /* use azimuth for "x", altitude for "y". */
  422. X        spy = sin (skyp.s_alt);
  423. X        cpy = cos (skyp.s_alt);
  424. X        px = skyp.s_az;
  425. X        qx = &skyq.s_az;
  426. X        qy = &skyq.s_alt;
  427. X    }
  428. X    for (q = nxtbody(-1); q != -1; q = nxtbody(q))
  429. X        if (q != p && (q != OBJX || wantx) && (q != OBJY || wanty)) {
  430. X        double sep, dsep;
  431. X        (void) body_cir (q, as, np, &skyq);
  432. X        sep = acos(spy*sin(*qy) + cpy*cos(*qy)*cos(px-*qx));
  433. X        dsep = raddeg(sep);
  434. X        if (dsep >= (100.0 - 1.0/60.0/2.0))
  435. X            f_int (row, bodycol[q], "%5d:", dsep);
  436. X        else
  437. X            f_angle (row, bodycol[q], sep);
  438. X        }
  439. X}
  440. END_OF_FILE
  441.   if test 11329 -ne `wc -c <'altmenus.c'`; then
  442.     echo shar: \"'altmenus.c'\" unpacked with wrong size!
  443.   fi
  444.   # end of 'altmenus.c'
  445. fi
  446. if test -f 'flog.c' -a "${1}" != "-c" ; then 
  447.   echo shar: Will not clobber existing file \"'flog.c'\"
  448. else
  449.   echo shar: Extracting \"'flog.c'\" \(3241 characters\)
  450.   sed "s/^X//" >'flog.c' <<'END_OF_FILE'
  451. X/* this is a simple little package to manage the saving and retrieving of
  452. X * field values, which we call field logging or "flogs". a flog consists of a
  453. X * field location, ala rcfpack(), its value as a double and its value as
  454. X * a string (ie, however it was printed). you can reset the list of flogs, add
  455. X * to and remove from the list of registered fields and log a field if it has
  456. X * been registered.
  457. X *
  458. X * this is used by the plotting and searching facilities of ephem to maintain
  459. X * the values of the fields that are being plotted or used in search
  460. X * expressions. it is used by the listing facility to generate listing files.
  461. X *
  462. X * a field can be in use for more than one
  463. X * thing at a time (eg, all the X plot values may the same time field, or
  464. X * searching and plotting might be on at one time using the same field) so
  465. X * we consider the field to be in use as long a usage count is > 0.
  466. X */
  467. X
  468. X#include "screen.h"
  469. X
  470. Xextern char *strcpy(), *strncpy();
  471. X
  472. X#define    NFLOGS    32        /* max number of distinct simultaneous logged
  473. X                 * fields
  474. X                 */
  475. X
  476. Xtypedef struct {
  477. X    int fl_usagecnt;    /* number of "users" logging to this field */
  478. X    int fl_fld;        /* an rcfpack(r,c,0) */
  479. X    double fl_val;        /* stored value as a double */
  480. X    char fl_str[16];    /* stored value as a formatted string.
  481. X                 * N.B.: never overwrite last char: keep as \0
  482. X                 */
  483. X} FLog;
  484. X
  485. Xstatic FLog flog[NFLOGS];
  486. X
  487. X/* add fld to the list. if already there, just increment usage count.
  488. X * return 0 if ok, else -1 if no more room.
  489. X */
  490. Xflog_add (fld)
  491. Xint fld;
  492. X{
  493. X    FLog *flp, *unusedflp = 0;
  494. X
  495. X    /* scan for fld already in list, or find an unused one along the way */
  496. X    for (flp = &flog[NFLOGS]; --flp >= flog; ) {
  497. X        if (flp->fl_usagecnt > 0) {
  498. X        if (flp->fl_fld == fld) {
  499. X            flp->fl_usagecnt++;
  500. X            return (0);
  501. X        }
  502. X        } else
  503. X        unusedflp = flp;
  504. X    }
  505. X    if (unusedflp) {
  506. X        unusedflp->fl_fld = fld;
  507. X        unusedflp->fl_usagecnt = 1;
  508. X        return (0);
  509. X    }
  510. X    return (-1);
  511. X}
  512. X
  513. X/* decrement usage count for flog for fld. if goes to 0 take it out of list.
  514. X * ok if not in list i guess...
  515. X */
  516. Xflog_delete (fld)
  517. Xint fld;
  518. X{
  519. X    FLog *flp;
  520. X
  521. X    for (flp = &flog[NFLOGS]; --flp >= flog; )
  522. X        if (flp->fl_fld == fld && flp->fl_usagecnt > 0) {
  523. X        if (--flp->fl_usagecnt <= 0) {
  524. X            flp->fl_usagecnt = 0;
  525. X        }
  526. X        break;
  527. X        }
  528. X}
  529. X
  530. X/* if plotting, listing or searching is active then
  531. X * if rcfpack(r,c,0) is in the fld list, set its value to val.
  532. X * return 0 if ok, else -1 if not in list.
  533. X */
  534. Xflog_log (r, c, val, str)
  535. Xint r, c;
  536. Xdouble val;
  537. Xchar *str;
  538. X{
  539. X    if (plot_ison() || listing_ison() || srch_ison()) {
  540. X        FLog *flp;
  541. X        int fld = rcfpack (r, c, 0);
  542. X        for (flp = &flog[NFLOGS]; --flp >= flog; )
  543. X        if (flp->fl_fld == fld && flp->fl_usagecnt > 0) {
  544. X            flp->fl_val = val;
  545. X            (void) strncpy (flp->fl_str, str, sizeof(flp->fl_str)-1);
  546. X            return(0);
  547. X        }
  548. X        return (-1);
  549. X    } else
  550. X        return (0);
  551. X}
  552. X
  553. X/* search for fld in list. if find it, return its value and str, if str.
  554. X * return 0 if found it, else -1 if not in list.
  555. X */
  556. Xflog_get (fld, vp, str)
  557. Xint fld;
  558. Xdouble *vp;
  559. Xchar *str;
  560. X{
  561. X    FLog *flp;
  562. X
  563. X    for (flp = &flog[NFLOGS]; --flp >= flog; )
  564. X        if (flp->fl_fld == fld && flp->fl_usagecnt > 0) {
  565. X        *vp = flp->fl_val;
  566. X        if (str) 
  567. X            (void) strcpy (str, flp->fl_str);
  568. X        return (0);
  569. X        }
  570. X    return (-1);
  571. X}
  572. END_OF_FILE
  573.   if test 3241 -ne `wc -c <'flog.c'`; then
  574.     echo shar: \"'flog.c'\" unpacked with wrong size!
  575.   fi
  576.   # end of 'flog.c'
  577. fi
  578. if test -f 'formats.c' -a "${1}" != "-c" ; then 
  579.   echo shar: Will not clobber existing file \"'formats.c'\"
  580. else
  581.   echo shar: Extracting \"'formats.c'\" \(7430 characters\)
  582.   sed "s/^X//" >'formats.c' <<'END_OF_FILE'
  583. X/* basic formating routines.
  584. X * all the screen oriented printing should go through here.
  585. X */
  586. X
  587. X#include <stdio.h>
  588. X#include <math.h>
  589. X#include <ctype.h>
  590. X#ifdef VMS
  591. X#include <stdlib.h>
  592. X#endif
  593. X#include "astro.h"
  594. X#include "screen.h"
  595. X
  596. Xextern char *strcpy();
  597. X
  598. X/* suppress screen io if this is true, but always flog stuff.
  599. X */
  600. Xstatic int f_scrnoff;
  601. Xf_on ()
  602. X{
  603. X    f_scrnoff = 0;
  604. X}
  605. Xf_off ()
  606. X{
  607. X    f_scrnoff = 1;
  608. X}
  609. X
  610. X/* draw n blanks at the given cursor position.  */
  611. Xf_blanks (r, c, n)
  612. Xint r, c, n;
  613. X{
  614. X    if (f_scrnoff)
  615. X        return;
  616. X    c_pos (r, c);
  617. X    while (--n >= 0)
  618. X        putchar (' ');
  619. X}
  620. X
  621. X/* print the given value, v, in "sexadecimal" format at [r,c]
  622. X * ie, in the form A:m.P, where A is a digits wide, P is p digits.
  623. X * if p == 0, then no decimal point either.
  624. X */
  625. Xf_sexad (r, c, a, p, mod, v)
  626. Xint r, c;
  627. Xint a, p;    /* left space, min precision */
  628. Xint mod;    /* don't let whole portion get this big */
  629. Xdouble v;
  630. X{
  631. X    char astr[32], str[32];
  632. X    long dec;
  633. X    double frac;
  634. X    int visneg;
  635. X    double vsav = v;
  636. X
  637. X    if (v >= 0.0)
  638. X        visneg = 0;
  639. X    else {
  640. X        if (v <= -0.5/60.0*pow(10.0,-1.0*p)) {
  641. X        v = -v;
  642. X        visneg = 1;
  643. X        } else {
  644. X        /* don't show as negative if less than the precision showing */
  645. X        v = 0.0;
  646. X        visneg = 0;
  647. X        }
  648. X    }
  649. X
  650. X    dec = v;
  651. X    frac = (v - dec)*60.0;
  652. X    (void) sprintf (str, "59.%.*s5", p, "999999999");
  653. X    if (frac >= atof (str)) {
  654. X        dec += 1;
  655. X        frac = 0.0;
  656. X    }
  657. X    dec %= mod;
  658. X    if (dec == 0 && visneg)
  659. X        (void) strcpy (str, "-0");
  660. X    else
  661. X        (void) sprintf (str, "%ld", visneg ? -dec : dec);
  662. X
  663. X    /* would just do this if Turbo-C 2.0 %?.0f" worked:
  664. X     * sprintf (astr, "%*s:%0*.*f", a, str, p == 0 ? 2 : p+3, p, frac);
  665. X     */
  666. X    if (p == 0)
  667. X        (void) sprintf (astr, "%*s:%02d", a, str, (int)(frac+0.5));
  668. X    else
  669. X        (void) sprintf (astr, "%*s:%0*.*f", a, str, p+3, p, frac);
  670. X
  671. X    (void) flog_log (r, c, vsav, astr);
  672. X
  673. X    f_string (r, c, astr);
  674. X}
  675. X
  676. X/* print the given value, t, in sexagesimal format at [r,c]
  677. X * ie, in the form T:mm:ss, where T is nd digits wide.
  678. X * N.B. we assume nd >= 2.
  679. X */
  680. Xf_sexag (r, c, nd, t)
  681. Xint r, c, nd;
  682. Xdouble t;
  683. X{
  684. X    char tstr[32];
  685. X    int h, m, s;
  686. X    int tisneg;
  687. X    
  688. X    dec_sex (t, &h, &m, &s, &tisneg);
  689. X    if (h == 0 && tisneg)
  690. X        (void) sprintf (tstr, "%*s-0:%02d:%02d", nd-2, "", m, s);
  691. X    else
  692. X        (void) sprintf (tstr, "%*d:%02d:%02d", nd, tisneg ? -h : h, m, s);
  693. X
  694. X    (void) flog_log (r, c, t, tstr);
  695. X    f_string (r, c, tstr);
  696. X}
  697. X
  698. X/* print angle ra, in radians, in ra hours as hh:mm.m at [r,c]
  699. X * N.B. we assume ra is >= 0.
  700. X */
  701. Xf_ra (r, c, ra)
  702. Xint r, c;
  703. Xdouble ra;
  704. X{
  705. X    f_sexad (r, c, 2, 1, 24, radhr(ra));
  706. X}
  707. X
  708. X/* print time, t, as hh:mm:ss */
  709. Xf_time (r, c, t)
  710. Xint r, c;
  711. Xdouble t;
  712. X{
  713. X    f_sexag (r, c, 2, t);
  714. X}
  715. X
  716. X/* print time, t, as +/-hh:mm:ss (don't show leading +) */
  717. Xf_signtime (r, c, t)
  718. Xint r, c;
  719. Xdouble t;
  720. X{
  721. X    f_sexag (r, c, 3, t);
  722. X}
  723. X
  724. X/* print time, t, as hh:mm */
  725. Xf_mtime (r, c, t)
  726. Xint r, c;
  727. Xdouble t;
  728. X{
  729. X    f_sexad (r, c, 2, 0, 24, t);
  730. X}
  731. X
  732. X/* print angle, a, in rads, as degress at [r,c] in form ddd:mm */
  733. Xf_angle(r, c, a)
  734. Xint r, c;
  735. Xdouble a;
  736. X{
  737. X    f_sexad (r, c, 3, 0, 360, raddeg(a));
  738. X}
  739. X
  740. X/* print angle, a, in rads, as degress at [r,c] in form dddd:mm:ss */
  741. Xf_gangle(r, c, a)
  742. Xint r, c;
  743. Xdouble a;
  744. X{
  745. X    f_sexag (r, c, 4, raddeg(a));
  746. X}
  747. X
  748. X/* print the given modified Julian date, jd, as the starting date at [r,c]
  749. X * in the form mm/dd/yyyy.
  750. X */
  751. Xf_date (r, c, jd)
  752. Xint r, c;
  753. Xdouble jd;
  754. X{
  755. X    char dstr[32];
  756. X    int m, y;
  757. X    double d, tmp;
  758. X
  759. X    mjd_cal (jd, &m, &d, &y);
  760. X    (void) sprintf (dstr, "%2d/%02d/%-4d", m, (int)(d), y);
  761. X
  762. X    /* shadow to the plot subsystem as years. */
  763. X    mjd_year (jd, &tmp);
  764. X    (void) flog_log (r, c, tmp, dstr);
  765. X    f_string (r, c, dstr);
  766. X}
  767. X
  768. X/* print the given double as a rounded int, with the given format.
  769. X * this is used to plot full precision, but display far less.
  770. X * N.B. caller beware that we really do expect fmt to refer to an int, not
  771. X *   a long for example. also beware of range that implies.
  772. X */
  773. Xf_int (row, col, fmt, f)
  774. Xint row, col;
  775. Xchar fmt[];
  776. Xdouble f;
  777. X{
  778. X    char str[80];
  779. X    int i;
  780. X
  781. X    i = (f < 0) ? (int)(f-0.5) : (int)(f+0.5);
  782. X    (void) sprintf (str, fmt, i);
  783. X
  784. X    (void) flog_log (row, col, f, str);
  785. X    f_string (row, col, str);
  786. X}
  787. X
  788. Xf_char (row, col, c)
  789. Xint row, col;
  790. Xchar c;
  791. X{
  792. X    if (f_scrnoff)
  793. X        return;
  794. X    c_pos (row, col);
  795. X    putchar (c);
  796. X}
  797. X
  798. Xf_string (r, c, s)
  799. Xint r, c;
  800. Xchar *s;
  801. X{
  802. X    if (f_scrnoff)
  803. X        return;
  804. X    c_pos (r, c);
  805. X    (void) fputs (s, stdout);
  806. X}
  807. X
  808. Xf_double (r, c, fmt, f)
  809. Xint r, c;
  810. Xchar *fmt;
  811. Xdouble f;
  812. X{
  813. X    char str[80];
  814. X    (void) sprintf (str, fmt, f);
  815. X    (void) flog_log (r, c, f, str);
  816. X    f_string (r, c, str);
  817. X}
  818. X
  819. X/* print prompt line */
  820. Xf_prompt (p)
  821. Xchar *p;
  822. X{
  823. X    c_pos (R_PROMPT, C_PROMPT);
  824. X    c_eol ();
  825. X    c_pos (R_PROMPT, C_PROMPT);
  826. X    (void) fputs (p, stdout);
  827. X}
  828. X
  829. X/* clear from [r,c] to end of line, if we are drawing now. */
  830. Xf_eol (r, c)
  831. Xint r, c;
  832. X{
  833. X    if (!f_scrnoff) {
  834. X        c_pos (r, c);
  835. X        c_eol();
  836. X    }
  837. X}
  838. X
  839. X/* print a message and wait for op to hit any key */
  840. Xf_msg (m)
  841. Xchar *m;
  842. X{
  843. X    f_prompt (m);
  844. X    (void) read_char();
  845. X}
  846. X
  847. X/* crack a line of the form X?X?X into its components,
  848. X *   where X is an integer and ? can be any character except '0-9' or '-',
  849. X *   such as ':' or '/'.
  850. X * only change those fields that are specified:
  851. X *   eg:  ::10    only changes *s
  852. X *        10    only changes *d
  853. X *        10:0  changes *d and *m
  854. X * if see '-' anywhere, first non-zero component will be made negative.
  855. X */
  856. Xf_sscansex (bp, d, m, s)
  857. Xchar *bp;
  858. Xint *d, *m, *s;
  859. X{
  860. X    char c;
  861. X    int *p = d;
  862. X    int *nonzp = 0;
  863. X    int sawneg = 0;
  864. X    int innum = 0;
  865. X
  866. X    while (c = *bp++)
  867. X        if (isdigit(c)) {
  868. X        if (!innum) {
  869. X            *p = 0;
  870. X            innum = 1;
  871. X        }
  872. X        *p = *p*10 + (c - '0');
  873. X        if (*p && !nonzp)
  874. X            nonzp = p;
  875. X        } else if (c == '-') {
  876. X        sawneg = 1;
  877. X        } else if (c != ' ') {
  878. X        /* advance to next component */
  879. X        p = (p == d) ? m : s;
  880. X        innum = 0;
  881. X        }
  882. X
  883. X    if (sawneg && nonzp)
  884. X        *nonzp = -*nonzp;
  885. X}
  886. X
  887. X/* crack a floating date string, bp, of the form m/d/y, where d may be a
  888. X *   floating point number, into its components.
  889. X * leave any component unspecified unchanged.
  890. X * actually, the slashes may be anything but digits or a decimal point.
  891. X * this is functionally the same as f_sscansex() exept we allow for
  892. X *   the day portion to be real, and we don't handle negative numbers.
  893. X *   maybe someday we could make a combined one and use it everywhere.
  894. X */
  895. Xf_sscandate (bp, m, d, y)
  896. Xchar *bp;
  897. Xint *m, *y;
  898. Xdouble *d;
  899. X{
  900. X    char *bp0, c;
  901. X
  902. X    bp0 = bp;
  903. X    while ((c = *bp++) && isdigit(c))
  904. X        continue;
  905. X    if (bp > bp0+1)
  906. X        *m = atoi (bp0);
  907. X    if (c == '\0')
  908. X        return;
  909. X    bp0 = bp;
  910. X    while ((c = *bp++) && (isdigit(c) || c == '.'))
  911. X        continue;
  912. X    if (bp > bp0+1)
  913. X        *d = atof (bp0);
  914. X    if (c == '\0')
  915. X        return;
  916. X    bp0 = bp;
  917. X    while (c = *bp++)
  918. X        continue;
  919. X    if (bp > bp0+1)
  920. X        *y = atoi (bp0);
  921. X}
  922. X
  923. X/* just like dec_sex() but makes the first non-zero element negative if
  924. X * x is negative (instead of returning a sign flag).
  925. X */
  926. Xf_dec_sexsign (x, h, m, s)
  927. Xdouble x;
  928. Xint *h, *m, *s;
  929. X{
  930. X    int n;
  931. X    dec_sex (x, h, m, s, &n);
  932. X    if (n) {
  933. X        if (*h)
  934. X        *h = -*h;
  935. X        else if (*m)
  936. X        *m = -*m;
  937. X        else
  938. X        *s = -*s;
  939. X    }
  940. X}
  941. X
  942. X/* return 1 if bp looks like a decimal year; else 0.
  943. X * any number greater than 12 or less than 0 is assumed to be a year, or any
  944. X * string with exactly one decimal point, an optional minus sign, and nothing
  945. X * else but digits.
  946. X */
  947. Xdecimal_year (bp)
  948. Xchar *bp;
  949. X{
  950. X    char c;
  951. X    int ndig = 0, ndp = 0, nneg = 0, nchar = 0;
  952. X    double y = atof(bp);
  953. X
  954. X    while (c = *bp++) {
  955. X        nchar++;
  956. X        if (isdigit(c))
  957. X        ndig++;
  958. X        else if (c == '.')
  959. X        ndp++;
  960. X        else if (c == '-')
  961. X        nneg++;
  962. X    }
  963. X
  964. X    return (y > 12 || y < 0
  965. X            || (ndp == 1 && nneg <= 1 && nchar == ndig+ndp+nneg));
  966. X}
  967. END_OF_FILE
  968.   if test 7430 -ne `wc -c <'formats.c'`; then
  969.     echo shar: \"'formats.c'\" unpacked with wrong size!
  970.   fi
  971.   # end of 'formats.c'
  972. fi
  973. if test -f 'listing.c' -a "${1}" != "-c" ; then 
  974.   echo shar: Will not clobber existing file \"'listing.c'\"
  975. else
  976.   echo shar: Extracting \"'listing.c'\" \(7576 characters\)
  977.   sed "s/^X//" >'listing.c' <<'END_OF_FILE'
  978. X/* code to support the listing capabilities.
  979. X * idea is to let the operator name a listing file and mark some fields for
  980. X * logging. then after each screen update, the logged fields are written to
  981. X * the listing file in the same manner as they appeared on the screen.
  982. X * 
  983. X * format of the listing file is one line per screen update.
  984. X */
  985. X
  986. X#include <stdio.h>
  987. X#include <math.h>
  988. X#include "screen.h"
  989. X
  990. Xextern char *strcpy();
  991. X
  992. X#ifdef VMS
  993. X#include <perror.h>
  994. X#include <errno.h>
  995. X#else
  996. Xextern char *sys_errlist[];
  997. Xextern errno;
  998. X#endif
  999. X
  1000. X#define    errsys    (sys_errlist[errno])
  1001. X
  1002. X
  1003. X#define    TRACE(x)    {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);}
  1004. X
  1005. X#define    MAXLSTFLDS    10    /* max number of fields we can track.
  1006. X                 * note we can't store more than NFLOGS fields
  1007. X                 * anyway (see flog.c).
  1008. X                 */
  1009. X#define    FNLEN        (14+1)    /* longest filename; plus 1 for \0 */
  1010. X
  1011. Xstatic char lst_filename[FNLEN] = "ephem.lst";    /* default plot file name */
  1012. Xstatic FILE *lst_fp;        /* the plot file; == 0 means don't plot */
  1013. X
  1014. X/* store rcfpack()s for each field to track, in l-to-r order */
  1015. Xstatic int lstflds[MAXLSTFLDS];
  1016. Xstatic int nlstflds;        /* number of lstflds[] in actual use */
  1017. X
  1018. Xstatic int lstsrchfld;        /* set when the Search field is to be listed */
  1019. X
  1020. X/* picked the Listing label:
  1021. X * if on, just turn it off.
  1022. X * if off, turn on, define fields or select name of file to list to and do it.
  1023. X * TODO: more flexibility, more relevance.
  1024. X */
  1025. Xlisting_setup()
  1026. X{
  1027. X    if (lst_fp)
  1028. X        lst_turn_off();
  1029. X    else {
  1030. X        static char *chcs[] = {
  1031. X        "Select fields", "Display a listing file", "Begin listing"
  1032. X        };
  1033. X        static int fn;    /* start with 0, then remember for next time */
  1034. X    ask:
  1035. X        switch (popup(chcs, fn, nlstflds > 0 ? 3 : 2)) {
  1036. X        case 0: fn = 0; lst_select_fields(); goto ask;
  1037. X        case 1: fn = 1; lst_file(); goto ask;
  1038. X        case 2: fn = 2; lst_turn_on(); break;
  1039. X        default: break;
  1040. X        }
  1041. X    }
  1042. X}
  1043. X
  1044. X/* write the active listing to the current listing file, if one is open. */
  1045. Xlisting()
  1046. X{
  1047. X    if (lst_fp) {
  1048. X        int n;
  1049. X        double flx;
  1050. X        char flstr[32];
  1051. X        if (!srch_ison() && lstsrchfld) {
  1052. X        /* if searching is not on but we are listing the search
  1053. X         * funtion we must evaluate and log it ourselves here and now.
  1054. X         * lst_turn_on() insured there is a good function to eval.
  1055. X         * N.B. if searching IS on, we rely on main() having called
  1056. X         * srch_eval() BEFORE plot() so it is already evaluated.
  1057. X         */
  1058. X        double e;
  1059. X        char errmsg[128];
  1060. X        if (execute_expr (&e, errmsg) < 0) {
  1061. X            f_msg (errmsg);
  1062. X            lst_turn_off();
  1063. X            return;
  1064. X        } else {
  1065. X            (void) sprintf (flstr, "%g", e);
  1066. X            (void) flog_log (R_SRCH, C_SRCH, e, flstr);
  1067. X        }
  1068. X        }
  1069. X
  1070. X        /* list in order of original selection */
  1071. X        for (n = 0; n < nlstflds; n++)
  1072. X        if (flog_get (lstflds[n], &flx, flstr) == 0)
  1073. X            (void) fprintf (lst_fp, "%s  ", flstr);
  1074. X        (void) fprintf (lst_fp, "\n");
  1075. X    }
  1076. X}
  1077. X
  1078. Xlisting_prstate (force)
  1079. Xint force;
  1080. X{
  1081. X    static last;
  1082. X    int this = lst_fp != 0;
  1083. X
  1084. X    if (force || this != last) {
  1085. X        f_string (R_LISTING, C_LISTINGV, this ? " on" : "off");
  1086. X        last = this;
  1087. X    }
  1088. X}
  1089. X
  1090. Xlisting_ison()
  1091. X{
  1092. X    return (lst_fp != 0);
  1093. X}
  1094. X
  1095. Xstatic
  1096. Xlst_reset()
  1097. X{
  1098. X    int *lp;
  1099. X
  1100. X    for (lp = lstflds; lp < &lstflds[nlstflds]; lp++) {
  1101. X        (void) flog_delete (*lp);
  1102. X        *lp = 0;
  1103. X    }
  1104. X    nlstflds = 0;
  1105. X    lstsrchfld = 0;
  1106. X}
  1107. X
  1108. X/* let operator select the fields he wants to have in his listing.
  1109. X * register them with flog and keep rcfpack() in lstflds[] array.
  1110. X * as a special case, set lstsrchfld if Search field is selected.
  1111. X */
  1112. Xstatic
  1113. Xlst_select_fields()
  1114. X{
  1115. X    static char hlp[] = "move and RETURN to select a field, or q to quit";
  1116. X    static char sry[] = "Sorry; can not list any more fields.";
  1117. X    int f = rcfpack(R_UT,C_UTV,0); /* TODO: start where main was? */
  1118. X    int sf = rcfpack (R_SRCH,C_SRCH,0);
  1119. X    char buf[64];
  1120. X    int i;
  1121. X
  1122. X    lst_reset();
  1123. X    for (i = 0; i < MAXLSTFLDS; i++) {
  1124. X        (void) sprintf(buf,"select field for column %d or q to quit", i+1);
  1125. X        f = sel_fld (f, alt_menumask()|F_PLT, buf, hlp);
  1126. X        if (!f)
  1127. X        break;
  1128. X        if (flog_add (f) < 0) {
  1129. X        f_msg (sry);
  1130. X        break;
  1131. X        }
  1132. X        lstflds[i] = f;
  1133. X        if (f == sf)
  1134. X        lstsrchfld = 1;
  1135. X    }
  1136. X    if (i == MAXLSTFLDS)
  1137. X        f_msg (sry);
  1138. X    nlstflds = i;
  1139. X}
  1140. X
  1141. Xstatic
  1142. Xlst_turn_off ()
  1143. X{
  1144. X    (void) fclose (lst_fp);
  1145. X    lst_fp = 0;
  1146. X    listing_prstate(0);
  1147. X}
  1148. X
  1149. X/* turn on listing facility.
  1150. X * establish a file to use (and thereby set lst_fp, the "listing-is-on" flag).
  1151. X * also check that there is a srch function if it is being used.
  1152. X */
  1153. Xstatic
  1154. Xlst_turn_on ()
  1155. X{
  1156. X    int sf = rcfpack(R_SRCH, C_SRCH, 0);
  1157. X    char fn[FNLEN], fnq[NC];
  1158. X    char *optype;
  1159. X    int n;
  1160. X
  1161. X    /* insure there is a valid srch function if we are to list it */
  1162. X    for (n = 0; n < nlstflds; n++)
  1163. X        if (lstflds[n] == sf && !prog_isgood()) {
  1164. X        f_msg ("Listing search function but it is not defined.");
  1165. X        return;
  1166. X        }
  1167. X
  1168. X    /* prompt for file name, giving current as default */
  1169. X    (void) sprintf (fnq, "file to write <%s>: ", lst_filename);
  1170. X    f_prompt (fnq);
  1171. X    n = read_line (fn, sizeof(fn)-1);
  1172. X
  1173. X    /* leave plotting off if type END.
  1174. X     * reuse same fn if just type \n
  1175. X     */
  1176. X    if (n < 0)
  1177. X        return;
  1178. X    if (n > 0)
  1179. X        (void) strcpy (lst_filename, fn);
  1180. X
  1181. X    /* give option to append if file already exists */
  1182. X    optype = "w";
  1183. X    if (access (lst_filename, 2) == 0) {
  1184. X        while (1) {
  1185. X        f_prompt ("files exists; append or overwrite (a/o)?: ");
  1186. X        n = read_char();
  1187. X        if (n == 'a') {
  1188. X            optype = "a";
  1189. X            break;
  1190. X        }
  1191. X        if (n == 'o')
  1192. X            break;
  1193. X        }
  1194. X    }
  1195. X
  1196. X    /* listing is on if file opens ok */
  1197. X    lst_fp = fopen (lst_filename, optype);
  1198. X    if (!lst_fp) {
  1199. X        (void) sprintf (fnq, "can not open %s: %s", lst_filename, errsys);
  1200. X        f_msg (fnq);
  1201. X    } else {
  1202. X        /* add a title if desired */
  1203. X        static char tp[] = "Title (q to skip): ";
  1204. X        f_prompt (tp);
  1205. X        if (read_line (fnq, PW - sizeof(tp)) > 0)
  1206. X        (void) fprintf (lst_fp, "%s\n", fnq);
  1207. X    }
  1208. X
  1209. X    listing_prstate (0);
  1210. X}
  1211. X
  1212. X/* ask operator for a listing file to show. if it's ok, do it.
  1213. X */
  1214. Xstatic
  1215. Xlst_file ()
  1216. X{
  1217. X    char fn[FNLEN], fnq[64];
  1218. X    FILE *lfp;
  1219. X    int n;
  1220. X
  1221. X    /* prompt for file name, giving current as default */
  1222. X    (void) sprintf (fnq, "file to read <%s>: ", lst_filename);
  1223. X    f_prompt (fnq);
  1224. X    n = read_line (fn, sizeof(fn)-1);
  1225. X
  1226. X    /* forget it if type END.
  1227. X     * reuse same fn if just type \n
  1228. X     */
  1229. X    if (n < 0)
  1230. X        return;
  1231. X    if (n > 0)
  1232. X        (void) strcpy (lst_filename, fn);
  1233. X
  1234. X    /* show it if file opens ok */
  1235. X    lfp = fopen (lst_filename, "r");
  1236. X    if (lfp) {
  1237. X        display_listing_file (lfp);
  1238. X        (void) fclose (lfp);
  1239. X    } else {
  1240. X        char buf[NC];
  1241. X        (void) sprintf (buf, "can not open %s: %s", lst_filename, errsys);
  1242. X        f_prompt (buf);
  1243. X        (void)read_char();
  1244. X    }
  1245. X}
  1246. X
  1247. X/* display the given listing file on the screen.
  1248. X * allow for files longer than the screen.
  1249. X * N.B. do whatever you like but redraw the screen when done.
  1250. X */
  1251. Xstatic
  1252. Xdisplay_listing_file (lfp)
  1253. XFILE *lfp;
  1254. X{
  1255. X    static char eofp[] = "[End-of-file. Hit any key to resume...] ";
  1256. X    static char p[] =    "[Hit any key to continue or q to quit...] ";
  1257. X    char buf[NC+2];    /* screen width plus for '\n' and '\0' */
  1258. X    int nc, nl;
  1259. X
  1260. X    c_erase();
  1261. X    nl = 0;
  1262. X    while (1) {
  1263. X        (void) fgets (buf, sizeof(buf), lfp);
  1264. X        if (feof(lfp)) {
  1265. X        printf (eofp);
  1266. X        (void) read_char();
  1267. X        break;
  1268. X        }
  1269. X        /* make sure last char is \n, even if it's a long line */
  1270. X        nc = strlen (buf);
  1271. X        if (nc == NC+1) {
  1272. X        (void) ungetc (buf[NC], lfp);
  1273. X        buf[NC] = '\n';
  1274. X        }
  1275. X        printf ("%s\r", buf);
  1276. X        if (++nl == NR-1) {
  1277. X        /* read-ahead one char to check for eof */
  1278. X        int rach = getc (lfp);
  1279. X        if (feof(lfp)) {
  1280. X            (void) printf (eofp);
  1281. X            (void) read_char();
  1282. X            break;
  1283. X        } else
  1284. X            (void) ungetc (rach, lfp);
  1285. X        (void) printf (p);
  1286. X        if (read_char() == END)
  1287. X            break;
  1288. X        c_erase();
  1289. X        nl = 0;
  1290. X        }
  1291. X    }
  1292. X
  1293. X    redraw_screen (2);    /* full redraw */
  1294. X}
  1295. END_OF_FILE
  1296.   if test 7576 -ne `wc -c <'listing.c'`; then
  1297.     echo shar: \"'listing.c'\" unpacked with wrong size!
  1298.   fi
  1299.   # end of 'listing.c'
  1300. fi
  1301. if test -f 'plot.c' -a "${1}" != "-c" ; then 
  1302.   echo shar: Will not clobber existing file \"'plot.c'\"
  1303. else
  1304.   echo shar: Extracting \"'plot.c'\" \(11208 characters\)
  1305.   sed "s/^X//" >'plot.c' <<'END_OF_FILE'
  1306. X/* code to support the plotting capabilities.
  1307. X * idea is to let the operator name a plot file and mark some fields for
  1308. X * logging. then after each screen update, the logged fields are written to
  1309. X * the plot file. later, the file may be plotted (very simplistically by 
  1310. X * ephem, for now anyway, or by some other program entirely.).
  1311. X * 
  1312. X * format of the plot file is one line per coordinate: label,x,y
  1313. X * if z was specified, it is a fourth field.
  1314. X * x,y,z are plotted using %g format.
  1315. X */
  1316. X
  1317. X#include <stdio.h>
  1318. X#include <math.h>
  1319. X#include "screen.h"
  1320. X
  1321. Xextern char *strcpy();
  1322. X
  1323. X#ifdef VMS
  1324. X#include <perror.h>
  1325. X#include <errno.h>
  1326. X#else
  1327. Xextern char *sys_errlist[];
  1328. Xextern errno;
  1329. X#endif
  1330. X
  1331. X#define    errsys    (sys_errlist[errno])
  1332. X
  1333. X
  1334. X#define    TRACE(x)    {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);}
  1335. X
  1336. X#define    MAXPLTLINES    10    /* max number of labeled lines we can track.
  1337. X                 * note we can't store more than NFLOGS fields
  1338. X                 * anyway (see flog.c).
  1339. X                 */
  1340. X#define    FNLEN        (14+1)    /* longest filename; plus 1 for \0 */
  1341. X
  1342. Xstatic char plt_filename[FNLEN] = "ephem.plt";    /* default plot file name */
  1343. Xstatic FILE *plt_fp;        /* the plot file; == 0 means don't plot */
  1344. X
  1345. X/* store the label and rcfpack()s for each line to track. */
  1346. Xtypedef struct {
  1347. X    char pl_label;
  1348. X    int pl_rcpx, pl_rcpy, pl_rcpz;
  1349. X} PltLine;
  1350. Xstatic PltLine pltlines[MAXPLTLINES];
  1351. Xstatic int npltlines;        /* number of pltlines[] in actual use */
  1352. X
  1353. Xstatic int plt_in_polar;    /*if true plot in polar coords, else cartesian*/
  1354. Xstatic int pltsrchfld;        /* set when the Search field is to be plotted */
  1355. X
  1356. X/* picked the Plot label:
  1357. X * if on, just turn it off.
  1358. X * if off, turn on, define fields or select name of file to plot and do it.
  1359. X * TODO: more flexibility, more relevance.
  1360. X */
  1361. Xplot_setup()
  1362. X{
  1363. X    if (plt_fp)
  1364. X        plt_turn_off();
  1365. X    else {
  1366. X        static char *chcs[4] = {
  1367. X        "Select fields", "Display a plot file", (char *)0,
  1368. X        "Begin plotting"
  1369. X        };
  1370. X        static int fn;    /* start with 0, then remember for next time */
  1371. X    ask:
  1372. X        chcs[2] = plt_in_polar ? "Polar coords" : "Cartesian coords";
  1373. X        switch (popup(chcs, fn, npltlines > 0 ? 4 : 3)) {
  1374. X        case 0: fn = 0; plt_select_fields(); goto ask;
  1375. X        case 1: fn = 1; plt_file(); goto ask;
  1376. X        case 2: fn = 2; plt_in_polar ^= 1; goto ask;
  1377. X        case 3: fn = 3; plt_turn_on(); break;
  1378. X        default: break;
  1379. X        }
  1380. X    }
  1381. X}
  1382. X
  1383. X/* write the active plotfields to the current plot file, if one is open. */
  1384. Xplot()
  1385. X{
  1386. X    if (plt_fp) {
  1387. X        PltLine *plp;
  1388. X        double x, y, z;
  1389. X        if (!srch_ison() && pltsrchfld) {
  1390. X        /* if searching is not on but we are plotting the search
  1391. X         * funtion we must evaluate and log it ourselves here and now.
  1392. X         * plt_turn_on() insured there is a good function to eval.
  1393. X         * N.B. if searching IS on, we rely on main() having called
  1394. X         * srch_eval() BEFORE plot() so it is already evaluated.
  1395. X         */
  1396. X        double e;
  1397. X        char errmsg[128];
  1398. X        if (execute_expr (&e, errmsg) < 0) {
  1399. X            f_msg (errmsg);
  1400. X            plt_turn_off();
  1401. X            return;
  1402. X        } else
  1403. X            (void) flog_log (R_SRCH, C_SRCH, e, "");
  1404. X        }
  1405. X        /* plot in order of original selection */
  1406. X        for (plp = pltlines; plp < &pltlines[npltlines]; plp++) {
  1407. X        if (flog_get (plp->pl_rcpx, &x, (char *)0) == 0 
  1408. X            && flog_get (plp->pl_rcpy, &y, (char *)0) == 0) {
  1409. X            (void) fprintf (plt_fp, "%c,%.12g,%.12g", plp->pl_label,
  1410. X                                    x, y);
  1411. X            if (flog_get (plp->pl_rcpz, &z, (char *)0) == 0)
  1412. X            (void) fprintf (plt_fp, ",%.12g", z);
  1413. X            (void) fprintf (plt_fp, "\n");
  1414. X        }
  1415. X        }
  1416. X    }
  1417. X}
  1418. X
  1419. Xplot_prstate (force)
  1420. Xint force;
  1421. X{
  1422. X    static last;
  1423. X    int this = plt_fp != 0;
  1424. X
  1425. X    if (force || this != last) {
  1426. X        f_string (R_PLOT, C_PLOTV, this ? " on" : "off");
  1427. X        last = this;
  1428. X    }
  1429. X}
  1430. X
  1431. Xplot_ison()
  1432. X{
  1433. X    return (plt_fp != 0);
  1434. X}
  1435. X
  1436. Xstatic
  1437. Xplt_reset()
  1438. X{
  1439. X    PltLine *plp;
  1440. X
  1441. X    for (plp = &pltlines[npltlines]; --plp >= pltlines; ) {
  1442. X        (void) flog_delete (plp->pl_rcpx);
  1443. X        (void) flog_delete (plp->pl_rcpy);
  1444. X        (void) flog_delete (plp->pl_rcpz);
  1445. X        plp->pl_rcpx = plp->pl_rcpy = plp->pl_rcpz = 0;
  1446. X    }
  1447. X    npltlines = 0;
  1448. X    pltsrchfld = 0;
  1449. X}
  1450. X
  1451. X/* let operator select the fields he wants to plot.
  1452. X * register them with flog and keep rcfpack() in pltlines[] array.
  1453. X * as a special case, set pltsrchfld if Search field is selected.
  1454. X */
  1455. Xstatic
  1456. Xplt_select_fields()
  1457. X{
  1458. X    static char hlp[] = "move and RETURN to select a field, or q to quit";
  1459. X    static char sry[] = "Sorry; can not log any more fields.";
  1460. X    int f = rcfpack(R_UT,C_UTV,0); /* TODO: start where main was? */
  1461. X    int sf = rcfpack (R_SRCH, C_SRCH, 0);
  1462. X    char buf[64];
  1463. X    int i;
  1464. X    int tmpf;
  1465. X
  1466. X    plt_reset();
  1467. X    for (i = 0; i < MAXPLTLINES; i++) {
  1468. X        (void) sprintf (buf, "select x field for line %d", i+1);
  1469. X        f = sel_fld (f, alt_menumask()|F_PLT, buf, hlp);
  1470. X        if (!f)
  1471. X        break;
  1472. X        if (flog_add (f) < 0) {
  1473. X        f_msg (sry);
  1474. X        break;
  1475. X        }
  1476. X        pltlines[i].pl_rcpx = f;
  1477. X        if (f == sf)
  1478. X        pltsrchfld = 1;
  1479. X
  1480. X        (void) sprintf (buf, "select y field for line %d", i+1);
  1481. X        f = sel_fld (f, alt_menumask()|F_PLT, buf, hlp);
  1482. X        if (!f) {
  1483. X        (void) flog_delete (pltlines[i].pl_rcpx);
  1484. X        break;
  1485. X        }
  1486. X        if (flog_add (f) < 0) {
  1487. X        (void) flog_delete (pltlines[i].pl_rcpx);
  1488. X        f_msg (sry);
  1489. X        break;
  1490. X        }
  1491. X        pltlines[i].pl_rcpy = f;
  1492. X        if (f == sf)
  1493. X        pltsrchfld = 1;
  1494. X
  1495. X        (void) sprintf (buf, "select z field for line %d (q for no z)",i+1);
  1496. X        tmpf = sel_fld (f, alt_menumask()|F_PLT, buf, hlp);
  1497. X        if (tmpf) {
  1498. X        if (flog_add (tmpf) < 0) {
  1499. X            (void) flog_delete (pltlines[i].pl_rcpx);
  1500. X            (void) flog_delete (pltlines[i].pl_rcpy);
  1501. X            f_msg (sry);
  1502. X            break;
  1503. X        }
  1504. X        pltlines[i].pl_rcpz = tmpf;
  1505. X        if (tmpf == sf)
  1506. X            pltsrchfld = 1;
  1507. X        f = tmpf;
  1508. X        }
  1509. X
  1510. X        do {
  1511. X        (void) sprintf(buf,"enter a one-character label for line %d: ",
  1512. X                                    i+1);
  1513. X        f_prompt (buf);
  1514. X        } while (read_line (buf, 1) != 1);
  1515. X        pltlines[i].pl_label = *buf;
  1516. X    }
  1517. X    npltlines = i;
  1518. X}
  1519. X
  1520. Xstatic
  1521. Xplt_turn_off ()
  1522. X{
  1523. X    (void) fclose (plt_fp);
  1524. X    plt_fp = 0;
  1525. X    plot_prstate(0);
  1526. X}
  1527. X
  1528. X/* turn on plotting.
  1529. X * establish a file to use (and thereby set plt_fp, the plotting_is_on flag).
  1530. X * also check that there is a srch function if it is being plotted.
  1531. X */
  1532. Xstatic
  1533. Xplt_turn_on ()
  1534. X{
  1535. X    int sf = rcfpack(R_SRCH, C_SRCH, 0);
  1536. X    char fn[FNLEN], fnq[NC];
  1537. X    char *optype;
  1538. X    int n;
  1539. X    PltLine *plp;
  1540. X
  1541. X    /* insure there is a valid srch function if we are to plot it */
  1542. X    for (plp = &pltlines[npltlines]; --plp >= pltlines; )
  1543. X        if ((plp->pl_rcpx == sf || plp->pl_rcpy == sf || plp->pl_rcpz == sf)
  1544. X            && !prog_isgood()) {
  1545. X        f_msg ("Plotting search function but it is not defined.");
  1546. X        return;
  1547. X        }
  1548. X
  1549. X    /* prompt for file name, giving current as default */
  1550. X    (void) sprintf (fnq, "file to write <%s>: ", plt_filename);
  1551. X    f_prompt (fnq);
  1552. X    n = read_line (fn, sizeof(fn)-1);
  1553. X
  1554. X    /* leave plotting off if type END.
  1555. X     * reuse same fn if just type \n
  1556. X     */
  1557. X    if (n < 0)
  1558. X        return;
  1559. X    if (n > 0)
  1560. X        (void) strcpy (plt_filename, fn);
  1561. X
  1562. X    /* give option to append if file already exists */
  1563. X    optype = "w";
  1564. X    if (access (plt_filename, 2) == 0) {
  1565. X        while (1) {
  1566. X        f_prompt ("files exists; append or overwrite (a/o)?: ");
  1567. X        n = read_char();
  1568. X        if (n == 'a') {
  1569. X            optype = "a";
  1570. X            break;
  1571. X        }
  1572. X        if (n == 'o')
  1573. X            break;
  1574. X        }
  1575. X    }
  1576. X
  1577. X    /* plotting is on if file opens ok */
  1578. X    plt_fp = fopen (plt_filename, optype);
  1579. X    if (!plt_fp) {
  1580. X        char buf[NC];
  1581. X        (void) sprintf (buf, "can not open %s: %s", plt_filename, errsys);
  1582. X        f_prompt (buf);
  1583. X        (void)read_char();
  1584. X    } else {
  1585. X        /* add a title if desired */
  1586. X        static char tp[] = "Title (q to skip): ";
  1587. X        f_prompt (tp);
  1588. X        if (read_line (fnq, PW - sizeof(tp)) > 0)
  1589. X        (void) fprintf (plt_fp, "* %s\n", fnq);
  1590. X    }
  1591. X    plot_prstate (0);
  1592. X}
  1593. X
  1594. X/* ask operator for a file to plot. if it's ok, do it.
  1595. X */
  1596. Xstatic
  1597. Xplt_file ()
  1598. X{
  1599. X    char fn[FNLEN], fnq[64];
  1600. X    FILE *pfp;
  1601. X    int n;
  1602. X
  1603. X    /* prompt for file name, giving current as default */
  1604. X    (void) sprintf (fnq, "file to read <%s>: ", plt_filename);
  1605. X    f_prompt (fnq);
  1606. X    n = read_line (fn, sizeof(fn)-1);
  1607. X
  1608. X    /* forget it if type END.
  1609. X     * reuse same fn if just type \n
  1610. X     */
  1611. X    if (n < 0)
  1612. X        return;
  1613. X    if (n > 0)
  1614. X        (void) strcpy (plt_filename, fn);
  1615. X
  1616. X    /* do the plot if file opens ok */
  1617. X    pfp = fopen (plt_filename, "r");
  1618. X    if (pfp) {
  1619. X        if (plt_in_polar)
  1620. X        plot_polar (pfp);
  1621. X        else
  1622. X        plot_cartesian (pfp);
  1623. X        (void) fclose (pfp);
  1624. X    } else {
  1625. X        char buf[NC];
  1626. X        (void) sprintf (buf, "can not open %s: %s", plt_filename, errsys);
  1627. X        f_prompt (buf);
  1628. X        (void)read_char();
  1629. X    }
  1630. X}
  1631. X
  1632. X/* plot the given file on the screen in cartesian coords.
  1633. X * TODO: add z tags somehow
  1634. X * N.B. do whatever you like but redraw the screen when done.
  1635. X */
  1636. Xstatic
  1637. Xplot_cartesian (pfp)
  1638. XFILE *pfp;
  1639. X{
  1640. X    static char fmt[] = "%c,%lf,%lf";
  1641. X    double x, y;    /* N.B. be sure these match what scanf's %lf wants*/
  1642. X    double minx, maxx, miny, maxy;
  1643. X    char buf[128];
  1644. X    int npts = 0;
  1645. X    char c;
  1646. X
  1647. X    /* find ranges and number of points */
  1648. X    while (fgets (buf, sizeof(buf), pfp)) {
  1649. X        if (sscanf (buf, fmt, &c, &x, &y) != 3)
  1650. X        continue;
  1651. X        if (npts++ == 0) {
  1652. X        maxx = minx = x;
  1653. X        maxy = miny = y;
  1654. X        } else {
  1655. X        if (x > maxx) maxx = x;
  1656. X        else if (x < minx) minx = x;
  1657. X        if (y > maxy) maxy = y;
  1658. X        else if (y < miny) miny = y;
  1659. X        }
  1660. X    }
  1661. X
  1662. X#define    SMALL    (1e-10)
  1663. X    if (npts < 2 || fabs(minx-maxx) < SMALL || fabs(miny-maxy) < SMALL)
  1664. X        f_prompt ("At least two different points required to plot.");
  1665. X    else {
  1666. X        /* read file again, this time plotting */
  1667. X        rewind (pfp);
  1668. X        c_erase();
  1669. X        while (fgets (buf, sizeof(buf), pfp)) {
  1670. X        int row, col;
  1671. X        if (sscanf (buf, fmt, &c, &x, &y) != 3)
  1672. X            continue;
  1673. X        row = NR-(int)((NR-1)*(y-miny)/(maxy-miny)+0.5);
  1674. X        col =  1+(int)((NC-1)*(x-minx)/(maxx-minx)+0.5);
  1675. X        if (row == NR && col == NC)
  1676. X            col--;    /* avoid lower right scrolling corner */
  1677. X        f_char (row, col, c);
  1678. X        }
  1679. X
  1680. X        /* label axes */
  1681. X        f_double (1, 1, "%g", maxy);
  1682. X        f_double (NR-1, 1, "%g", miny);
  1683. X        f_double (NR, 1, "%g", minx);
  1684. X        f_double (NR, NC-10, "%g", maxx);
  1685. X    }
  1686. X
  1687. X    /* hit any key to resume... */
  1688. X    (void) read_char();
  1689. X    redraw_screen (2);    /* full redraw */
  1690. X}
  1691. X
  1692. X/* plot the given file on the screen in polar coords.
  1693. X * first numberic field in plot file is r, second is theta in degrees.
  1694. X * TODO: add z tags somehow
  1695. X * N.B. do whatever you like but redraw the screen when done.
  1696. X */
  1697. Xstatic
  1698. Xplot_polar (pfp)
  1699. XFILE *pfp;
  1700. X{
  1701. X    static char fmt[] = "%c,%lf,%lf";
  1702. X    double r, th;    /* N.B. be sure these match what scanf's %lf wants*/
  1703. X    double maxr;
  1704. X    char buf[128];
  1705. X    int npts = 0;
  1706. X    char c;
  1707. X
  1708. X    /* find ranges and number of points */
  1709. X    while (fgets (buf, sizeof(buf), pfp)) {
  1710. X        if (sscanf (buf, fmt, &c, &r, &th) != 3)
  1711. X        continue;
  1712. X        if (npts++ == 0)
  1713. X        maxr = r;
  1714. X        else
  1715. X        if (r > maxr)
  1716. X            maxr = r;
  1717. X    }
  1718. X
  1719. X    if (npts < 2)
  1720. X        f_prompt ("At least two points required to plot.");
  1721. X    else {
  1722. X        /* read file again, this time plotting */
  1723. X        rewind (pfp);
  1724. X        c_erase();
  1725. X        while (fgets (buf, sizeof(buf), pfp)) {
  1726. X        int row, col;
  1727. X        double x, y;
  1728. X        if (sscanf (buf, fmt, &c, &r, &th) != 3)
  1729. X            continue;
  1730. X        x = r * cos(th/57.2958);    /* degs to rads */
  1731. X        y = r * sin(th/57.2958);
  1732. X        row = NR-(int)((NR-1)*(y+maxr)/(2.0*maxr)+0.5);
  1733. X        col =  1+(int)((NC-1)*(x+maxr)/(2.0*maxr)/ASPECT+0.5);
  1734. X        if (row == NR && col == NC)
  1735. X            col--;    /* avoid lower right scrolling corner */
  1736. X        f_char (row, col, c);
  1737. X        }
  1738. X
  1739. X        /* label radius */
  1740. X        f_double (NR/2, NC-10, "%g", maxr);
  1741. X    }
  1742. X
  1743. X    /* hit any key to resume... */
  1744. X    (void) read_char();
  1745. X    redraw_screen (2);    /* full redraw */
  1746. X}
  1747. END_OF_FILE
  1748.   if test 11208 -ne `wc -c <'plot.c'`; then
  1749.     echo shar: \"'plot.c'\" unpacked with wrong size!
  1750.   fi
  1751.   # end of 'plot.c'
  1752. fi
  1753. if test -f 'srch.c' -a "${1}" != "-c" ; then 
  1754.   echo shar: Will not clobber existing file \"'srch.c'\"
  1755. else
  1756.   echo shar: Extracting \"'srch.c'\" \(8160 characters\)
  1757.   sed "s/^X//" >'srch.c' <<'END_OF_FILE'
  1758. X/* this file contains functions to support iterative ephem searches.
  1759. X * we support several kinds of searching and solving algorithms.
  1760. X * values used in the evaluations come from the field logging flog.c system.
  1761. X * the expressions being evaluated are compiled and executed from compiler.c.
  1762. X */
  1763. X
  1764. X#include <stdio.h>
  1765. X#include <math.h>
  1766. X#include "screen.h"
  1767. X
  1768. Xextern char *strcpy();
  1769. X
  1770. Xstatic int (*srch_f)();
  1771. Xstatic int srch_tmscalled;
  1772. Xstatic char expbuf[NC];        /* [0] == '\0' when expression is invalid */
  1773. Xstatic double tmlimit = 1./60.;    /* search accuracy, in hrs; def is one minute */
  1774. X
  1775. X
  1776. Xsrch_setup()
  1777. X{
  1778. X    int srch_minmax(), srch_solve0(), srch_binary();
  1779. X    static char *chcs[] = {
  1780. X        "Find extreme", "Find 0", "Binary", "New function", "Accuracy",
  1781. X        "Stop"
  1782. X    };
  1783. X    static int fn;    /* start with 0, then remember for next time */
  1784. X
  1785. X    /* let op select algorithm, edit, set accuracy
  1786. X     * or stop if currently searching
  1787. X     * algorithms require a function.
  1788. X     */
  1789. X    ask:
  1790. X    switch (popup(chcs, fn, srch_f ? 6 : 5)) {
  1791. X    case 0: fn = 0;
  1792. X        if (expbuf[0] == '\0')
  1793. X            set_function();
  1794. X        srch_f = expbuf[0] ? srch_minmax : (int (*)())0;
  1795. X        if (srch_f)
  1796. X            break;
  1797. X        else
  1798. X            goto ask;
  1799. X    case 1: fn = 1;
  1800. X        if (expbuf[0] == '\0')
  1801. X            set_function();
  1802. X        srch_f = expbuf[0] ? srch_solve0 : (int (*)())0;
  1803. X        if (srch_f)
  1804. X            break;
  1805. X        else
  1806. X            goto ask;
  1807. X    case 2: fn = 2;
  1808. X        if (expbuf[0] == '\0')
  1809. X            set_function();
  1810. X        srch_f = expbuf[0] ? srch_binary : (int (*)())0;
  1811. X        if (srch_f)
  1812. X            break;
  1813. X        else
  1814. X            goto ask;
  1815. X    case 3: fn = 3; srch_f = 0; set_function(); goto ask;
  1816. X    case 4: fn = 4; srch_f = 0; set_accuracy(); goto ask;
  1817. X    case 5: srch_f = 0; srch_prstate(0); return;
  1818. X    default: return;
  1819. X    }
  1820. X
  1821. X    /* new search */
  1822. X    srch_tmscalled = 0;
  1823. X    srch_prstate (0);
  1824. X}
  1825. X
  1826. X/* if searching is in effect call the search type function.
  1827. X * it might modify *tmincp according to where it next wants to eval.
  1828. X * (remember tminc is in hours, not days).
  1829. X * if searching ends for any reason it is also turned off.
  1830. X * also, flog the new value.
  1831. X * return 0 if caller can continue or -1 if it is time to stop.
  1832. X */
  1833. Xsrch_eval(mjd, tmincp)
  1834. Xdouble mjd;
  1835. Xdouble *tmincp;
  1836. X{
  1837. X    char errbuf[128];
  1838. X    int s;
  1839. X    double v;
  1840. X
  1841. X    if (!srch_f)
  1842. X        return (0);
  1843. X
  1844. X    if (execute_expr (&v, errbuf) < 0) {
  1845. X        srch_f = 0;
  1846. X        f_msg (errbuf);
  1847. X    } else {
  1848. X        s = (*srch_f)(mjd, v, tmincp);
  1849. X        if (s < 0)
  1850. X        srch_f = 0;
  1851. X        (void) flog_log (R_SRCH, C_SRCH, v, "");
  1852. X        srch_tmscalled++;
  1853. X    }
  1854. X
  1855. X    srch_prstate (0);
  1856. X    return (s);
  1857. X}
  1858. X
  1859. X/* print state of searching. */
  1860. Xsrch_prstate (force)
  1861. Xint force;
  1862. X{
  1863. X    int srch_minmax(), srch_solve0(), srch_binary();
  1864. X    static (*last)();
  1865. X
  1866. X    if (force || srch_f != last) {
  1867. X        f_string (R_SRCH, C_SRCHV,
  1868. X            srch_f == srch_minmax   ? "Extrema" :
  1869. X            srch_f == srch_solve0   ? " Find 0" :
  1870. X            srch_f == srch_binary ?   " Binary" :
  1871. X                          "    off");
  1872. X        last = srch_f;
  1873. X    }
  1874. X}
  1875. X
  1876. Xsrch_ison()
  1877. X{
  1878. X    return (srch_f != 0);
  1879. X}
  1880. X
  1881. X/* display current expression. then if type in at least one char make it the
  1882. X * current expression IF it compiles ok.
  1883. X * TODO: editing?
  1884. X */
  1885. Xstatic
  1886. Xset_function()
  1887. X{
  1888. X    static char prompt[] = "Function: ";
  1889. X    char newexp[NC];
  1890. X    int s;
  1891. X
  1892. X    f_prompt (prompt);
  1893. X    (void) fputs (expbuf, stdout);
  1894. X    c_pos (R_PROMPT, sizeof(prompt));
  1895. X
  1896. X    s = read_line (newexp, PW-sizeof(prompt));
  1897. X    if (s >= 0) {
  1898. X        char errbuf[NC];
  1899. X        if (s > 0 && compile_expr (newexp, errbuf) < 0)
  1900. X        f_msg (errbuf);
  1901. X        else
  1902. X        (void) strcpy (expbuf, newexp);
  1903. X    }
  1904. X}
  1905. X
  1906. Xstatic
  1907. Xset_accuracy()
  1908. X{
  1909. X    static char p[] = "Desired accuracy (         hrs): ";
  1910. X    int hrs, mins, secs;
  1911. X    char buf[NC];
  1912. X
  1913. X    f_prompt (p);
  1914. X    f_time (R_PROMPT, C_PROMPT+18, tmlimit); /* place in blank spot */
  1915. X    c_pos (R_PROMPT, sizeof(p));
  1916. X    if (read_line (buf, PW-sizeof(p)) > 0) {
  1917. X        f_dec_sexsign (tmlimit, &hrs, &mins, &secs);
  1918. X        f_sscansex (buf, &hrs, &mins, &secs);
  1919. X        sex_dec (hrs, mins, secs, &tmlimit);
  1920. X    }
  1921. X}
  1922. X
  1923. X/* use successive paraboloidal fits to find when expression is at a
  1924. X * local minimum or maximum.
  1925. X */
  1926. Xstatic
  1927. Xsrch_minmax(mjd, v, tmincp)
  1928. Xdouble mjd;
  1929. Xdouble v;
  1930. Xdouble *tmincp;
  1931. X{
  1932. X    static double base;        /* for better stability */
  1933. X    static double x_1, x_2, x_3;    /* keep in increasing order */
  1934. X    static double y_1, y_2, y_3;
  1935. X    double xm, a, b;
  1936. X
  1937. X    if (srch_tmscalled == 0) {
  1938. X        base = mjd;
  1939. X        x_1 = 0.0;
  1940. X        y_1 = v;
  1941. X        return (0);
  1942. X    }
  1943. X    mjd -= base;
  1944. X    if (srch_tmscalled == 1) {
  1945. X        /* put in one of first two slots */
  1946. X        if (mjd < x_1) {
  1947. X            x_2 = x_1;  y_2 = y_1;
  1948. X        x_1 = mjd; y_1 = v;
  1949. X        } else {
  1950. X        x_2 = mjd; y_2 = v;
  1951. X        }
  1952. X        return (0);
  1953. X    }
  1954. X    if (srch_tmscalled == 2 || fabs(mjd - x_1) < fabs(mjd - x_3)) {
  1955. X        /* closer to x_1 so discard x_3.
  1956. X         * or if it's our third value we know to "discard" x_3.
  1957. X         */
  1958. X        if (mjd > x_2) {
  1959. X        x_3 = mjd; y_3 = v;
  1960. X        } else {
  1961. X        x_3 = x_2;  y_3 = y_2;
  1962. X        if (mjd > x_1) {
  1963. X            x_2 = mjd; y_2 = v;
  1964. X        } else {
  1965. X            x_2 = x_1;  y_2 = y_1;
  1966. X            x_1 = mjd; y_1 = v;
  1967. X        }
  1968. X        }
  1969. X        if (srch_tmscalled == 2)
  1970. X        return (0);
  1971. X    } else {
  1972. X        /* closer to x_3 so discard x_1 */
  1973. X        if (mjd < x_2) {
  1974. X        x_1 = mjd;  y_1 = v;
  1975. X        } else {
  1976. X        x_1 =  x_2;  y_1 = y_2;
  1977. X        if (mjd < x_3) {
  1978. X            x_2 = mjd; y_2 = v;
  1979. X        } else {
  1980. X            x_2 =  x_3; y_2 = y_3;
  1981. X            x_3 = mjd; y_3 = v;
  1982. X        }
  1983. X        }
  1984. X    }
  1985. X
  1986. X#ifdef TRACEMM
  1987. X    { char buf[NC];
  1988. X      sprintf (buf, "x_1=%g y_1=%g x_2=%g y_2=%g x_3=%g y_3=%g",
  1989. X                        x_1, y_1, x_2, y_2, x_3, y_3);
  1990. X      f_msg (buf);
  1991. X    }
  1992. X#endif
  1993. X    a = y_1*(x_2-x_3) - y_2*(x_1-x_3) + y_3*(x_1-x_2);
  1994. X    if (fabs(a) < 1e-10) {
  1995. X        /* near-0 zero denominator, ie, curve is pretty flat here,
  1996. X         * so assume we are done enough.
  1997. X         * signal this by forcing a 0 tminc.
  1998. X         */
  1999. X        *tmincp = 0.0;
  2000. X        return (-1);
  2001. X    }
  2002. X    b = (x_1*x_1)*(y_2-y_3) - (x_2*x_2)*(y_1-y_3) + (x_3*x_3)*(y_1-y_2);
  2003. X    xm = -b/(2.0*a);
  2004. X    *tmincp = (xm - mjd)*24.0;
  2005. X    return (fabs (*tmincp) < tmlimit ? -1 : 0);
  2006. X}
  2007. X
  2008. X/* use secant method to solve for time when expression passes through 0.
  2009. X */
  2010. Xstatic
  2011. Xsrch_solve0(mjd, v, tmincp)
  2012. Xdouble mjd;
  2013. Xdouble v;
  2014. Xdouble *tmincp;
  2015. X{
  2016. X    static double x0, x_1;    /* x(n-1) and x(n) */
  2017. X    static double y_0, y_1;    /* y(n-1) and y(n) */
  2018. X    double x_2;        /* x(n+1) */
  2019. X    double df;        /* y(n) - y(n-1) */
  2020. X
  2021. X    switch (srch_tmscalled) {
  2022. X    case 0: x0 = mjd; y_0 = v; return(0);
  2023. X    case 1: x_1 = mjd; y_1 = v; break;
  2024. X    default: x0 = x_1; y_0 = y_1; x_1 = mjd; y_1 = v; break;
  2025. X    }
  2026. X
  2027. X    df = y_1 - y_0;
  2028. X    if (fabs(df) < 1e-10) {
  2029. X        /* near-0 zero denominator, ie, curve is pretty flat here,
  2030. X         * so assume we are done enough.
  2031. X         * signal this by forcing a 0 tminc.
  2032. X         */
  2033. X        *tmincp = 0.0;
  2034. X        return (-1);
  2035. X    }
  2036. X    x_2 = x_1 - y_1*(x_1-x0)/df;
  2037. X    *tmincp = (x_2 - mjd)*24.0;
  2038. X    return (fabs (*tmincp) < tmlimit ? -1 : 0);
  2039. X}
  2040. X
  2041. X/* binary search for time when expression changes from its initial state.
  2042. X * if the change is outside the initial tminc range, then keep searching in that
  2043. X *    direction by tminc first before starting to divide down.
  2044. X */
  2045. Xstatic
  2046. Xsrch_binary(mjd, v, tmincp)
  2047. Xdouble mjd;
  2048. Xdouble v;
  2049. Xdouble *tmincp;
  2050. X{
  2051. X    static double lb, ub;        /* lower and upper bound */
  2052. X    static int initial_state;
  2053. X    int this_state = v >= 0.5;
  2054. X
  2055. X#define    FLUNDEF    -9e10
  2056. X
  2057. X    if (srch_tmscalled == 0) {
  2058. X        if (*tmincp >= 0.0) {
  2059. X        /* going forwards in time so first mjd is lb and no ub yet */
  2060. X        lb = mjd;
  2061. X        ub = FLUNDEF;
  2062. X        } else {
  2063. X        /* going backwards in time so first mjd is ub and no lb yet */
  2064. X        ub = mjd;
  2065. X        lb = FLUNDEF;
  2066. X        }
  2067. X        initial_state = this_state;
  2068. X        return (0);
  2069. X    }
  2070. X
  2071. X    if (ub != FLUNDEF && lb != FLUNDEF) {
  2072. X        if (this_state == initial_state)
  2073. X        lb = mjd;
  2074. X        else
  2075. X        ub = mjd;
  2076. X        *tmincp = ((lb + ub)/2.0 - mjd)*24.0;
  2077. X#ifdef TRACEBIN
  2078. X        { char buf[NC];
  2079. X          sprintf (buf, "lb=%g ub=%g tminc=%g mjd=%g is=%d ts=%d",
  2080. X                lb, ub, *tmincp, mjd, initial_state, this_state);
  2081. X          f_msg (buf);
  2082. X        }
  2083. X#endif
  2084. X        /* signal to stop if asking for time change less than TMLIMIT */
  2085. X        return (fabs (*tmincp) < tmlimit ? -1 : 0);
  2086. X    } else if (this_state != initial_state) {
  2087. X        /* gone past; turn around half way */
  2088. X        if (*tmincp >= 0.0)
  2089. X        ub = mjd;
  2090. X        else
  2091. X        lb = mjd;
  2092. X        *tmincp /= -2.0;
  2093. X        return (0);
  2094. X    } else {
  2095. X        /* just keep going, looking for first state change but we keep
  2096. X         * learning the lower (or upper, if going backwards) bound.
  2097. X         */
  2098. X        if (*tmincp >= 0.0)
  2099. X        lb = mjd;
  2100. X        else
  2101. X        ub = mjd;
  2102. X        return (0);
  2103. X    }
  2104. X}
  2105. END_OF_FILE
  2106.   if test 8160 -ne `wc -c <'srch.c'`; then
  2107.     echo shar: \"'srch.c'\" unpacked with wrong size!
  2108.   fi
  2109.   # end of 'srch.c'
  2110. fi
  2111. echo shar: End of archive 7 \(of 9\).
  2112. cp /dev/null ark7isdone
  2113. MISSING=""
  2114. for I in 1 2 3 4 5 6 7 8 9 ; do
  2115.     if test ! -f ark${I}isdone ; then
  2116.     MISSING="${MISSING} ${I}"
  2117.     fi
  2118. done
  2119. if test "${MISSING}" = "" ; then
  2120.     echo You have unpacked all 9 archives.
  2121.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2122. else
  2123.     echo You still must unpack the following archives:
  2124.     echo "        " ${MISSING}
  2125. fi
  2126. exit 0
  2127. exit 0 # Just in case...
  2128.