home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume11
/
ephem4.12
/
part04
< prev
next >
Wrap
Text File
|
1990-03-10
|
57KB
|
1,809 lines
Newsgroups: comp.sources.misc
subject: v11i005: ephem, 4 of 7
From: ecd@cs.umn.edu@ncs-med.UUCP (Elwood C. Downey)
Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
Posting-number: Volume 11, Issue 5
Submitted-by: ecd@cs.umn.edu@ncs-med.UUCP (Elwood C. Downey)
Archive-name: ephem4.12/part04
# This is the first line of a "shell archive" file.
# This means it contains several files that can be extracted into
# the current directory when run with the sh shell, as follows:
# sh < this_file_name
# This is file 4.
echo x plot.c
sed -e 's/^X//' << 'EOFxEOF' > plot.c
X/* code to support the plotting capabilities.
X * idea is to let the operator name a plot file and mark some fields for
X * logging. then after each screen update, the logged fields are written to
X * the plot file. later, the file may be plotted (very simplistically by
X * ephem, for now anyway, or by some other program entirely.).
X *
X * format of the plot file is one line per coordinate: label,x,y
X * if z was specified, it is a fourth field.
X * x,y,z are plotted using %g format.
X */
X
X#include <stdio.h>
X#include <math.h>
X#include "screen.h"
X
Xextern char *strcpy();
Xextern errno;
Xextern char *sys_errlist[];
X#define errsys (sys_errlist[errno])
X
X#define TRACE(x) {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);}
X
X#define MAXPLTLINES 10 /* max number of labeled lines we can track.
X * note we can't store more than NFLOGS fields
X * anyway (see flog.c).
X */
X#define FNLEN (14+1) /* longest filename; plus 1 for \0 */
X
Xstatic char plt_filename[FNLEN] = "ephem.plt"; /* default plot file name */
Xstatic FILE *plt_fp; /* the plot file; == 0 means don't plot */
X
X/* store the label and rcfpack()s for each line to track. */
Xtypedef struct {
X char pl_label;
X int pl_rcpx, pl_rcpy, pl_rcpz;
X} PltLine;
Xstatic PltLine pltlines[MAXPLTLINES];
Xstatic int npltlines; /* number of pltlines[] in actual use */
X
Xstatic int plt_in_polar; /*if true plot in polar coords, else cartesian*/
Xstatic int pltsrchfld; /* set when the Search field is to be plotted */
X
X/* picked the Plot label:
X * if on, just turn it off.
X * if off, turn on, define fields or select name of file to plot and do it.
X * TODO: more flexibility, more relevance.
X */
Xplot_setup()
X{
X if (plt_fp)
X plt_turn_off();
X else {
X static char *chcs[4] = {
X "Select fields", "Display a plot file", (char *)0,
X "Begin plotting"
X };
X int ff = 0;
X ask:
X chcs[2] = plt_in_polar ? "Polar coords" : "Cartesian coords";
X switch (popup(chcs, ff, npltlines > 0 ? 4 : 3)) {
X case 0: plt_select_fields(); break;
X case 1: plt_file(); break;
X case 2: plt_in_polar ^= 1; ff = 2; goto ask;
X case 3: plt_turn_on(); break;
X }
X }
X}
X
X/* write the active plotfields to the current plot file, if one is open. */
Xplot()
X{
X if (plt_fp) {
X PltLine *plp;
X double x, y, z;
X if (!srch_ison() && pltsrchfld) {
X /* if searching is not on but we are plotting the search
X * funtion we must evaluate and log it ourselves here and now.
X * plt_turn_on() insured there is a good function to eval.
X * N.B. if searching IS on, we rely on main() having called
X * srch_eval() BEFORE plot() so it is already evaluated.
X */
X double e;
X char errmsg[128];
X if (execute_expr (&e, errmsg) < 0) {
X f_msg (errmsg);
X plt_turn_off();
X return;
X } else
X flog_log (R_SRCH, C_SRCH, e);
X }
X /* plot in order of original selection */
X for (plp = pltlines; plp < &pltlines[npltlines]; plp++) {
X if (flog_get (plp->pl_rcpx, &x) == 0
X && flog_get (plp->pl_rcpy, &y) == 0) {
X fprintf (plt_fp, "%c,%.12g,%.12g", plp->pl_label, x, y);
X if (flog_get (plp->pl_rcpz, &z) == 0)
X fprintf (plt_fp, ",%.12g", z);
X fprintf (plt_fp, "\n");
X }
X }
X }
X}
X
Xplot_prstate (force)
Xint force;
X{
X static last;
X int this = plt_fp != 0;
X
X if (force || this != last) {
X f_string (R_PLOT, C_PLOTV, this ? " on" : "off");
X last = this;
X }
X}
X
Xplot_ison()
X{
X return (plt_fp != 0);
X}
X
Xstatic
Xplt_reset()
X{
X PltLine *plp;
X
X for (plp = &pltlines[npltlines]; --plp >= pltlines; ) {
X (void) flog_delete (plp->pl_rcpx);
X (void) flog_delete (plp->pl_rcpy);
X (void) flog_delete (plp->pl_rcpz);
X plp->pl_rcpx = plp->pl_rcpy = plp->pl_rcpz = 0;
X }
X npltlines = 0;
X pltsrchfld = 0;
X}
X
X/* let operator select the fields he wants to plot.
X * register them with flog and keep rcfpack() in pltlines[] array.
X * as a special case, set pltsrchfld if Search field is selected.
X */
Xstatic
Xplt_select_fields()
X{
X static char hlp[] = "move and RETURN to select a field, or q to quit";
X static char sry[] = "Sorry; can not log any more fields.";
X int r = R_UT, c = C_UTV; /* TODO: start where main was? */
X int sf = rcfpack (R_SRCH, C_SRCH, 0);
X char buf[64];
X int rcp;
X int i;
X
X plt_reset();
X for (i = 0; i < MAXPLTLINES; i++) {
X sprintf (buf, "select x field for line %d", i+1);
X rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp);
X if (!rcp)
X break;
X if (flog_add (rcp) < 0) {
X f_msg (sry);
X break;
X }
X pltlines[i].pl_rcpx = rcp;
X if (rcp == sf)
X pltsrchfld = 1;
X
X sprintf (buf, "select y field for line %d", i+1);
X r = unpackr (rcp); c = unpackc (rcp);
X rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp);
X if (!rcp) {
X (void) flog_delete (pltlines[i].pl_rcpx);
X break;
X }
X if (flog_add (rcp) < 0) {
X (void) flog_delete (pltlines[i].pl_rcpx);
X f_msg (sry);
X break;
X }
X pltlines[i].pl_rcpy = rcp;
X if (rcp == sf)
X pltsrchfld = 1;
X
X sprintf (buf, "select z field for line %d", i+1);
X r = unpackr (rcp); c = unpackc (rcp);
X rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp);
X if (rcp) {
X if (flog_add (rcp) < 0) {
X (void) flog_delete (pltlines[i].pl_rcpx);
X (void) flog_delete (pltlines[i].pl_rcpy);
X f_msg (sry);
X break;
X }
X pltlines[i].pl_rcpz = rcp;
X if (rcp == sf)
X pltsrchfld = 1;
X r = unpackr (rcp); c = unpackc (rcp);
X }
X
X do {
X sprintf (buf, "enter a one-character label for line %d: ", i+1);
X f_prompt (buf);
X } while (read_line (buf, 1) != 1);
X pltlines[i].pl_label = *buf;
X }
X npltlines = i;
X}
X
Xstatic
Xplt_turn_off ()
X{
X fclose (plt_fp);
X plt_fp = 0;
X plot_prstate(0);
X}
X
X/* turn on plotting.
X * establish a file to use (and thereby set plt_fp, the plotting_is_on flag).
X * also check that there is a srch function if it is being plotted.
X */
Xstatic
Xplt_turn_on ()
X{
X int sf = rcfpack(R_SRCH, C_SRCH, 0);
X char fn[FNLEN], fnq[64];
X char *optype;
X int n;
X PltLine *plp;
X
X /* insure there is a valid srch function if we are to plot it */
X for (plp = &pltlines[npltlines]; --plp >= pltlines; )
X if ((plp->pl_rcpx == sf || plp->pl_rcpy == sf || plp->pl_rcpz == sf)
X && !prog_isgood()) {
X f_msg ("Plotting search function but it is not defined.");
X return;
X }
X
X /* prompt for file name, giving current as default */
X sprintf (fnq, "file to write <%s>: ", plt_filename);
X f_prompt (fnq);
X n = read_line (fn, sizeof(fn)-1);
X
X /* leave plotting off if type END.
X * reuse same fn if just type \n
X */
X if (n < 0)
X return;
X if (n > 0)
X strcpy (plt_filename, fn);
X
X /* give option to append if file already exists */
X optype = "w";
X if (access (plt_filename, 2) == 0) {
X while (1) {
X f_prompt ("files exists; append or overwrite (a/o)?: ");
X n = read_char();
X if (n == 'a') {
X optype = "a";
X break;
X }
X if (n == 'o')
X break;
X }
X }
X
X /* plotting is on if file opens ok */
X plt_fp = fopen (plt_filename, optype);
X if (!plt_fp) {
X char buf[NC];
X sprintf (buf, "can not open %s: %s", plt_filename, errsys);
X f_prompt (buf);
X (void)read_char();
X }
X plot_prstate (0);
X}
X
X/* ask operator for a file to plot. if it's ok, do it.
X */
Xstatic
Xplt_file ()
X{
X char fn[FNLEN], fnq[64];
X FILE *pfp;
X int n;
X
X /* prompt for file name, giving current as default */
X sprintf (fnq, "file to read <%s>: ", plt_filename);
X f_prompt (fnq);
X n = read_line (fn, sizeof(fn)-1);
X
X /* forget it if type END.
X * reuse same fn if just type \n
X */
X if (n < 0)
X return;
X if (n > 0)
X strcpy (plt_filename, fn);
X
X /* do the plot if file opens ok */
X pfp = fopen (plt_filename, "r");
X if (pfp) {
X if (plt_in_polar)
X plot_polar (pfp);
X else
X plot_cartesian (pfp);
X fclose (pfp);
X } else {
X char buf[NC];
X sprintf (buf, "can not open %s: %s", plt_filename, errsys);
X f_prompt (buf);
X (void)read_char();
X }
X}
X
X/* plot the given file on the screen in cartesian coords.
X * TODO: add z tags somehow
X * N.B. do whatever you like but redraw the screen when done.
X */
Xstatic
Xplot_cartesian (pfp)
XFILE *pfp;
X{
X static char fmt[] = "%c,%lf,%lf";
X double x, y; /* N.B. be sure these match what scanf's %lf wants*/
X double minx, maxx, miny, maxy;
X char buf[128];
X int npts = 0;
X char c;
X
X /* find ranges and number of points */
X while (fgets (buf, sizeof(buf), pfp)) {
X sscanf (buf, fmt, &c, &x, &y);
X if (npts++ == 0) {
X maxx = minx = x;
X maxy = miny = y;
X } else {
X if (x > maxx) maxx = x;
X else if (x < minx) minx = x;
X if (y > maxy) maxy = y;
X else if (y < miny) miny = y;
X }
X }
X
X#define SMALL (1e-10)
X if (npts < 2 || fabs(minx-maxx) < SMALL || fabs(miny-maxy) < SMALL)
X f_prompt ("At least two different points required to plot.");
X else {
X /* read file again, this time plotting */
X rewind (pfp);
X c_erase();
X while (fgets (buf, sizeof(buf), pfp)) {
X int row, col;
X sscanf (buf, fmt, &c, &x, &y);
X row = NR-(int)((NR-1)*(y-miny)/(maxy-miny)+0.5);
X col = 1+(int)((NC-1)*(x-minx)/(maxx-minx)+0.5);
X if (row == NR && col == NC)
X col--; /* avoid lower right scrolling corner */
X f_char (row, col, c);
X }
X
X /* label axes */
X f_double (1, 1, "%.2g", maxy);
X f_double (NR-1, 1, "%.2g", miny);
X f_double (NR, 1, "%.2g", minx);
X f_double (NR, NC-10, "%.2g", maxx);
X }
X
X /* hit any key to resume... */
X (void) read_char();
X redraw_screen (2); /* full redraw */
X}
X
X/* plot the given file on the screen in polar coords.
X * first numberic field in plot file is r, second is theta in degrees.
X * TODO: add z tags somehow
X * N.B. do whatever you like but redraw the screen when done.
X */
Xstatic
Xplot_polar (pfp)
XFILE *pfp;
X{
X static char fmt[] = "%c,%lf,%lf";
X double r, th; /* N.B. be sure these match what scanf's %lf wants*/
X double maxr;
X char buf[128];
X int npts = 0;
X char c;
X
X /* find ranges and number of points */
X while (fgets (buf, sizeof(buf), pfp)) {
X sscanf (buf, fmt, &c, &r, &th);
X if (npts++ == 0)
X maxr = r;
X else
X if (r > maxr)
X maxr = r;
X }
X
X if (npts < 2)
X f_prompt ("At least two points required to plot.");
X else {
X /* read file again, this time plotting */
X rewind (pfp);
X c_erase();
X while (fgets (buf, sizeof(buf), pfp)) {
X int row, col;
X double x, y;
X sscanf (buf, fmt, &c, &r, &th);
X x = r * cos(th/57.2958); /* degs to rads */
X y = r * sin(th/57.2958);
X row = NR-(int)((NR-1)*(y+maxr)/(2.0*maxr)+0.5);
X col = 1+(int)((NC-1)*(x+maxr)/(2.0*maxr)/ASPECT+0.5);
X if (row == NR && col == NC)
X col--; /* avoid lower right scrolling corner */
X f_char (row, col, c);
X }
X
X /* label radius */
X f_double (NR/2, NC-10, "%.4g", maxr);
X }
X
X /* hit any key to resume... */
X (void) read_char();
X redraw_screen (2); /* full redraw */
X}
EOFxEOF
len=`wc -c < plot.c`
if expr $len != 10712 > /dev/null
then echo Length of plot.c is $len but it should be 10712.
fi
echo x popup.c
sed -e 's/^X//' << 'EOFxEOF' > popup.c
X/* put up a one-line menu consisting of the given fields and let op move
X * between them with the same methods as sel_fld().
X * return index of which he picked, or -1 if hit END.
X */
X
X#include <stdio.h>
X#include "screen.h"
X
X#define FLDGAP 2 /* inter-field gap */
X#define MAXFLDS 32 /* max number of fields we can handle */
X
Xstatic char pup[] = "Select: ";
X
X/* put up an array of strings on prompt line and let op pick one.
X * start with field fn.
X * N.B. we do not do much error/bounds checking.
X */
Xpopup (fields, fn, nfields)
Xchar *fields[];
Xint fn;
Xint nfields;
X{
X int fcols[MAXFLDS]; /* column to use for each field */
X int i;
X
X if (nfields > MAXFLDS)
X return (-1);
X
X again:
X /* erase the prompt line; we are going to take it over */
X c_pos (R_PROMPT, C_PROMPT);
X c_eol();
X
X /* compute starting column for each field */
X fcols[0] = sizeof(pup);
X for (i = 1; i < nfields; i++)
X fcols[i] = fcols[i-1] + strlen (fields[i-1]) + FLDGAP;
X
X /* draw each field, with comma after all but last */
X c_pos (R_PROMPT, 1);
X fputs (pup, stdout);
X for (i = 0; i < nfields; i++) {
X c_pos (R_PROMPT, fcols[i]);
X printf (i < nfields-1 ? "%s," : "%s", fields[i]);
X }
X
X /* let op choose one now; begin at fn.
X */
X i = fn;
X while (1) {
X c_pos (R_PROMPT, fcols[i]);
X switch (read_char()) {
X case END: return (-1);
X case REDRAW: redraw_screen(2); goto again;
X case VERSION: version(); goto again;
X case '\r': return (i);
X case 'h':
X if (--i < 0)
X i = nfields - 1;
X break;
X case 'l':
X if (++i >= nfields)
X i = 0;
X break;
X }
X }
X}
EOFxEOF
len=`wc -c < popup.c`
if expr $len != 1578 > /dev/null
then echo Length of popup.c is $len but it should be 1578.
fi
echo x precess.c
sed -e 's/^X//' << 'EOFxEOF' > precess.c
X#include <stdio.h>
X#include <math.h>
X#include "astro.h"
X
X/* corrects ra and dec, both in radians, for precession from epoch 1 to epoch 2.
X * the epochs are given by their modified JDs, mjd1 and mjd2, respectively.
X * N.B. ra and dec are modifed IN PLACE.
X */
Xprecess (mjd1, mjd2, ra, dec)
Xdouble mjd1, mjd2; /* initial and final epoch modified JDs */
Xdouble *ra, *dec; /* ra/dec for mjd1 in, for mjd2 out */
X{
X static double lastmjd1, lastmjd2;
X static double m, n, nyrs;
X double dra, ddec; /* ra and dec corrections */
X
X if (mjd1 != lastmjd1 || mjd2 != lastmjd2) {
X double t1, t2; /* Julian centuries of 36525 days since Jan .5 1900*/
X double m1, n1; /* "constants" for t1 */
X double m2, n2; /* "constants" for t2 */
X t1 = mjd1/36525.;
X t2 = mjd2/36525.;
X m1 = 3.07234+(1.86e-3*t1);
X n1 = 20.0468-(8.5e-3*t1);
X m2 = 3.07234+(1.86e-3*t2);
X n2 = 20.0468-(8.5e-3*t2);
X m = (m1+m2)/2; /* average m for the two epochs */
X n = (n1+n2)/2; /* average n for the two epochs */
X nyrs = (mjd2-mjd1)/365.2425;
X lastmjd1 = mjd1;
X lastmjd2 = mjd2;
X }
X
X dra = (m+(n*sin(*ra)*tan(*dec)/15))*7.272205e-5*nyrs;
X ddec = n*cos(*ra)*4.848137e-6*nyrs;
X *ra += dra;
X *dec += ddec;
X /* added by ECD */
X if (*dec > PI/2) {
X *dec = PI - *dec;
X *ra += PI;
X } else if (*dec < -PI/2) {
X *dec = -PI - *dec;
X *ra += PI;
X }
X range (ra, 2*PI);
X}
EOFxEOF
len=`wc -c < precess.c`
if expr $len != 1385 > /dev/null
then echo Length of precess.c is $len but it should be 1385.
fi
echo x reduce.c
sed -e 's/^X//' << 'EOFxEOF' > reduce.c
X#include <math.h>
X#include "astro.h"
X
X/* convert those orbital elements that change from epoch mjd0 to epoch mjd.
X */
Xreduce_elements (mjd0, mjd, inc0, ap0, om0, inc, ap, om)
Xdouble mjd0; /* initial epoch */
Xdouble mjd; /* desired epoch */
Xdouble inc0; /* initial inclination, rads */
Xdouble ap0; /* initial argument of perihelion, as an mjd */
Xdouble om0; /* initial , rads */
Xdouble *inc; /* desired inclination, rads */
Xdouble *ap; /* desired epoch of perihelion, as an mjd */
Xdouble *om; /* desired , rads */
X{
X double t0, t1;
X double tt, tt2, t02, tt3;
X double eta, th, th0;
X double a, b;
X double dap;
X double cinc, sinc;
X double ot, sot, cot, ot1;
X double seta, ceta;
X
X t0 = mjd0/365250.0;
X t1 = mjd/365250.0;
X
X tt = t1-t0;
X tt2 = tt*tt;
X t02 = t0*t0;
X tt3 = tt*tt2;
X eta = (471.07-6.75*t0+.57*t02)*tt+(.57*t0-3.37)*tt2+.05*tt3;
X th0 = 32869.0*t0+56*t02-(8694+55*t0)*tt+3*tt2;
X eta = degrad(eta/3600.0);
X th0 = degrad((th0/3600.0)+173.950833);
X th = (50256.41+222.29*t0+.26*t02)*tt+(111.15+.26*t0)*tt2+.1*tt3;
X th = th0+degrad(th/3600.0);
X cinc = cos(inc0);
X sinc = sin(inc0);
X ot = om0-th0;
X sot = sin(ot);
X cot = cos(ot);
X seta = sin(eta);
X ceta = cos(eta);
X a = sinc*sot;
X b = ceta*sinc*cot-seta*cinc;
X ot1 = atan(a/b);
X if (b<0) ot1 += PI;
X b = sinc*ceta-cinc*seta*cot;
X a = -1*seta*sot;
X dap = atan(a/b);
X if (b<0) dap += PI;
X
X *ap = ap0+dap;
X range (ap, 2*PI);
X *om = ot1+th;
X range (om, 2*PI);
X
X if (inc0<.175)
X *inc = asin(a/sin(dap));
X else
X *inc = 1.570796327-asin((cinc*ceta)+(sinc*seta*cot));
X}
EOFxEOF
len=`wc -c < reduce.c`
if expr $len != 1647 > /dev/null
then echo Length of reduce.c is $len but it should be 1647.
fi
echo x refract.c
sed -e 's/^X//' << 'EOFxEOF' > refract.c
X#include <stdio.h>
X#include <math.h>
X#include "astro.h"
X
X/* correct the true altitude, ta, for refraction to the apparent altitude, aa,
X * each in radians, given the local atmospheric pressure, pr, in mbars, and
X * the temperature, tr, in degrees C.
X */
Xrefract (pr, tr, ta, aa)
Xdouble pr, tr;
Xdouble ta;
Xdouble *aa;
X{
X double r; /* refraction correction*/
X
X if (ta >= degrad(15.)) {
X /* model for altitudes at least 15 degrees above horizon */
X r = 7.888888e-5*pr/((273+tr)*tan(ta));
X } else if (ta > degrad(-5.)) {
X /* hairier model for altitudes at least -5 and below 15 degrees */
X double a, b, tadeg = raddeg(ta);
X a = ((2e-5*tadeg+1.96e-2)*tadeg+1.594e-1)*pr;
X b = (273+tr)*((8.45e-2*tadeg+5.05e-1)*tadeg+1);
X r = degrad(a/b);
X } else {
X /* do nothing if more than 5 degrees below horizon.
X */
X r = 0;
X }
X
X *aa = ta + r;
X}
X
X/* correct the apparent altitude, aa, for refraction to the true altitude, ta,
X * each in radians, given the local atmospheric pressure, pr, in mbars, and
X * the temperature, tr, in degrees C.
X */
Xunrefract (pr, tr, aa, ta)
Xdouble pr, tr;
Xdouble aa;
Xdouble *ta;
X{
X double err;
X double appar;
X double true;
X
X /* iterative solution: search for the true that refracts to the
X * given apparent.
X * since refract() is discontinuous at -5 degrees, there is a range
X * of apparent altitudes between about -4.5 and -5 degrees that are
X * not invertable (the graph of ap vs. true has a vertical step at
X * true = -5). thus, the iteration just oscillates if it gets into
X * this region. if this happens the iteration is forced to abort.
X * of course, this makes unrefract() discontinuous too.
X */
X true = aa;
X do {
X refract (pr, tr, true, &appar);
X err = appar - aa;
X true -= err;
X } while (fabs(err) >= 1e-6 && true > degrad(-5));
X
X *ta = true;
X}
EOFxEOF
len=`wc -c < refract.c`
if expr $len != 1857 > /dev/null
then echo Length of refract.c is $len but it should be 1857.
fi
echo x riset.c
sed -e 's/^X//' << 'EOFxEOF' > riset.c
X#include <stdio.h>
X#include <math.h>
X#include "astro.h"
X
X/* given the true geocentric ra and dec of an object, in radians, the observer's
X * latitude in radians, and a horizon displacement correction, dis, in radians
X * find the local sidereal times and azimuths of rising and setting, lstr/s
X * and azr/s, in radians, respectively.
X * dis is the vertical displacement from the true position of the horizon. it
X * is positive if the apparent position is higher than the true position.
X * said another way, it is positive if the shift causes the object to spend
X * longer above the horizon. for example, atmospheric refraction is typically
X * assumed to produce a vertical shift of 34 arc minutes at the horizon; dis
X * would then take on the value +9.89e-3 (radians). On the other hand, if
X * your horizon has hills such that your apparent horizon is, say, 1 degree
X * above sea level, you would allow for this by setting dis to -1.75e-2
X * (radians).
X * status: 0: normal; 1: never rises; -1: circumpolar; 2: trouble.
X */
Xriset (ra, dec, lat, dis, lstr, lsts, azr, azs, status)
Xdouble ra, dec;
Xdouble lat, dis;
Xdouble *lstr, *lsts;
Xdouble *azr, *azs;
Xint *status;
X{
X static double lastlat = 0, slat = 0, clat = 1.0;
X double dec1, sdec, cdec, tdec;
X double psi, spsi, cpsi;
X double h, dh, ch; /* hr angle, delta and cos */
X
X /* avoid needless sin/cos since latitude doesn't change often */
X if (lat != lastlat) {
X clat = cos(lat);
X slat = sin(lat);
X lastlat = lat;
X }
X
X /* can't cope with objects very near the celestial pole nor if we
X * are located very near the earth's poles.
X */
X cdec = cos(dec);
X if (fabs(cdec*clat) < 1e-10) {
X /* trouble */
X *status = 2;
X return;
X }
X
X cpsi = slat/cdec;
X if (cpsi>1.0) cpsi = 1.0;
X else if (cpsi<-1.0) cpsi = -1.0;
X psi = acos(cpsi);
X spsi = sin(psi);
X
X dh = dis*spsi;
X dec1 = dec + (dis*cpsi);
X sdec = sin(dec1);
X tdec = tan(dec1);
X
X ch = (-1*slat*tdec)/clat;
X
X if (ch < -1) {
X /* circumpolar */
X *status = -1;
X return;
X }
X if (ch > 1) {
X /* never rises */
X *status = 1;
X return;
X }
X
X *status = 0;
X h = acos(ch)+dh;
X
X *lstr = 24+radhr(ra-h);
X *lsts = radhr(ra+h);
X range (lstr, 24.0);
X range (lsts, 24.0);
X
X *azr = acos(sdec/clat);
X range (azr, 2*PI);
X *azs = 2*PI - *azr;
X}
EOFxEOF
len=`wc -c < riset.c`
if expr $len != 2388 > /dev/null
then echo Length of riset.c is $len but it should be 2388.
fi
echo x riset_c.c
sed -e 's/^X//' << 'EOFxEOF' > riset_c.c
X/* find rise and set circumstances, ie, riset_cir() and related functions. */
X
X#include <stdio.h>
X#include <math.h>
X#include "astro.h"
X#include "circum.h"
X#include "screen.h" /* just for SUN and MOON */
X
X#define TRACE(x) {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);}
X
X#define STDREF degrad(34./60.) /* nominal horizon refraction amount */
X#define TWIREF degrad(18.) /* twilight horizon displacement */
X
X/* find where and when a body, p, will rise and set and
X * its transit circumstances. all times are local, angles rads e of n.
X * return 0 if just returned same stuff as previous call, else 1 if new.
X * status is set from the RS_* #defines in circum.h.
X * also used to find astro twilight by calling with dis of 18 degrees.
X */
Xriset_cir (p, np, hzn, ltr, lts, ltt, azr, azs, altt, status)
Xint p; /* one of the body defines in astro.h or screen.h */
XNow *np;
Xint hzn; /* STDHZN or ADPHZN or TWILIGHT */
Xdouble *ltr, *lts; /* local rise and set times */
Xdouble *ltt; /* local transit time */
Xdouble *azr, *azs; /* local rise and set azimuths, rads e of n */
Xdouble *altt; /* local altitude at transit */
Xint *status; /* one or more of the RS_* defines */
X{
X typedef struct {
X Now l_now;
X double l_ltr, l_lts, l_ltt, l_azr, l_azs, l_altt;
X int l_hzn;
X int l_status;
X } Last;
X /* must be in same order as the astro.h/screen.h #define's */
X static Last last[NOBJ];
X Last *lp;
X int new;
X
X lp = last + p;
X if (same_cir (np, &lp->l_now) && same_lday (np, &lp->l_now)
X && lp->l_hzn == hzn) {
X *ltr = lp->l_ltr;
X *lts = lp->l_lts;
X *ltt = lp->l_ltt;
X *azr = lp->l_azr;
X *azs = lp->l_azs;
X *altt = lp->l_altt;
X *status = lp->l_status;
X new = 0;
X } else {
X *status = 0;
X iterative_riset (p, np, hzn, ltr, lts, ltt, azr, azs, altt, status);
X lp->l_ltr = *ltr;
X lp->l_lts = *lts;
X lp->l_ltt = *ltt;
X lp->l_azr = *azr;
X lp->l_azs = *azs;
X lp->l_altt = *altt;
X lp->l_status = *status;
X lp->l_hzn = hzn;
X lp->l_now = *np;
X new = 1;
X }
X return (new);
X}
X
Xstatic
Xiterative_riset (p, np, hzn, ltr, lts, ltt, azr, azs, altt, status)
Xint p;
XNow *np;
Xint hzn;
Xdouble *ltr, *lts, *ltt; /* local times of rise, set and transit */
Xdouble *azr, *azs, *altt;/* local azimuths of rise, set and transit altitude */
Xint *status;
X{
X#define MAXPASSES 6
X double lstr, lsts, lstt; /* local sidereal times of rising/setting */
X double mjd0; /* mjd estimates of rise/set event */
X double lnoon; /* mjd of local noon */
X double x; /* discarded tmp value */
X Now n; /* just used to call now_lst() */
X double lst; /* lst at local noon */
X double diff, lastdiff; /* iterative improvement to mjd0 */
X int pass;
X int rss;
X
X /* first approximation is to find rise/set times of a fixed object
X * in its position at local noon.
X */
X lnoon = mjd_day(mjd - tz/24.0) + (12.0 + tz)/24.0; /*mjd of local noon*/
X n.n_mjd = lnoon;
X n.n_lng = lng;
X now_lst (&n, &lst); /* lst at local noon */
X mjd0 = lnoon;
X stationary_riset (p,mjd0,np,hzn,&lstr,&lsts,&lstt,&x,&x,&x,&rss);
X chkrss:
X switch (rss) {
X case 0: break;
X case 1: *status = RS_NEVERUP; return;
X case -1: *status = RS_CIRCUMPOLAR; goto transit;
X default: *status = RS_ERROR; return;
X }
X
X /* find a better approximation to the rising circumstances based on
X * more passes, each using a "fixed" object at the location at
X * previous approximation of the rise time.
X */
X lastdiff = 1000.0;
X for (pass = 1; pass < MAXPASSES; pass++) {
X diff = (lstr - lst)*SIDRATE; /* next guess at rise time wrt noon */
X if (diff > 12.0)
X diff -= 24.0*SIDRATE; /* not tomorrow, today */
X else if (diff < -12.0)
X diff += 24.0*SIDRATE; /* not yesterday, today */
X mjd0 = lnoon + diff/24.0; /* next guess at mjd of rise */
X stationary_riset (p,mjd0,np,hzn,&lstr,&x,&x,azr,&x,&x,&rss);
X if (rss != 0) goto chkrss;
X if (fabs (diff - lastdiff) < 0.25/60.0)
X break; /* converged to better than 15 secs */
X lastdiff = diff;
X }
X if (pass == MAXPASSES)
X *status |= RS_NORISE; /* didn't converge - no rise today */
X else {
X *ltr = 12.0 + diff;
X if (p != MOON &&
X (*ltr <= 24.0*(1.0-SIDRATE) || *ltr >= 24.0*SIDRATE))
X *status |= RS_2RISES;
X }
X
X /* find a better approximation to the setting circumstances based on
X * more passes, each using a "fixed" object at the location at
X * previous approximation of the set time.
X */
X lastdiff = 1000.0;
X for (pass = 1; pass < MAXPASSES; pass++) {
X diff = (lsts - lst)*SIDRATE; /* next guess at set time wrt noon */
X if (diff > 12.0)
X diff -= 24.0*SIDRATE; /* not tomorrow, today */
X else if (diff < -12.0)
X diff += 24.0*SIDRATE; /* not yesterday, today */
X mjd0 = lnoon + diff/24.0; /* next guess at mjd of set */
X stationary_riset (p,mjd0,np,hzn,&x,&lsts,&x,&x,azs,&x,&rss);
X if (rss != 0) goto chkrss;
X if (fabs (diff - lastdiff) < 0.25/60.0)
X break; /* converged to better than 15 secs */
X lastdiff = diff;
X }
X if (pass == MAXPASSES)
X *status |= RS_NOSET; /* didn't converge - no set today */
X else {
X *lts = 12.0 + diff;
X if (p != MOON &&
X (*lts <= 24.0*(1.0-SIDRATE) || *lts >= 24.0*SIDRATE))
X *status |= RS_2SETS;
X }
X
X transit:
X /* find a better approximation to the transit circumstances based on
X * more passes, each using a "fixed" object at the location at
X * previous approximation of the transit time.
X */
X lastdiff = 1000.0;
X for (pass = 1; pass < MAXPASSES; pass++) {
X diff = (lstt - lst)*SIDRATE; /*next guess at transit time wrt noon*/
X if (diff > 12.0)
X diff -= 24.0*SIDRATE; /* not tomorrow, today */
X else if (diff < -12.0)
X diff += 24.0*SIDRATE; /* not yesterday, today */
X mjd0 = lnoon + diff/24.0; /* next guess at mjd of set */
X stationary_riset (p,mjd0,np,hzn,&x,&x,&lstt,&x,&x,altt,&rss);
X if (fabs (diff - lastdiff) < 0.25/60.0)
X break; /* converged to better than 15 secs */
X lastdiff = diff;
X }
X if (pass == MAXPASSES)
X *status |= RS_NOTRANS; /* didn't converge - no transit today */
X else {
X *ltt = 12.0 + diff;
X if (p != MOON &&
X (*ltt <= 24.0*(1.0-SIDRATE) || *ltt >= 24.0*SIDRATE))
X *status |= RS_2TRANS;
X }
X}
X
Xstatic
Xstationary_riset (p, mjd0, np, hzn, lstr, lsts, lstt, azr, azs, altt, status)
Xint p;
Xdouble mjd0;
XNow *np;
Xint hzn;
Xdouble *lstr, *lsts, *lstt;
Xdouble *azr, *azs, *altt;
Xint *status;
X{
X extern void bye();
X double dis;
X Now n;
X Sky s;
X
X switch (hzn) {
X case STDHZN:
X /* nominal atmospheric refraction.
X * then add nominal moon or sun semi-diameter, as appropriate.
X */
X dis = STDREF;
X break;
X case TWILIGHT:
X if (p != SUN) {
X f_msg ("Non-sun twilight bug!");
X bye();
X }
X dis = TWIREF;
X break;
X default:
X /* horizon displacement is refraction plus object's semi-diameter */
X unrefract (pressure, temp, 0.0, &dis);
X dis = -dis;
X n = *np;
X n.n_mjd = mjd0;
X (void) body_cir (p, 0.0, &n, &s);
X dis += degrad(s.s_size/3600./2.0);
X }
X
X switch (p) {
X case SUN:
X if (hzn == STDHZN)
X dis += degrad (32./60./2.);
X fixedsunriset (mjd0,np,dis,lstr,lsts,lstt,azr,azs,altt,status);
X break;
X case MOON:
X if (hzn == STDHZN)
X dis += degrad (32./60./2.);
X fixedmoonriset (mjd0,np,dis,lstr,lsts,lstt,azr,azs,altt,status);
X break;
X default:
X if (hzn == STDHZN) {
X /* assume planets have negligible diameters.
X * also, need to set s if hzn was STDHZN.
X */
X n = *np;
X n.n_mjd = mjd0;
X (void) body_cir (p, 0.0, &n, &s);
X }
X riset (s.s_ra, s.s_dec, lat, dis, lstr, lsts, azr, azs, status);
X transit (s.s_ra, s.s_dec, np, lstt, altt);
X }
X}
X
X/* find the local rise/set sidereal times and azimuths of an object fixed
X * at the ra/dec of the sun on the given mjd time as seen from lat.
X * times are for the upper limb. dis should account for refraction and
X * sun's semi-diameter; we add corrections for nutation and aberration.
X */
Xstatic
Xfixedsunriset (mjd0, np, dis, lstr, lsts, lstt, azr, azs, altt, status)
Xdouble mjd0;
XNow *np;
Xdouble dis;
Xdouble *lstr, *lsts, *lstt;
Xdouble *azr, *azs, *altt;
Xint *status;
X{
X double lsn, rsn;
X double deps, dpsi;
X double r, d;
X
X /* find ecliptic position of sun at mjd */
X sunpos (mjd0, &lsn, &rsn);
X
X /* allow for nutation and 20.4" light travel time */
X nutation (mjd0, &deps, &dpsi);
X lsn += dpsi;
X lsn -= degrad(20.4/3600.0);
X
X /* convert ecliptic to equatorial coords */
X ecl_eq (mjd0, 0.0, lsn, &r, &d);
X
X /* find circumstances for given horizon displacement */
X riset (r, d, lat, dis, lstr, lsts, azr, azs, status);
X transit (r, d, np, lstt, altt);
X}
X
X/* find the local sidereal rise/set times and azimuths of an object fixed
X * at the ra/dec of the moon on the given mjd time as seen from lat.
X * times are for the upper limb. dis should account for refraction and moon's
X * semi-diameter; we add corrections for parallax, and nutation.
X * accuracy is to nearest minute.
X */
Xstatic
Xfixedmoonriset (mjd0, np, dis, lstr, lsts, lstt, azr, azs, altt, status)
Xdouble mjd0;
XNow *np;
Xdouble dis;
Xdouble *lstr, *lsts, *lstt;
Xdouble *azr, *azs, *altt;
Xint *status;
X{
X double lam, bet, hp;
X double deps, dpsi;
X double r, d;
X double ha;
X
X /* find geocentric ecliptic location and equatorial horizontal parallax
X * of moon at mjd.
X */
X moon (mjd0, &lam, &bet, &hp);
X
X /* allow for nutation */
X nutation (mjd0, &deps, &dpsi);
X lam += dpsi;
X
X /* convert ecliptic to equatorial coords */
X ecl_eq (mjd0, bet, lam, &r, &d);
X
X /* find local sidereal times of rise/set times/azimuths for given
X * equatorial coords, allowing for
X * .27249*sin(hp) parallax (hp is radius of earth from moon;
X * .27249 is radius of moon from earth where
X * the ratio is the dia_moon/dia_earth).
X * hp nominal angular earth radius. subtract because
X * tangential line-of-sight makes moon appear lower
X * as move out from center of earth.
X */
X dis += .27249*sin(hp) - hp;
X riset (r, d, lat, dis, lstr, lsts, azr, azs, status);
X
X /* account for parallax on the meridian (0 hour-angle).
X * TODO: is this really right? other stuff too? better way?? help!
X */
X ta_par (0.0, d, lat, height, hp, &ha, &d);
X transit (r+ha, d, np, lstt, altt);
X}
X
X/* find when and how hi object at (r,d) is when it transits. */
Xstatic
Xtransit (r, d, np, lstt, altt)
Xdouble r, d; /* ra and dec, rads */
XNow *np; /* for refraction info */
Xdouble *lstt; /* local sidereal time of transit */
Xdouble *altt; /* local, refracted, altitude at time of transit */
X{
X *lstt = radhr(r);
X *altt = PI/2 - lat + d;
X if (*altt > PI/2)
X *altt = PI - *altt;
X refract (pressure, temp, *altt, altt);
X}
EOFxEOF
len=`wc -c < riset_c.c`
if expr $len != 10652 > /dev/null
then echo Length of riset_c.c is $len but it should be 10652.
fi
echo x sel_fld.c
sed -e 's/^X//' << 'EOFxEOF' > sel_fld.c
X#include <stdio.h>
X#include "screen.h"
X
X/* table of the fields, with flags indicating which menu(s) they are on and
X * whether pickable for changing or plotting.
X * N.B. type must be long enough to hold 16 bits.
X */
Xstatic int fields[] = {
X rcfpack (R_ALTM, C_ALTM, F_MMNU|F_CHG),
X rcfpack (R_DAWN, C_DAWN, F_MMNU|F_CHG),
X rcfpack (R_DAWN, C_DAWNV, F_MMNU|F_PLT),
X rcfpack (R_DUSK, C_DUSK, F_MMNU|F_CHG),
X rcfpack (R_DUSK, C_DUSKV, F_MMNU|F_PLT),
X rcfpack (R_EPOCH, C_EPOCHV, F_MMNU|F_CHG),
X rcfpack (R_HEIGHT, C_HEIGHTV, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_JD, C_JDV, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_JUPITER, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_JUPITER, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_RA, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_JUPITER, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_JUPITER, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_JUPITER, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_JUPITER, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_JUPITER, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_JUPITER, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_JUPITER, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_JUPITER, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_JUPITER, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_LAT, C_LATV, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_LD, C_LD, F_MMNU|F_PLT|F_CHG),
X rcfpack (R_LON, C_LON, F_MMNU|F_CHG),
X rcfpack (R_LON, C_LONV, F_MMNU|F_PLT),
X rcfpack (R_LONG, C_LONGV, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_LST, C_LSTV, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_LT, C_LT, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_MARS, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_MARS, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_RA, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_MARS, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_MARS, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_MARS, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_MARS, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_MARS, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_MARS, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_MARS, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_MARS, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_MARS, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_MERCURY, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_RA, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_MERCURY, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_MERCURY, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_MERCURY, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_MERCURY, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_MERCURY, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_MERCURY, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_MERCURY, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_MERCURY, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_MERCURY, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_MOON, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_RA, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_MOON, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_MOON, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_MOON, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_MOON, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_MOON, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_MOON, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_MOON, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_MOON, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_MOON, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_NEPTUNE, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_RA, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_NEPTUNE, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_NEPTUNE, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_NEPTUNE, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_NEPTUNE, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_NEPTUNE, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_NEPTUNE, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_NEPTUNE, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_NEPTUNE, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_NEPTUNE, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_NSTEP, C_NSTEPV, F_MMNU|F_CHG),
X rcfpack (R_OBJX, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_OBJX, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_RA, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_OBJX, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_OBJX, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_OBJX, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_OBJX, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_OBJX, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_OBJX, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_OBJX, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_OBJX, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_OBJX, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_PLOT, C_PLOT, F_MMNU|F_CHG),
X rcfpack (R_PLUTO, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_PLUTO, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_RA, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_PLUTO, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_PLUTO, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_PLUTO, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_PLUTO, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_PLUTO, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_PLUTO, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_PLUTO, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_PLUTO, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_PLUTO, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_PRES, C_PRESV, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_SATURN, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_SATURN, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_RA, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_SATURN, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_SATURN, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_SATURN, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_SATURN, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_SATURN, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_SATURN, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_SATURN, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_SATURN, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_SATURN, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_SRCH, C_SRCH, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_STPSZ, C_STPSZV, F_MMNU|F_CHG),
X rcfpack (R_SUN, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_SUN, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_SUN, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_SUN, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_SUN, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_SUN, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_SUN, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_SUN, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_RA, F_MNU1|F_PLT),
X rcfpack (R_SUN, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_SUN, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_SUN, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_SUN, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_SUN, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_SUN, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_SUN, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_SUN, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_SUN, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_SUN, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_TEMP, C_TEMPV, F_MMNU|F_CHG|F_PLT),
X rcfpack (R_TZN, C_TZN, F_MMNU|F_CHG),
X rcfpack (R_TZONE, C_TZONEV, F_MMNU|F_CHG),
X rcfpack (R_UD, C_UD, F_MMNU|F_PLT|F_CHG),
X rcfpack (R_URANUS, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_URANUS, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_RA, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_URANUS, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_URANUS, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_URANUS, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_URANUS, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_URANUS, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_URANUS, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_URANUS, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_URANUS, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_URANUS, C_VENUS, F_MNU3|F_PLT),
X rcfpack (R_UT, C_UTV, F_MMNU|F_PLT|F_CHG),
X rcfpack (R_VENUS, C_ALT, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_AZ, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_DEC, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_EDIST, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_ELONG, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_HLAT, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_HLONG, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_JUPITER, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_MAG, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_MARS, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_MERCURY, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_MOON, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_NEPTUNE, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_OBJ, F_MMNU|F_CHG),
X rcfpack (R_VENUS, C_OBJX, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_PHASE, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_PLUTO, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_RA, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_RISEAZ, F_MNU2|F_PLT),
X rcfpack (R_VENUS, C_RISETM, F_MNU2|F_PLT),
X rcfpack (R_VENUS, C_SATURN, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_SDIST, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_SETAZ, F_MNU2|F_PLT),
X rcfpack (R_VENUS, C_SETTM, F_MNU2|F_PLT),
X rcfpack (R_VENUS, C_SIZE, F_MNU1|F_PLT),
X rcfpack (R_VENUS, C_SUN, F_MNU3|F_PLT),
X rcfpack (R_VENUS, C_TRANSALT, F_MNU2|F_PLT),
X rcfpack (R_VENUS, C_TRANSTM, F_MNU2|F_PLT),
X rcfpack (R_VENUS, C_TUP, F_MNU2|F_PLT),
X rcfpack (R_VENUS, C_URANUS, F_MNU3|F_PLT),
X rcfpack (R_WATCH, C_WATCH, F_MMNU|F_CHG),
X};
X#define NFIELDS (sizeof(fields)/sizeof(fields[0]))
X
X/* let op select a field by moving around and hitting RETURN, or until see END.
X * also allow moving directly to a planet row using its name.
X * only allow fields with the given flag mask.
X * return the rcfpack()'d field, or 0 if typed END.
X * N.B. we might also exit() entirely by calling bye() if op types QUIT.
X */
Xsel_fld (r, c, flag, prmpt, help)
Xint r, c; /* inial row, col */
Xint flag;
Xchar *prmpt, *help;
X{
X extern void bye();
X char *lastp;
X int ch;
X
X lastp = 0;
X while (1) {
X if (lastp != prmpt) {
X lastp = prmpt;
X f_prompt (lastp);
X }
X c_pos (r, c);
X switch (ch = read_char()) {
X case REDRAW:
X redraw_screen(2); /* redraw all from scratch */
X lastp = 0;
X break;
X case VERSION:
X version();
X lastp = 0;
X break;
X case HELP:
X f_msg (help);
X lastp = 0;
X break;
X case QUIT:
X f_prompt ("Exit ephem? (y) ");
X if (read_char() == 'y')
X bye(); /* never returns */
X lastp = 0;
X break;
X case END:
X return (0);
X case '\r':
X return (rcfpack (r, c, 0));
X default:
X move_cur (ch, flag, &r, &c);
X break;
X }
X }
X}
X
X/* move cursor to next field in given direction: hjkl, or directly to a
X * field, and set *rp and *cp.
X * limit eligible fields to those with given flag mask.
X */
Xstatic
Xmove_cur (dirchar, flag, rp, cp)
Xchar dirchar;
Xint flag;
Xint *rp, *cp;
X{
X int curr = *rp, curc = *cp;
X int f, newf, *fp;
X int d, newd;
X
X wrapped:
X newf = 0;
X newd = 1000;
X
X switch (dirchar) {
X case 'h': /* left */
X /* go to next field to the left, or wrap. */
X for (fp = fields+NFIELDS; --fp >= fields; ) {
X f = *fp;
X if (tstpackf(f,flag) && unpackr(f) == curr) {
X d = curc - unpackc(f);
X if (d > 0 && d < newd) {
X newf = f;
X newd = d;
X }
X }
X }
X if (!newf) {
X curc = NC;
X goto wrapped;
X }
X break;
X
X case 'j': /* down */
X /* go to closest field on next row down with anything on it,
X * or wrap.
X */
X for (fp = fields+NFIELDS; --fp >= fields; ) {
X f = *fp;
X if (tstpackf(f,flag)) {
X d = unpackr(f) - curr;
X if (d > 0 && d < newd) {
X newf = f;
X newd = d;
X }
X }
X }
X if (newf) {
X /* now find the field closest to current col on that row */
X newf = nearestfld (unpackr(newf), curc, flag);
X } else {
X curr = 0;
X goto wrapped;
X }
X break;
X
X case 'k': /* up */
X /* go to closest field on next row up with anything on it,
X * or wrap.
X */
X for (fp = fields+NFIELDS; --fp >= fields; ) {
X f = *fp;
X if (tstpackf(f,flag)) {
X d = curr - unpackr(f);
X if (d > 0 && d < newd) {
X newf = f;
X newd = d;
X }
X }
X }
X if (newf) {
X /* now find the field closest to current col on that row */
X newf = nearestfld (unpackr(newf), curc, flag);
X } else {
X curr = NR+1;
X goto wrapped;
X }
X break;
X
X case 'l': /* right */
X /* go to next field to the right, or wrap. */
X for (fp = fields+NFIELDS; --fp >= fields; ) {
X f = *fp;
X if (tstpackf(f,flag) && unpackr(f) == curr) {
X d = unpackc(f) - curc;
X if (d > 0 && d < newd) {
X newf = f;
X newd = d;
X }
X }
X }
X if (!newf) {
X curc = 0;
X goto wrapped;
X }
X break;
X
X /* handy shorthands directly to a given spot.
X * calling nearestfld() automatically allows for which menu
X * is up now and what is pickable.
X * N.B. using nearestfld() can be too aggressive. it will try
X * other fields entirely if one you intend is not eligible.
X */
X case 'S': newf = nearestfld (R_SUN, 1, flag); break;
X case 'M': newf = nearestfld (R_MOON, 1, flag); break;
X case 'e': newf = nearestfld (R_MERCURY, 1, flag); break;
X case 'v': newf = nearestfld (R_VENUS, 1, flag); break;
X case 'm': newf = nearestfld (R_MARS, 1, flag); break;
X case cntrl('j'): newf = nearestfld (R_JUPITER, 1, flag); break;
X case 's': newf = nearestfld (R_SATURN, 1, flag); break;
X case 'u': newf = nearestfld (R_URANUS, 1, flag); break;
X case 'n': newf = nearestfld (R_NEPTUNE, 1, flag); break;
X case 'p': newf = nearestfld (R_PLUTO, 1, flag); break;
X case 'x': newf = nearestfld (R_OBJX, 1, flag); break;
X case 'd': newf = nearestfld (R_UD, C_UD, flag); break;
X case 'o': newf = nearestfld (R_EPOCH, C_EPOCHV, flag); break;
X case 'z': newf = nearestfld (R_STPSZ, C_STPSZV, flag); break;
X }
X
X if (newf > 0) {
X *rp = unpackr(newf);
X *cp = unpackc(newf);
X }
X}
X
X/* return the nearest field with given flag mask, either way, on this row,
X * else -1 if none.
X */
Xstatic int
Xnearestfld (r, c, flag)
Xint r, c, flag;
X{
X int nf, f, *fp;
X int d, d0;
X
X nf = 0;
X d0 = 1000;
X
X for (fp = fields+NFIELDS; --fp >= fields; ) {
X f = *fp;
X if (tstpackf(f,flag) && unpackr(f) == r) {
X d = abs(c - unpackc(f));
X if (d < d0) {
X nf = f;
X d0 = d;
X }
X }
X }
X return (nf ? nf : -1);
X}
EOFxEOF
len=`wc -c < sel_fld.c`
if expr $len != 21267 > /dev/null
then echo Length of sel_fld.c is $len but it should be 21267.
fi
echo x sex_dec.c
sed -e 's/^X//' << 'EOFxEOF' > sex_dec.c
X/* given hours (or degrees), hd, minutes, m, and seconds, s,
X * return decimal hours (or degrees), *d.
X * in the case of hours (angles) < 0, only the first non-zero element should
X * be negative.
X */
Xsex_dec (hd, m, s, d)
Xint hd, m, s;
Xdouble *d;
X{
X int sign = 1;
X
X if (hd < 0) {
X sign = -1;
X hd = -hd;
X } else if (m < 0) {
X sign = -1;
X m = -m;
X } else if (s < 0) {
X sign = -1;
X s = -s;
X }
X
X *d = (((double)s/60.0 + (double)m)/60.0 + (double)hd) * sign;
X}
X
X/* given decimal hours (or degrees), d.
X * return nearest hours (or degrees), *hd, minutes, *m, and seconds, *s,
X * each always non-negative; *isneg is set to 1 if d is < 0, else to 0.
X */
Xdec_sex (d, hd, m, s, isneg)
Xdouble d;
Xint *hd, *m, *s, *isneg;
X{
X double min;
X
X if (d < 0) {
X *isneg = 1;
X d = -d;
X } else
X *isneg = 0;
X
X *hd = (int)d;
X min = (d - *hd)*60.;
X *m = (int)min;
X *s = (int)((min - *m)*60. + 0.5);
X
X if (*s == 60) {
X if ((*m += 1) == 60) {
X *hd += 1;
X *m = 0;
X }
X *s = 0;
X }
X /* no negative 0's */
X if (*hd == 0 && *m == 0 && *s == 0)
X *isneg = 0;
X}
X
X/* insure 0 <= *v < r.
X */
Xrange (v, r)
Xdouble *v, r;
X{
X while (*v < 0) *v += r;
X while (*v >= r) *v -= r;
X}
EOFxEOF
len=`wc -c < sex_dec.c`
if expr $len != 1194 > /dev/null
then echo Length of sex_dec.c is $len but it should be 1194.
fi