home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume7 / ephem / part02 < prev    next >
Text File  |  1989-06-03  |  61KB  |  2,378 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. Subject: v07i010: astronomical ephemeris - 2 of 3
  4. Keywords: ephemeris astro
  5. Organization: Dimensional Medicine, Inc.  Minnetonka, MN.
  6. Reply-To: ecd@ncs-med.UUCP (Elwood C. Downey)
  7.  
  8. Posting-number: Volume 7, Issue 10
  9. Submitted-by: ecd@ncs-med.UUCP (Elwood C. Downey)
  10. Archive-name: ephem/part02
  11.  
  12. #!/bin/sh
  13. echo extracting main.c
  14. cat > main.c << 'xXx'
  15. /* main program. 
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <math.h>
  20. #include "astro.h"
  21. #include "circum.h"
  22. #include "screen.h"
  23.  
  24. extern char *strchr(), *malloc();
  25.  
  26. static char *cfgfile = "ephem.cfg";    /* default config filename */
  27.  
  28. /* value for standard and my adaptive rise/set refraction model.
  29.  */
  30. #define    STDREF    degrad(50.0/60.0)    /* 34(ref)+16(semi-diam) arc mins */
  31.  
  32. static float dis = STDREF; /* sun displacement for rise/set refraction */
  33. static Now now;        /* where and when, right now */
  34. static float epoch;    /* ra/dec display precession epoch, or EOD */
  35. static float tminc;    /* hrs to inc time by each loop; RTC means use clock */
  36. static int newtm;    /* when op sets his own time don't auto inc first step*/
  37. static int nstep;    /* steps to go before stopping */
  38. static int ops, opm;    /* print options flags; 1 if want it */
  39. static int optwi, opsrs, opmrs;
  40. static int oppl[PLUTO+1];
  41.  
  42. /* info about the misc obj to be displayed at the bottom line */
  43. static int opobj;    /* 1 while wanting to use object */
  44. static float obj_ra, obj_dec, obj_epoch;    /* location of object */
  45. static char obj_name[C_RA-C_OBJ];
  46.  
  47. /* shorthands into now */
  48. #define mjd    now.n_mjd
  49. #define lat    now.n_lat
  50. #define lng    now.n_lng
  51. #define tz    now.n_tz
  52. #define temp    now.n_temp
  53. #define pressure    now.n_pressure
  54. #define height    now.n_height
  55. #define tznm    now.n_tznm
  56.  
  57. main (ac, av)
  58. int ac;
  59. char *av[];
  60. {
  61.     static char ssrun[] = "Updating...";
  62.     static char freerun[] =
  63.         "Running... press any key to stop to make changes.";
  64.     static char prmpt[] =
  65. "Move to another field, RETURN to change this field, ? for help, or ESC to run";
  66.     static char hlp[] =
  67.     "arrow keys move to field; any key stops running; ^d exits; ^l redraws";
  68.     int curr = R_NSTEP, curc = C_NSTEPV;    /* must start somewhere */
  69.     int sflag = 0;
  70.     int i;
  71.     int one = 1;    /* use a variable so masscomp optimizer not disabled */
  72.  
  73.     while ((--ac > 0) && (**++av == '-')) {
  74.         char *s;
  75.         for (s = *av+1; *s != '\0'; s++)
  76.         switch (*s) {
  77.         case 's': /* no credits "silent" (don't publish this) */
  78.             sflag++;
  79.             break;
  80.         case 'c': /* set name of config file to use */
  81.             if (--ac <= 0) usage();
  82.             cfgfile = *++av;
  83.             break;
  84.         default:
  85.             usage();
  86.         }
  87.     }
  88.     if (ac > 0)
  89.         usage();
  90.  
  91.     /* unbuffered stdout; avoid fflush(stdout) hassle. */
  92.     setbuf (stdout, (char *)0);
  93.  
  94.     /* make sure we can read the config file. try adding .cfg too. */
  95.     if (access (cfgfile, 4) < 0) {
  96.         if (strchr (cfgfile, '.') == 0) {
  97.         /* no . so try it with .cfg suffix */
  98.         char *cf = malloc (strlen(cfgfile)+4+1); /* .cfg + 0 */
  99.         sprintf (cf, "%s.cfg", cfgfile);
  100.         cfgfile = cf;
  101.         }
  102.         if (access (cfgfile, 4) < 0) {
  103.         printf ("Can not read config file: %s\n", cfgfile);
  104.         exit (1);
  105.         }
  106.     }
  107.  
  108.     /* init the screen and all the globals */
  109.     if (!sflag)
  110.         credits();
  111.     pr_erase();
  112.     pr_labels();
  113.     borders();
  114.     read_cfgfile (cfgfile);
  115.     newtm = 0;
  116.  
  117.     /* update screen forever (until QUIT) */
  118.     while (one) {
  119.         if (nstep <= 1)
  120.         pr_prompt (ssrun);
  121.         /* print all the time-related fields */
  122.         pr_now (&now);
  123.  
  124.         /* print solar system body info */
  125.         if (opsrs) pr_sunrs (&now, dis);
  126.         if (opmrs) pr_moonrs (&now);
  127.         if (optwi) pr_twilight (&now);
  128.         if (ops) pr_sun (&now, epoch);
  129.         if (opm) pr_moon (&now, epoch);
  130.         for (i = MERCURY; i <= PLUTO; i++)
  131.         if (oppl[i]) pr_planet (i, &now, epoch);
  132.  
  133.         /* print the misc obj */
  134.         if (opobj) pr_obj (obj_ra, obj_dec, obj_epoch, &now, epoch);
  135.  
  136.         /* now everything is up-to-date; decrement nstep */
  137.         pr_newcir(0);
  138.         plot();
  139.         if (nstep > 0) nstep -= 1;
  140.         prnstep ();
  141.  
  142.         /* change parameters after steps are done or when op hits a key.
  143.          */
  144.         if (nstep == 0 || (chk_char()==0 && read_char()!=0)) {
  145.         if (nstep == 0) {
  146.             nstep = 1;
  147.             prnstep ();
  148.         }
  149.         while (1) {
  150.             int fld = sel_fld (curr, curc, F_VIS|F_CHG, prmpt, hlp);
  151.             if (fld == 0)
  152.             break;
  153.             chg_fld ((char *)0, fld);
  154.             pr_now (&now);
  155.             curr = unpackr (fld);
  156.             curc = unpackc (fld);
  157.         }
  158.         if (nstep > 1)
  159.             pr_prompt (freerun);
  160.         }
  161.  
  162.         /* increment time if op didn't enter his own */
  163.         if (newtm)
  164.         newtm = 0;
  165.         else
  166.         inc_mjd (&now, tminc);
  167.     }
  168.  
  169.     return (0);
  170. }
  171.  
  172. /* clean up and exit
  173.  * TODO: ask "are you sure?" ?
  174.  */
  175. bye()
  176. {
  177.     pr_erase();
  178.     byetty();
  179.     exit (0);
  180. }
  181.  
  182. static
  183. usage()
  184. {
  185.     /* don't advertise -s (silent) option */
  186.     printf ("usage: [-c <configfile>]\n");
  187.     exit (1);
  188. }
  189.  
  190. /* read cfg file, fn, if present */
  191. static
  192. read_cfgfile(fn)
  193. char *fn;
  194. {
  195.     char buf[256];
  196.     FILE *fp;
  197.  
  198.     fp = fopen (fn, "r");
  199.     if (!fp)
  200.         return;
  201.  
  202.     while (fgets (buf, sizeof(buf), fp)) {
  203.         buf[strlen(buf)-1] = '\0';    /* no trailing \n */
  204.         if (strncmp ("SITE", buf, 4) == 0)
  205.         pr_string (R_TITLE, C_TITLE-strlen(buf+5)/2, buf+5);
  206.         else if (strncmp ("LAT", buf, 3) == 0)
  207.         chg_fld (buf+4, rcfpack (R_LAT,C_LATV,0));
  208.         else if (strncmp ("LONG", buf, 4) == 0)
  209.         chg_fld (buf+5, rcfpack (R_LONG,C_LONGV,0));
  210.         else if (strncmp ("UT", buf, 2) == 0)
  211.         chg_fld (buf+3, rcfpack (R_UT,C_UTV,0));
  212.         else if (strncmp ("UD", buf, 2) == 0)
  213.         chg_fld (buf+3, rcfpack (R_UD,C_UD,0));
  214.         else if (strncmp ("TZONE", buf, 5) == 0)
  215.         chg_fld (buf+6, rcfpack (R_TZONE,C_TZONEV,0));
  216.         else if (strncmp ("TZNAME", buf, 6) == 0)
  217.         chg_fld (buf+7, rcfpack (R_TZN,C_TZN,0));
  218.         else if (strncmp ("HEIGHT", buf, 6) == 0)
  219.         chg_fld (buf+7, rcfpack (R_HEIGHT,C_HEIGHTV,0));
  220.         else if (strncmp ("NSTEP", buf, 5) == 0)
  221.         chg_fld (buf+6, rcfpack (R_NSTEP,C_NSTEPV,0));
  222.         else if (strncmp ("STPSZ", buf, 5) == 0)
  223.         chg_fld (buf+6, rcfpack (R_STPSZ,C_STPSZV,0));
  224.         else if (strncmp ("TEMP", buf, 4) == 0)
  225.         chg_fld (buf+5, rcfpack (R_TEMP,C_TEMPV,0));
  226.         else if (strncmp ("PRES", buf, 4) == 0)
  227.         chg_fld (buf+5, rcfpack (R_PRES,C_PRESV,0));
  228.         else if (strncmp ("EPOCH", buf, 5) == 0)
  229.         chg_fld (buf+6, rcfpack (R_EPOCH,C_EPOCH,0));
  230.         else if (strncmp ("OBJN", buf, 4) == 0)
  231.         chg_fld (buf+5, rcfpack (R_OBJ,C_OBJ,0)); /*must be first*/
  232.         else if (strncmp ("OBJRA", buf, 5) == 0)
  233.         chg_fld (buf+6, rcfpack (R_OBJ,C_RA,0));
  234.         else if (strncmp ("OBJDEC", buf, 6) == 0)
  235.         chg_fld (buf+7, rcfpack (R_OBJ,C_DEC,0));
  236.         else if (strncmp ("PROPTS", buf, 6) == 0) {
  237.         char *bp = buf+7;
  238.         while (*bp)
  239.             switch (*bp++) {
  240.             case 'T': optwi = 1; break;
  241.             case 'S': ops = opsrs = 1; break;
  242.             case 'M': opm = opmrs = 1; break;
  243.             case 'e': oppl[MERCURY] = 1; break;
  244.             case 'v': oppl[VENUS] = 1; break;
  245.             case 'a': oppl[MARS] = 1; break;
  246.             case 'j': oppl[JUPITER] = 1; break;
  247.             case 's': oppl[SATURN] = 1; break;
  248.             case 'u': oppl[URANUS] = 1; break;
  249.             case 'n': oppl[NEPTUNE] = 1; break;
  250.             case 'p': oppl[PLUTO] = 1; break;
  251.             }
  252.         }
  253.     }
  254.     fclose (fp);
  255. }
  256.  
  257. /* change the field at rcpk according to the optional string input at bp.
  258.  * if bp is != 0 use it, else issue read_line() and use buffer.
  259.  * then sscanf the buffer and update the corresponding (global) variable(s)
  260.  * or do whatever a pick at that field should do.
  261.  */
  262. static
  263. chg_fld (bp, rcpk)
  264. char *bp;
  265. int rcpk;
  266. {
  267.     char buf[NC];
  268.     int deghrs = 0, mins = 0, secs = 0;
  269.  
  270.     /* switch on just the row/col portion */
  271.     switch (rcpk & ((1<<F_SHFT)-1)) {
  272.     case rcfpack (R_UD, C_UD, 0):
  273.         if (!bp) {
  274.         static char p[] = "utc date (m/d/y, or NOW): ";
  275.         pr_prompt (p);
  276.         if (read_line (buf, PW-sizeof(p)) <= 0)
  277.             return;
  278.         bp = buf;
  279.         }
  280.         if (bp[0] == 'n' || bp[0] == 'N')
  281.         time_fromsys (&now);
  282.         else {
  283.         float fday, newmjd0;
  284.         int month, day, year;
  285.         mjd_cal ((float)mjd, &month, &fday, &year); /* init with now */
  286.         day = (int)fday;    /* ignore partial days */
  287.         sscansex (bp, &month, &day, &year);
  288.         cal_mjd (month, (float)day, year, &newmjd0);
  289.         mjd = newmjd0 + mjd_hr(mjd)/24.0;
  290.         }
  291.         newtm = 1;
  292.         set_t0 (&now);
  293.         pr_newcir(1);
  294.         break;
  295.     case rcfpack (R_UT, C_UTV, 0):
  296.         if (!bp) {
  297.         static char p[] = "utc time (h:m:s, or NOW): ";
  298.         pr_prompt (p);
  299.         if (read_line (buf, PW-sizeof(p)) <= 0)
  300.             return;
  301.         bp = buf;
  302.         }
  303.         if (bp[0] == 'n' || bp[0] == 'N')
  304.         time_fromsys (&now);
  305.         else {
  306.         float newutc = (mjd-mjd_day(mjd)) * 24.0;
  307.         dec_sexsign (newutc, °hrs, &mins, &secs);
  308.         sscansex (bp, °hrs, &mins, &secs);
  309.         sex_dec (deghrs, mins, secs, &newutc);
  310.         mjd = mjd_day(mjd) + newutc/24.0;
  311.         }
  312.         newtm = 1;
  313.         set_t0 (&now);
  314.         pr_newcir(1);
  315.         break;
  316.     case rcfpack (R_LD, C_LD, 0):
  317.         if (!bp) {
  318.         static char p[] = "local date (m/d/y, or NOW): ";
  319.         pr_prompt (p);
  320.         if (read_line (buf, PW-sizeof(p)) <= 0)
  321.             return;
  322.         bp = buf;
  323.         }
  324.         if (bp[0] == 'n' || bp[0] == 'N')
  325.         time_fromsys (&now);
  326.         else {
  327.         float fday, newlmjd0;
  328.         int month, day, year;
  329.         mjd_cal ((float)(mjd-tz/24.0), &month, &fday, &year); /* now */
  330.         day = (int)fday;    /* ignore partial days */
  331.         sscansex (bp, &month, &day, &year);
  332.         cal_mjd (month, (float)day, year, &newlmjd0);
  333.         mjd = newlmjd0 + mjd_hr(mjd)/24.0;
  334.         mjd += newlmjd0 - mjd_day(mjd-tz/24.0);
  335.         }
  336.         newtm = 1;
  337.         set_t0 (&now);
  338.         pr_newcir(1);
  339.         break;
  340.     case rcfpack (R_LT, C_LT, 0):
  341.         if (!bp) {
  342.         static char p[] = "local time (h:m:s, or NOW): ";
  343.         pr_prompt (p);
  344.         if (read_line (buf, PW-sizeof(p)) <= 0)
  345.             return;
  346.         bp = buf;
  347.         }
  348.         if (bp[0] == 'n' || bp[0] == 'N')
  349.         time_fromsys (&now);
  350.         else {
  351.         float newlt = (mjd-mjd_day(mjd)) * 24.0 - tz;
  352.         range (&newlt, 24.0);
  353.         dec_sexsign (newlt, °hrs, &mins, &secs);
  354.         sscansex (bp, °hrs, &mins, &secs);
  355.         sex_dec (deghrs, mins, secs, &newlt);
  356.         mjd = mjd_day(mjd-tz/24.0) + (newlt + tz)/24.0;
  357.         }
  358.         newtm = 1;
  359.         set_t0 (&now);
  360.         pr_newcir(1);
  361.         break;
  362.     case rcfpack (R_TZN, C_TZN, 0):
  363.         if (!bp) {
  364.         static char p[] = "timezone abbreviation (3 char max): ";
  365.         pr_prompt (p);
  366.         if (read_line (buf, 3) <= 0)
  367.             return;
  368.         bp = buf;
  369.         }
  370.         strcpy (tznm, bp);
  371.         break;
  372.     case rcfpack (R_TZONE, C_TZONEV, 0):
  373.         if (!bp) {
  374.         static char p[] = "hours behind utc: ";
  375.         pr_prompt (p);
  376.         if (read_line (buf, PW-sizeof(p)) <= 0)
  377.             return;
  378.         bp = buf;
  379.         }
  380.         dec_sexsign (tz, °hrs, &mins, &secs);
  381.         sscansex (bp, °hrs, &mins, &secs);
  382.         sex_dec (deghrs, mins, secs, &tz);
  383.         pr_newcir(1);
  384.         break;
  385.     case rcfpack (R_LONG, C_LONGV, 0):
  386.         if (!bp) {
  387.         static char p[] = "longitude (+ west) (d:m:s): ";
  388.         pr_prompt (p);
  389.         if (read_line (buf, PW-sizeof(p)) <= 0)
  390.             return;
  391.         bp = buf;
  392.         }
  393.         dec_sexsign (-raddeg(lng), °hrs, &mins, &secs);
  394.         sscansex (bp, °hrs, &mins, &secs);
  395.         sex_dec (deghrs, mins, secs, &lng);
  396.         lng = degrad (-lng);         /* want - radians west */
  397.         pr_newcir(1);
  398.         break;
  399.     case rcfpack (R_LAT, C_LATV, 0):
  400.         if (!bp) {
  401.         static char p[] = "latitude (+ north) (d:m:s): ";
  402.         pr_prompt (p);
  403.         if (read_line (buf, PW-sizeof(p)) <= 0)
  404.             return;
  405.         bp = buf;
  406.         }
  407.         dec_sexsign (raddeg(lat), °hrs, &mins, &secs);
  408.         sscansex (bp, °hrs, &mins, &secs);
  409.         sex_dec (deghrs, mins, secs, &lat);
  410.         lat = degrad (lat);
  411.         pr_newcir(1);
  412.         break;
  413.     case rcfpack (R_HEIGHT, C_HEIGHTV, 0):
  414.         if (!bp) {
  415.         static char p[] = "height above sea level (ft): ";
  416.         pr_prompt (p);
  417.         if (read_line (buf, PW-sizeof(p)) <= 0)
  418.             return;
  419.         bp = buf;
  420.         }
  421.         sscanf (bp, "%f", &height);
  422.         sprintf (buf, "%5g ft", height);
  423.         pr_string (R_HEIGHT, C_HEIGHTV, buf);
  424.         height /= 2.093e7; /* convert ft to earth radii above sea level */
  425.         pr_newcir(1);
  426.         break;
  427.     case rcfpack (R_NSTEP, C_NSTEPV, 0):
  428.         if (!bp) {
  429.         static char p[] = "number of steps to run: ";
  430.         pr_prompt (p);
  431.         if (read_line (buf, 8) <= 0)
  432.             return;
  433.         bp = buf;
  434.         }
  435.         sscanf (bp, "%d", &nstep);
  436.         prnstep ();
  437.         break;
  438.     case rcfpack (R_TEMP, C_TEMPV, 0):
  439.         if (!bp) {
  440.         static char p[] = "temperatue (deg.F): ";
  441.         pr_prompt (p);
  442.         if (read_line (buf, PW-sizeof(p)) <= 0)
  443.             return;
  444.         bp = buf;
  445.         }
  446.         sscanf (bp, "%f", &temp);
  447.         sprintf (buf, "%6g F", temp);
  448.         pr_string (R_TEMP, C_TEMPV, buf);
  449.         temp = 5./9.*(temp - 32.0);    /* want degs C */
  450.         pr_newcir(1);
  451.         break;
  452.     case rcfpack (R_PRES, C_PRESV, 0):
  453.         if (!bp) {
  454.         static char p[] =
  455.             "atmos pressure (in. Hg; 0 for no refraction correction): ";
  456.         pr_prompt (p);
  457.         if (read_line (buf, PW-sizeof(p)) <= 0)
  458.             return;
  459.         bp = buf;
  460.         }
  461.         sscanf (bp, "%f", &pressure);
  462.         sprintf (buf, "%5.2f in", pressure);
  463.         pr_string (R_PRES, C_PRESV, buf);
  464.         pressure *= 33.86;        /* want mBar */
  465.         pr_newcir(1);
  466.         break;
  467.     case rcfpack (R_EPOCH, C_EPOCH, 0):
  468.         if (!bp) {
  469.         static char p[] = "epoch (year, or EOD for no precession): ";
  470.         pr_prompt (p);
  471.         if (read_line (buf, PW-strlen(p)) <= 0)
  472.             return;
  473.         bp = buf;
  474.         }
  475.         if (bp[0] == 'e' || bp[0] == 'E') {
  476.         epoch = EOD;
  477.         sprintf (buf, "(Epoch of date)");
  478.         } else {
  479.         float e;
  480.         sscanf (bp, "%f", &e);
  481.         sprintf (buf, "(Epoch %6.1f) ", e);
  482.         cal_mjd (1, 1.0, (int)e, &epoch);    /* convert to mjd */
  483.         epoch += (e - (int)e)*365.24;
  484.         }
  485.         pr_string (R_EPOCH, C_EPOCH, buf);
  486.         pr_newcir(1);
  487.         break;
  488.     case rcfpack (R_STPSZ, C_STPSZV, 0):
  489.         if (!bp) {
  490.         static char p[] =
  491.             "step size increment (h:m:s, or <x>D, or RTC): ";
  492.         pr_prompt (p);
  493.         if (read_line (buf, PW-sizeof(p)) <= 0)
  494.             return;
  495.         bp = buf;
  496.         }
  497.         if (bp[0] == 'r' || bp[0] == 'R') {
  498.         pr_string (R_STPSZ, C_STPSZV, "RT CLOCK");
  499.         tminc = RTC;
  500.         } else {
  501.         int last = strlen (bp) - 1;
  502.         if (bp[last] == 'd' || bp[last] == 'D') {
  503.             /* ends in d so treat as decimal number of days */
  504.             float x;
  505.             sscanf (bp, "%g", &x);
  506.             tminc = x * 24.0;
  507.             pr_float (R_STPSZ, C_STPSZV, "%5g dy", x);
  508.         } else {
  509.             if (tminc == RTC)
  510.             deghrs = mins = secs = 0;
  511.             else
  512.             dec_sexsign (tminc, °hrs, &mins, &secs);
  513.             sscansex (bp, °hrs, &mins, &secs);
  514.             sex_dec (deghrs, mins, secs, &tminc);
  515.             pr_time (R_STPSZ, C_STPSZV, tminc);
  516.         }
  517.         }
  518.         set_t0 (&now);
  519.         break;
  520.     case rcfpack (R_PLOT, C_PLOT, 0):
  521.         plt_pk_label();
  522.         break;
  523.     case rcfpack (R_PLOT, C_PLOTV, 0):
  524.         plt_pk_onoff();
  525.         break;
  526.     case rcfpack (R_DAWN, C_DAWN, 0):
  527.     case rcfpack (R_DUSK, C_DUSK, 0):
  528.     case rcfpack (R_LON, C_LON, 0):
  529.         if (optwi ^= 1)
  530.         pr_twilight (&now);
  531.         else {
  532.         pr_blanks (R_DAWN, C_DAWNV, 5);
  533.         pr_blanks (R_DUSK, C_DUSKV, 5);
  534.         pr_blanks (R_LON, C_LONV, 5);
  535.         }
  536.         break;
  537.     case rcfpack (R_SUNR, C_SUNR, 0):
  538.     case rcfpack (R_SUNS, C_SUNS, 0):
  539.     case rcfpack (R_LOD, C_LOD, 0):
  540.         if (opsrs ^= 1) {
  541.         if (!bp) {
  542.             static char p[] =
  543.             "standard or adaptive refraction model (s/a)? ";
  544.             do {
  545.             pr_prompt (p);
  546.             if (read_line (buf, PW-sizeof(p)) < 0)
  547.                 return;
  548.             } while (*buf != 's' && *buf != 'a');
  549.             bp = buf;
  550.         }
  551.         dis = (*bp == 'a') ? ADPREF : STDREF;
  552.         pr_sunrs (&now, dis);
  553.         } else {
  554.         pr_blanks (R_SUNR, C_SUNRT, 14);
  555.         pr_blanks (R_SUNS, C_SUNST, 14);
  556.         pr_blanks (R_LOD, C_LODV, 5);
  557.         }
  558.         break;
  559.     case rcfpack (R_MOONR, C_MOONR, 0):
  560.     case rcfpack (R_MOONS, C_MOONS, 0):
  561.         if (opmrs ^= 1) 
  562.         pr_moonrs (&now);
  563.         else {
  564.         pr_blanks (R_MOONR, C_MOONRT, 14);
  565.         pr_blanks (R_MOONS, C_MOONST, 14);
  566.         }
  567.         break;
  568.     case rcfpack (R_SUN, C_OBJ, 0):
  569.         if (ops ^= 1)
  570.         pr_sun (&now, epoch);
  571.         else
  572.         pr_noplanet (R_SUN);
  573.         break;
  574.     case rcfpack (R_MOON, C_OBJ, 0):
  575.         if (opm ^= 1)
  576.         pr_moon (&now, epoch);
  577.         else
  578.         pr_noplanet (R_MOON);
  579.         break;
  580.     case rcfpack (R_MERCURY, C_OBJ, 0):
  581.         if (oppl[MERCURY] ^= 1)
  582.         pr_planet (MERCURY, &now, epoch);
  583.         else
  584.         pr_noplanet (R_MERCURY);
  585.         break;
  586.     case rcfpack (R_VENUS, C_OBJ, 0):
  587.         if (oppl[VENUS] ^= 1)
  588.         pr_planet (VENUS, &now, epoch);
  589.         else
  590.         pr_noplanet (R_VENUS);
  591.         break;
  592.     case rcfpack (R_MARS, C_OBJ, 0):
  593.         if (oppl[MARS] ^= 1)
  594.         pr_planet (MARS, &now, epoch);
  595.         else
  596.         pr_noplanet (R_MARS);
  597.         break;
  598.     case rcfpack (R_JUPITER, C_OBJ, 0):
  599.         if (oppl[JUPITER] ^= 1)
  600.         pr_planet (JUPITER, &now, epoch);
  601.         else
  602.         pr_noplanet (R_JUPITER);
  603.         break;
  604.     case rcfpack (R_SATURN, C_OBJ, 0):
  605.         if (oppl[SATURN] ^= 1)
  606.         pr_planet (SATURN, &now, epoch);
  607.         else
  608.         pr_noplanet (R_SATURN);
  609.         break;
  610.     case rcfpack (R_URANUS, C_OBJ, 0):
  611.         if (oppl[URANUS] ^= 1)
  612.         pr_planet (URANUS, &now, epoch);
  613.         else
  614.         pr_noplanet (R_URANUS);
  615.         break;
  616.     case rcfpack (R_NEPTUNE, C_OBJ, 0):
  617.         if (oppl[NEPTUNE] ^= 1)
  618.         pr_planet (NEPTUNE, &now, epoch);
  619.         else
  620.         pr_noplanet (R_NEPTUNE);
  621.         break;
  622.     case rcfpack (R_PLUTO, C_OBJ, 0):
  623.         if (oppl[PLUTO] ^= 1)
  624.         pr_planet (PLUTO, &now, epoch);
  625.         else
  626.         pr_noplanet (R_PLUTO);
  627.         break;
  628.     case rcfpack (R_OBJ, C_OBJ, 0):
  629.         if (!bp) {
  630.         static char p[] = "object name (or RETURN for none): ";
  631.         pr_prompt (p);
  632.         if (read_line (buf, sizeof(obj_name)-1) < 0)
  633.             return;
  634.         bp = buf;
  635.         } else
  636.         bp[sizeof(obj_name)-1] = '\0';
  637.         if (bp[0] == '\0') {
  638.         opobj = 0;
  639.         pr_blanks (R_OBJ, C_OBJ, sizeof(obj_name)-1);
  640.         /* pr_noplanet (R_OBJ); NO: writes on low-right of screen */
  641.         pr_blanks (R_OBJ, C_RA, 80-1-C_RA+1);
  642.         } else {
  643.         opobj = 1;
  644.         pr_blanks (R_OBJ, C_OBJ, sizeof(obj_name)-1);
  645.         strncpy (obj_name, bp, sizeof(obj_name)-1);
  646.         pr_string (R_OBJ, C_OBJ, bp);
  647.         obj_epoch = 0.0;
  648.         obj_ra = 0.0;
  649.         obj_dec = 0.0;
  650.         }
  651.         break;
  652.     case rcfpack (R_OBJ, C_RA, 0):
  653.         if (!opobj)
  654.         break;
  655.         if (!bp) {
  656.         static char p[] = "ra (current epoch, h:m:s): ";
  657.         pr_prompt (p);
  658.         if (read_line (buf, PW-sizeof(p)) <= 0)
  659.             return;
  660.         bp = buf;
  661.         }
  662.         dec_sexsign (radhr(obj_ra), °hrs, &mins, &secs);
  663.         sscansex (bp, °hrs, &mins, &secs);
  664.         sex_dec (deghrs, mins, secs, &obj_ra);
  665.         pr_ra (R_OBJ, C_RA, obj_ra);
  666.         obj_ra = hrrad (obj_ra);
  667.         obj_epoch = epoch == EOD ? mjd : epoch;
  668.         pr_obj (obj_ra, obj_dec, obj_epoch, &now, epoch);
  669.         break;
  670.     case rcfpack (R_OBJ, C_DEC, 0):
  671.         if (!opobj)
  672.         break;
  673.         if (!bp) {
  674.         static char p[] = "dec (current epoch, d:m:s): ";
  675.         pr_prompt (p);
  676.         if (read_line (buf, PW-sizeof(p)) <= 0)
  677.             return;
  678.         bp = buf;
  679.         }
  680.         dec_sexsign (raddeg(obj_dec), °hrs, &mins, &secs);
  681.         sscansex (bp, °hrs, &mins, &secs);
  682.         sex_dec (deghrs, mins, secs, &obj_dec);
  683.         obj_dec = degrad (obj_dec);
  684.         obj_epoch = epoch == EOD ? mjd : epoch;
  685.         pr_obj (obj_ra, obj_dec, obj_epoch, &now, epoch);
  686.         break;
  687.     }
  688. }
  689.  
  690. static
  691. prnstep()
  692. {
  693.     char buf[16];
  694.     sprintf (buf, "%8d", nstep);
  695.     pr_string (R_NSTEP, C_NSTEPV, buf);
  696. }
  697.  
  698. /* crack a line of the form X:X:X or X/X/X into its components.
  699.  * only change those fields that are specified:
  700.  *   eg:  ::10    only changes *s
  701.  *        10    only changes *d
  702.  *        10:0  changes *d and *m
  703.  * if see '-' anywhere, first non-zero component will be made negative.
  704.  */
  705. static
  706. sscansex (bp, d, m, s)
  707. char *bp;
  708. int *d, *m, *s;
  709. {
  710.     char c;
  711.     register int *p = d;
  712.     int *nonzp = 0;
  713.     int sawneg = 0;
  714.     int innum = 0;
  715.  
  716.     while (c = *bp++)
  717.         switch (c) {
  718.         case '0': case '1': case '2': case '3': case '4':
  719.         case '5': case '6': case '7': case '8': case '9':
  720.         if (!innum) {
  721.             *p = 0;
  722.             innum = 1;
  723.         }
  724.         *p = *p*10 + (c - '0');
  725.         if (*p && !nonzp)
  726.             nonzp = p;
  727.         break;
  728.         case ':': case '/':
  729.         /* advance to next component */
  730.         p = (p == d) ? m : s;
  731.         innum = 0;
  732.         break;
  733.         case '-':
  734.         sawneg = 1;
  735.         break;
  736.         }
  737.  
  738.     if (sawneg && nonzp)
  739.         *nonzp = -*nonzp;
  740. }
  741.  
  742. /* just like dec_sex() but makes the first non-zero element negative if
  743.  * x is negative (instead of returning a sign flag).
  744.  */
  745. static
  746. dec_sexsign (x, h, m, s)
  747. float x;
  748. int *h, *m, *s;
  749. {
  750.     int n;
  751.     dec_sex (x, h, m, s, &n);
  752.     if (n) {
  753.         if (*h)
  754.         *h = -*h;
  755.         else if (*m)
  756.         *m = -*m;
  757.         else
  758.         *s = -*s;
  759.     }
  760. }
  761. xXx
  762. echo extracting plot.c
  763. cat > plot.c << 'xXx'
  764. /* code to support the plotting capabilities. */
  765.  
  766. #include <stdio.h>
  767. #include "screen.h"
  768.  
  769. extern errno;
  770. extern char *sys_errlist[];
  771.  
  772. #define    UNDEFFL    1e38    /* magic float value to mean undefined */
  773.  
  774. /* number of simultaneous lines we can track/plot */
  775. #define    MAXPLTLINES    4
  776. #define    FNLEN        (14+1)    /* longest filename; plus 1 for \0 */
  777.  
  778. static char plt_filename[FNLEN] = "ephem.plt";
  779. static FILE *plt_fp;    /* == 0 means don't plot too */
  780.  
  781. /* a PlotField is a field location and a value stored there.
  782.  * a PlotLine is a label and two or three PlotFields:
  783.  *    [0] is the x coord, [1] the y, and [2], if not UNDEFFL/blank, is z.
  784.  */
  785. typedef struct {
  786.     int pf_rcpack;
  787.     float pf_val;
  788. } PlotField;
  789. typedef struct {
  790.     char pl_label;
  791.     PlotField pl_x, pl_y, pl_z;
  792. } PlotLine;
  793. static PlotLine plotline[MAXPLTLINES];
  794. static int npltlines;    /* actual number of plotline[]s in use */
  795.  
  796. /* picked the Plot label:
  797.  * if on, select fields to plot.
  798.  * if off, select name of file to plot.
  799.  */
  800. plt_pk_label()
  801. {
  802.     if (plt_fp)
  803.         plt_select_fields();
  804.     else
  805.         plt_file();
  806. }
  807.  
  808. /* pick the plot on/off field:
  809.  * if on, turn off.
  810.  * if off, turn on, using current set of plot fields.
  811.  */
  812. plt_pk_onoff()
  813. {
  814.     if (plt_fp)
  815.         plt_turn_off();
  816.     else
  817.         plt_turn_on();
  818. }
  819.  
  820. /* save value for r/c, if plot file open and r/c is in plotfield[].
  821.  * don't quit if see one since a field could be used more than once; time
  822.  *   is a frequent example.
  823.  */
  824. plt_val (r, c, value)
  825. int r, c;
  826. float value;
  827. {
  828.     PlotLine *plp;
  829.     int rcp;
  830.  
  831.     if (plt_fp) {
  832.         plp = &plotline[npltlines];
  833.         rcp = rcfpack (r, c, 0);
  834.         while (--plp >= plotline) {
  835.         if (plp->pl_x.pf_rcpack == rcp)
  836.             plp->pl_x.pf_val = value;
  837.         if (plp->pl_y.pf_rcpack == rcp)
  838.             plp->pl_y.pf_val = value;
  839.         if (plp->pl_z.pf_rcpack == rcp)
  840.             plp->pl_z.pf_val = value;
  841.         }
  842.     }
  843. }
  844.  
  845. /* write the active plotfields to the current plot file, if one is open. */
  846. plot ()
  847. {
  848.     PlotLine *plp;
  849.  
  850.     if (plt_fp)
  851.         for (plp = &plotline[npltlines]; --plp >= plotline; ) {
  852.         fprintf (plt_fp, "%c,%g,%g", plp->pl_label,
  853.                         plp->pl_x.pf_val, plp->pl_y.pf_val);
  854.         if (plp->pl_z.pf_val != UNDEFFL)
  855.             fprintf (plt_fp, ",%g", plp->pl_z.pf_val);
  856.         fprintf (plt_fp, "\n");
  857.         }
  858. }
  859.  
  860. static
  861. plt_init()
  862. {
  863.     PlotLine *plp = &plotline[MAXPLTLINES];
  864.  
  865.     while (--plp >= plotline) {
  866.         plp->pl_x.pf_rcpack = plp->pl_y.pf_rcpack = 0;
  867.         plp->pl_x.pf_val = plp->pl_y.pf_val = 0.0;
  868.         plp->pl_z.pf_val = UNDEFFL;
  869.     }
  870.     npltlines = 0;
  871. }
  872.  
  873. static
  874. plt_select_fields()
  875. {
  876.     static char hlp[] = "use arrow keys to select variable, or ESC to quit";
  877.     static int pltr = R_UT, pltc = C_UTV; /* start somewhere... */
  878.     int i;
  879.  
  880.     plt_init();
  881.     for (i = 0; i < MAXPLTLINES; i++) {
  882.         char buf[64];
  883.         int fld;
  884.  
  885.         sprintf (buf, "select x field for line %d", i+1);
  886.         fld = sel_fld (pltr, pltc, F_VIS|F_PLT, buf, hlp);
  887.         pltr = unpackr (fld); pltc = unpackc (fld);
  888.         if (!fld)
  889.         break;
  890.         plotline[i].pl_x.pf_rcpack = fld;
  891.  
  892.         sprintf (buf, "select y field for line %d", i+1);
  893.         fld = sel_fld (pltr, pltc, F_VIS|F_PLT, buf, hlp);
  894.         pltr = unpackr (fld); pltc = unpackc (fld);
  895.         if (!fld)
  896.         break;
  897.         plotline[i].pl_y.pf_rcpack = fld;
  898.  
  899.         sprintf (buf, "select z field for line %d", i+1);
  900.         fld = sel_fld (pltr, pltc, F_VIS|F_PLT, buf, hlp);
  901.         pltr = unpackr (fld); pltc = unpackc (fld);
  902.         if (fld)
  903.         plotline[i].pl_z.pf_rcpack = fld;
  904.  
  905.         do {
  906.         sprintf (buf, "select one-character label for line %d: ", i+1);
  907.         pr_prompt (buf);
  908.         fld = read_line (buf, 1);
  909.         } while (fld != 1);
  910.         plotline[i].pl_label = *buf;
  911.     }
  912.     npltlines = i;
  913. }
  914.  
  915. static
  916. plt_turn_off ()
  917. {
  918.     fclose (plt_fp);
  919.     plt_fp = 0;
  920.     pr_string (R_PLOT, C_PLOTV, "off");
  921. }
  922.  
  923. static
  924. plt_turn_on ()
  925. {
  926.     char fn[FNLEN], fnq[64];
  927.     char *optype;
  928.     int n;
  929.  
  930.     /* prompt for file name, giving current as default */
  931.     sprintf (fnq, "file to write <%s>: ", plt_filename);
  932.     pr_prompt (fnq);
  933.     n = read_line (fn, sizeof(fn)-1);
  934.  
  935.     /* leave plotting off if type ESC.
  936.      * reuse same fn if just type \n
  937.      */
  938.     if (n < 0)
  939.         return;
  940.     if (n > 0)
  941.         strcpy (plt_filename, fn);
  942.  
  943.     /* give option to append if file already exists */
  944.     optype = "w";
  945.     if (access (plt_filename, 2) == 0) {
  946.         while (1) {
  947.         pr_prompt ("append or overwrite (a/o)?: ");
  948.         n = read_line (fn, 1);
  949.         if (n < 0)
  950.             return;
  951.         if (fn[0] == 'a') {
  952.             optype = "a";
  953.             break;
  954.         }
  955.         if (fn[0] == 'o')
  956.             break;
  957.         }
  958.     }
  959.  
  960.     /* plotting is on if file opens ok */
  961.     plt_fp = fopen (plt_filename, optype);
  962.     if (plt_fp)
  963.         pr_string (R_PLOT, C_PLOTV, "on ");
  964.     else {
  965.         char buf[NC];
  966.         sprintf(buf,"can not open %s: %s",plt_filename,sys_errlist[errno]);
  967.         pr_prompt (buf);
  968.         (void)read_char();
  969.     }
  970. }
  971.  
  972. static
  973. plt_file ()
  974. {
  975.     char fn[FNLEN], fnq[64];
  976.     FILE *pfp;
  977.     int n;
  978.  
  979.     /* prompt for file name, giving current as default */
  980.     sprintf (fnq, "file to read <%s>: ", plt_filename);
  981.     pr_prompt (fnq);
  982.     n = read_line (fn, sizeof(fn)-1);
  983.  
  984.     /* forget it if type ESC.
  985.      * reuse same fn if just type \n
  986.      */
  987.     if (n < 0)
  988.         return;
  989.     if (n > 0)
  990.         strcpy (plt_filename, fn);
  991.  
  992.     /* do the plot if file opens ok */
  993.     pfp = fopen (plt_filename, "r");
  994.     if (pfp) {
  995.         plot_it (pfp);
  996.         fclose (pfp);
  997.     } else {
  998.         char buf[NC];
  999.         sprintf(buf,"can not open %s: %s",plt_filename,sys_errlist[errno]);
  1000.         pr_prompt (buf);
  1001.         (void)read_char();
  1002.     }
  1003. }
  1004.  
  1005. /* TODO: add z somehow
  1006.  * N.B. DON'T use pr_X() since they will be remembered over screen.
  1007.  */
  1008. static
  1009. plot_it (pfp)
  1010. FILE *pfp;
  1011. {
  1012.     static char fmt[] = "%c,%g,%g";
  1013.     float x, y;    /* N.B. most sscanf("%g")'s need ptrs to double */
  1014.     float minx, maxx, miny, maxy;
  1015.     char buf[128];
  1016.     int first = 1;
  1017.     char c;
  1018.  
  1019.     /* find ranges and number of points */
  1020.     while (fgets (buf, sizeof(buf), pfp)) {
  1021.         sscanf (buf, fmt, &c, &x, &y);
  1022.         if (first) {
  1023.         maxx = minx = x;
  1024.         maxy = miny = y;
  1025.         first = 0;
  1026.         } else {
  1027.         if (x > maxx) maxx = x;
  1028.         else if (x < minx) minx = x;
  1029.         if (y > maxy) maxy = y;
  1030.         else if (y < miny) miny = y;
  1031.         }
  1032.     }
  1033.  
  1034. #define    SMALL    (1e-10)
  1035.     if (first == 1 || fabs(minx-maxx) < SMALL || fabs(miny-maxy) < SMALL) {
  1036.         c_erase();
  1037.         c_pos (1,1); printf ("Nothing in file or range too small...");
  1038.     } else {
  1039.         /* read file again, this time plotting */
  1040.         rewind (pfp);
  1041.         c_erase();
  1042.         while (fgets (buf, sizeof(buf), pfp)) {
  1043.         int row, col;
  1044.         sscanf (buf, fmt, &c, &x, &y);
  1045.         row = NR-(int)((NR-1)*(y-miny)/(maxy-miny)+0.5);
  1046.         col =  1+(int)((NC-1)*(x-minx)/(maxx-minx)+0.5);
  1047.         if (row == NR && col == NC)
  1048.             col--;    /* avoid lower right scrolling corner */
  1049.         c_pos (row, col);
  1050.         putchar (c);
  1051.         }
  1052.  
  1053.         /* label axes */
  1054.         c_pos (1,1); printf ("%.2g", maxy);
  1055.         c_pos (NR-1,1); printf ("%.2g", miny);
  1056.         c_pos (NR,1); printf ("%.2g", minx);
  1057.         c_pos (NR,NC-10); printf ("%.2g", maxx);
  1058.     }
  1059.  
  1060.     /* hit any key to resume... */
  1061.     (void) read_char();
  1062.     pr_redraw();
  1063. }
  1064. xXx
  1065. echo extracting pr.c
  1066. cat > pr.c << 'xXx'
  1067. #include <stdio.h>
  1068. #include <math.h>
  1069. #include "astro.h"
  1070. #include "circum.h"
  1071. #include "screen.h"
  1072.  
  1073. /* shorthands into np */
  1074. #define mjd    np->n_mjd
  1075. #define lat    np->n_lat
  1076. #define lng    np->n_lng
  1077. #define tz    np->n_tz
  1078. #define temp    np->n_temp
  1079. #define pressure    np->n_pressure
  1080. #define height    np->n_height
  1081. #define tznm    np->n_tznm
  1082.  
  1083. /* display once-only labels. */
  1084. pr_labels()
  1085. {
  1086.     pr_string (R_PLOT,    C_PLOT,        "Plot");
  1087.     pr_string (R_PLOT,    C_PLOTV,    "off");
  1088.     pr_string (R_JD,    C_JD,        "JD");
  1089.     pr_string (R_LST,    C_LST,        "LST");
  1090.     pr_string (R_TZN,    C_TZN,        "LT");
  1091.     pr_string (R_UT,    C_UT,        "UTC");
  1092.     pr_string (R_TZONE,    C_TZONE,    "TZ");
  1093.     pr_string (R_LAT,    C_LAT,        "Lat");
  1094.     pr_string (R_LONG,    C_LONG,        "Long");
  1095.     pr_string (R_TEMP,    C_TEMP,        "Temp");
  1096.     pr_string (R_PRES,    C_PRES,        "AtmPr");
  1097.     pr_string (R_LOD,    C_LOD,        "DayLn");
  1098.     pr_string (R_LON,    C_LON,        "NiteLn");
  1099.     pr_string (R_NSTEP,    C_NSTEP,    "NStep");
  1100.     pr_string (R_STPSZ,    C_STPSZ,    "StpSz");
  1101.     pr_string (R_HEIGHT,    C_HEIGHT,    "Elev");
  1102.     pr_string (R_DUSK,    C_DUSK,        "Dusk");
  1103.     pr_string (R_SUNR,    C_SUNR,        "SRis");
  1104.     pr_string (R_MOONR,    C_MOONR,    "MRis");
  1105.     pr_string (R_DAWN,    C_DAWN,        "Dawn");
  1106.     pr_string (R_SUNS,    C_SUNS,        "SSet");
  1107.     pr_string (R_MOONS,    C_MOONS,    "MSet");
  1108.  
  1109.     /* planet column headings */
  1110.     pr_string (R_PLANTAB,    C_OBJ,    "Ob");
  1111.     pr_string (R_PLANTAB,    C_RA,    "R.A.");
  1112.     pr_string (R_PLANTAB,    C_DEC,    "Dec");
  1113.     pr_string (R_PLANTAB,    C_HLONG,"Helio");
  1114.     pr_string (R_PLANTAB+1,    C_HLONG,"Long");
  1115.     pr_string (R_PLANTAB,    C_HLAT,    "Helio");
  1116.     pr_string (R_PLANTAB+1,    C_HLAT,    "Lat");
  1117.     pr_string (R_PLANTAB,    C_AZ,    "Az");
  1118.     pr_string (R_PLANTAB+1,    C_AZ,    "Deg E");
  1119.     pr_string (R_PLANTAB,    C_ALT,    "Alt");
  1120.     pr_string (R_PLANTAB+1,    C_ALT,    "Deg Up");
  1121.     pr_string (R_PLANTAB,    C_EDIST,"Ea Dst");
  1122.     pr_string (R_PLANTAB+1,    C_EDIST,"AU(mi)");
  1123.     pr_string (R_PLANTAB,    C_SDIST,"Sn Dst");
  1124.     pr_string (R_PLANTAB+1,    C_SDIST,"AU");
  1125.     pr_string (R_PLANTAB,    C_ELONG,"Elong");
  1126.     pr_string (R_PLANTAB+1,    C_ELONG,"Deg E");
  1127.     pr_string (R_PLANTAB,    C_SIZE,    "Size");
  1128.     pr_string (R_PLANTAB+1,    C_SIZE,    "ArcS");
  1129.     pr_string (R_PLANTAB,    C_MAG,    "VMag");
  1130.     pr_string (R_PLANTAB,    C_PHASE,"Phs");
  1131.     pr_char (R_PLANTAB+1,    C_PHASE,'%');
  1132.  
  1133.     /* object names */
  1134.     pr_string (R_SUN,    C_OBJ,    "Su");
  1135.     pr_string (R_MOON,    C_OBJ,    "Mo");
  1136.     pr_string (R_MERCURY,    C_OBJ,    "Me");
  1137.     pr_string (R_VENUS,    C_OBJ,    "Ve");
  1138.     pr_string (R_MARS,    C_OBJ,    "Ma");
  1139.     pr_string (R_JUPITER,    C_OBJ,    "Ju");
  1140.     pr_string (R_SATURN,    C_OBJ,    "Sa");
  1141.     pr_string (R_URANUS,    C_OBJ,    "Ur");
  1142.     pr_string (R_NEPTUNE,    C_OBJ,    "Ne");
  1143.     pr_string (R_PLUTO,    C_OBJ,    "Pl");
  1144. }
  1145.  
  1146. /* display dawn/dusk times
  1147.  */
  1148. pr_twilight (np)
  1149. Now *np;
  1150. {
  1151.     float dusk, dawn;
  1152.     float tmp;
  1153.     int status;
  1154.  
  1155.     twilight_cir (np, &dawn, &dusk, &status);
  1156.     switch (status) {
  1157.     case -1:    /* sun never sets today */
  1158.     case  1:    /* sun never rises today */
  1159.     case  2:    /* can not find where sun is! */
  1160.         pr_blanks (R_DAWN, C_DAWNV, 5);
  1161.         pr_blanks (R_DUSK, C_DUSKV, 5);
  1162.         pr_blanks (R_LON, C_LONV, 5);
  1163.         return;
  1164.     default:    /* all ok */
  1165.         ;
  1166.     }
  1167.  
  1168.     /* print times in local tz */
  1169.     tmp = dawn - tz; range (&tmp, 24.0);
  1170.     pr_mtime (R_DAWN, C_DAWNV, tmp);
  1171.     tmp = dusk - tz; range (&tmp, 24.0);
  1172.     pr_mtime (R_DUSK, C_DUSKV, tmp);
  1173.     tmp = dawn - dusk; range (&tmp, 24.0);
  1174.     pr_mtime (R_LON, C_LONV, tmp);
  1175. }
  1176.  
  1177. /* display sun's rise/set times, and length of day.
  1178.  */
  1179. pr_sunrs (np, dis)
  1180. Now *np;
  1181. float dis;
  1182. {
  1183.     float utcr, utcs, azr, azs;
  1184.     float tmp;
  1185.     int status;
  1186.  
  1187.     sunrs_cir (np, dis, &utcr, &utcs, &azr, &azs, &status);
  1188.     switch (status) {
  1189.     case -1:    /* sun never sets today */
  1190.         pr_string (R_SUNR, C_SUNRT, "Circumpolar           ");
  1191.         pr_blanks (R_SUNS, C_SUNST, 14);
  1192.         pr_blanks (R_LOD, C_LODV, 5);
  1193.         return;
  1194.     case  1:    /* sun never rises today */
  1195.         pr_string (R_SUNR, C_SUNRT, "Never rises           ");
  1196.         pr_blanks (R_SUNS, C_SUNST, 14);
  1197.         pr_blanks (R_LOD, C_LODV, 5);
  1198.         return;
  1199.     case  2:    /* can not find where sun is! */
  1200.         pr_string (R_SUNR, C_SUNRT, "?Error?               ");
  1201.         pr_blanks (R_SUNS, C_SUNST, 14);
  1202.         pr_blanks (R_LOD, C_LODV, 5);
  1203.         return;
  1204.     default:    /* all ok */
  1205.         ;
  1206.     }
  1207.  
  1208.     /* use local tz */
  1209.     tmp = utcr - tz; range (&tmp, 24.0);
  1210.     pr_mtime (R_SUNR, C_SUNRT, tmp);
  1211.     /* possible sunrise error near utc midnight if status is -2 */
  1212.     pr_char (R_SUNR, C_SUNRT+5, status==-2 ? '?' : ' ');
  1213.     pr_char (R_SUNR, C_SUNRT+6, '@');
  1214.     pr_angle (R_SUNR, C_SUNRAZ, azr);
  1215.  
  1216.     tmp = utcs - tz; range (&tmp, 24.0);
  1217.     pr_mtime (R_SUNS, C_SUNST, tmp);
  1218.     /* possible sunset error near utc midnight if status is -3 */
  1219.     pr_char (R_SUNS, C_SUNST+5, status==-3 ? '?' : ' ');
  1220.     pr_char (R_SUNS, C_SUNST+6, '@');
  1221.     pr_angle (R_SUNS, C_SUNSAZ, azs);
  1222.  
  1223.     pr_mtime (R_LOD, C_LODV, utcs - utcr);
  1224. }
  1225.  
  1226. /* display moon's rise/set times
  1227.  */
  1228. pr_moonrs (np)
  1229. Now *np;
  1230. {
  1231.     float utcr, utcs, azr, azs;
  1232.     float tmp;
  1233.     int status;
  1234.  
  1235.     moonrs_cir (np, &utcr, &utcs, &azr, &azs, &status);
  1236.     switch (status) {
  1237.     case -1:    /* never sets (circumpolar) */
  1238.         pr_string (R_MOONR, C_MOONRT, "Circumpolar           ");
  1239.         pr_blanks (R_MOONS, C_MOONST, 14);
  1240.         return;
  1241.     case  1:    /* moon never rises today */
  1242.         pr_string (R_MOONR, C_MOONRT, "Never rises           ");
  1243.         pr_blanks (R_MOONS, C_MOONST, 14);
  1244.         return;
  1245.     case  2:    /* can not find where moon is! */
  1246.         pr_string (R_MOONR, C_MOONRT, "?Error?               ");
  1247.         pr_blanks (R_MOONS, C_MOONST, 14);
  1248.         return;
  1249.     default:    /* all ok */
  1250.         ;
  1251.     }
  1252.  
  1253.     /* use local tz */
  1254.     tmp = utcr - tz; range (&tmp, 24.0);
  1255.     pr_mtime (R_MOONR, C_MOONRT, tmp);
  1256.     /* possible moonrise error near midnight if status is -2 */
  1257.     pr_char (R_MOONR, C_MOONRT+5, status==-2 ? '?' : ' ');
  1258.     pr_char (R_MOONR, C_MOONRT+6, '@');
  1259.     pr_angle (R_MOONR, C_MOONRAZ, azr);
  1260.  
  1261.     tmp = utcs - tz; range (&tmp, 24.0);
  1262.     pr_mtime (R_MOONS, C_MOONST, tmp);
  1263.     /* possible moonset error near midnight if status is -3 */
  1264.     pr_char (R_MOONS, C_MOONST+5, status==-3 ? '?' : ' ');
  1265.     pr_char (R_MOONS, C_MOONST+6, '@');
  1266.     pr_angle (R_MOONS, C_MOONSAZ, azs);
  1267. }
  1268.  
  1269. /* print sun's info now */
  1270. pr_sun (np, epoch)
  1271. Now *np;
  1272. float epoch;
  1273. {
  1274.     Sky sky;
  1275.  
  1276.     sun_cir (np, &sky);
  1277.  
  1278.     if (epoch != EOD)
  1279.         precess ((float)mjd, epoch, &sky.s_ra, &sky.s_dec);
  1280.     pr_ra (R_SUN, C_RA, sky.s_ra);
  1281.     pr_angle (R_SUN, C_DEC, sky.s_dec);
  1282.     pr_angle (R_SUN, C_HLONG, sky.s_hlong);
  1283.     pr_angle (R_SUN, C_HLAT, sky.s_hlat);
  1284.     pr_angle (R_SUN, C_AZ, sky.s_az);
  1285.     pr_angle (R_SUN, C_ALT, sky.s_alt);
  1286.  
  1287.     pr_float (R_SUN, C_EDIST, "%6.4f", sky.s_edist);
  1288.     pr_float (R_SUN, C_SIZE, "%4.0f", sky.s_size);
  1289.     pr_float (R_SUN, C_MAG, "%4.0f", sky.s_mag);
  1290. }
  1291.  
  1292. /* print moon's info now */
  1293. pr_moon (np, epoch)
  1294. Now *np;
  1295. float epoch;
  1296. {
  1297.     Sky sky;
  1298.  
  1299.     moon_cir (np, &sky);
  1300.  
  1301.     if (epoch != EOD)
  1302.         precess ((float)mjd, epoch, &sky.s_ra, &sky.s_dec);
  1303.     pr_ra (R_MOON, C_RA, sky.s_ra);
  1304.     pr_angle (R_MOON, C_DEC, sky.s_dec);
  1305.     pr_angle (R_MOON, C_AZ, sky.s_az);
  1306.     pr_angle (R_MOON, C_ALT, sky.s_alt);
  1307.  
  1308.     pr_float (R_MOON, C_EDIST, "%6.0f", sky.s_edist/1.609344); /* km->m */
  1309.     pr_float (R_MOON, C_SDIST, "%6.4f", sky.s_sdist);
  1310.     pr_float (R_MOON, C_ELONG, "%6.1f", sky.s_elong);
  1311.     pr_float (R_MOON, C_SIZE, "%4.0f", sky.s_size);
  1312.     pr_float (R_MOON, C_MAG, "%4.0f", sky.s_mag);
  1313.     pr_float (R_MOON, C_PHASE, "%3.0f", sky.s_phase);
  1314.  
  1315. }
  1316.  
  1317. pr_planet (p, np, epoch)
  1318. int p;
  1319. Now *np;
  1320. float epoch;
  1321. {
  1322.     Sky sky;
  1323.     int row = R_PLANTAB+4 + p;
  1324.  
  1325.     planet_cir (p, np, &sky);
  1326.  
  1327.     if (epoch != EOD)
  1328.         precess ((float)mjd, epoch, &sky.s_ra, &sky.s_dec);
  1329.     pr_ra (row, C_RA, sky.s_ra);
  1330.     pr_angle (row, C_DEC, sky.s_dec);
  1331.     pr_angle (row, C_HLONG, sky.s_hlong);
  1332.     pr_angle (row, C_HLAT, sky.s_hlat);
  1333.     pr_angle (row, C_AZ, sky.s_az);
  1334.     pr_angle (row, C_ALT, sky.s_alt);
  1335.  
  1336.     pr_float (row, C_EDIST,(sky.s_edist>=10.0)?"%6.3f":"%6.4f",sky.s_edist);
  1337.     pr_float (row, C_SDIST,(sky.s_sdist>=10.0)?"%6.3f":"%6.4f",sky.s_sdist);
  1338.     pr_float (row, C_ELONG, "%6.1f", sky.s_elong);
  1339.     pr_float (row, C_SIZE, "%4.1f", sky.s_size);
  1340.     pr_float (row, C_MAG, "%4.1f", sky.s_mag);
  1341.     pr_float (row, C_PHASE, "%3.0f", sky.s_phase);
  1342. }
  1343.  
  1344. /* print all the time/date/where related stuff */
  1345. pr_now (np)
  1346. Now *np;
  1347. {
  1348.     char str[32];
  1349.     double lmjd = mjd - tz/24.0;
  1350.     float lst;
  1351.  
  1352.     sprintf (str, "%14.5f", (double)mjd + 2415020L);
  1353.     pr_string (R_JD, C_JDV, str);
  1354.  
  1355.     pr_time (R_UT, C_UTV, (float)mjd_hr(mjd));
  1356.     pr_date (R_UD, C_UD, (float)mjd_day(mjd));
  1357.  
  1358.     pr_time (R_TZONE, C_TZONEV, tz);
  1359.     sprintf (str, "%-3.3s", tznm); pr_string (R_TZN, C_TZN, str);
  1360.     pr_time (R_LT, C_LT, (float)mjd_hr(lmjd));
  1361.     pr_date (R_LD, C_LD, (float)mjd_day(lmjd));
  1362.  
  1363.     now_lst (np, &lst);
  1364.     pr_time (R_LST, C_LSTV, lst);
  1365.     pr_gangle (R_LONG, C_LONGV, -lng);    /* + west */
  1366.     pr_gangle (R_LAT, C_LATV, lat);
  1367.  
  1368.     /* print the calendar for local day, if new month/year.  */
  1369.     pr_calendar ((float)mjd_day(mjd-tz/24.0));
  1370. }
  1371.  
  1372. static
  1373. pr_calendar (jd)
  1374. float jd;
  1375. {
  1376.     static char *mnames[] = {
  1377.         "January", "February", "March", "April", "May", "June",
  1378.         "July", "August", "September", "October", "November", "December"
  1379.     };
  1380.     static int last_m, last_y;
  1381.     char str[64];
  1382.     int m, y;
  1383.     float d;
  1384.     int f, nd;
  1385.     int r;
  1386.     float jd0;
  1387.  
  1388.     /* get m/d/y. do nothing if still same month */
  1389.     mjd_cal (jd, &m, &d, &y);
  1390.     if (m == last_m && y == last_y)
  1391.         return;
  1392.     last_m = m;
  1393.     last_y = y;
  1394.  
  1395.     /* find day of week of first day of month */
  1396.     cal_mjd (m, 1.0, y, &jd0);
  1397.     mjd_dow (jd0, &f);
  1398.     if (f < 0) {
  1399.         /* can't figure it out - too hard before Gregorian */
  1400.         int i;
  1401.         for (i = 8; --i >= 0; )
  1402.         pr_string (R_CAL+i, C_CAL, "                    ");
  1403.         return;
  1404.     }
  1405.  
  1406.     /* print header */
  1407.     pr_blanks (R_CAL, C_CAL, 20);
  1408.     sprintf (str, "%s %4d", mnames[m-1], y);
  1409.     pr_string (R_CAL, C_CAL + (20 - (strlen(mnames[m-1]) + 5))/2, str);
  1410.     pr_string (R_CAL+1, C_CAL, "Su Mo Tu We Th Fr Sa");
  1411.  
  1412.     /* find number of days in this month */
  1413.     mjd_dpm (jd0, &nd);
  1414.  
  1415.     /* print the calendar */
  1416.     for (r = 0; r < 6; r++) {
  1417.         char row[7*3+1], *rp = row;
  1418.         int c;
  1419.         for (c = 0; c < 7; c++) {
  1420.         int i = r*7+c;
  1421.         if (i < f || i >= f + nd)
  1422.             sprintf (rp, "   ");
  1423.         else
  1424.             sprintf (rp, "%2d ", i-f+1);
  1425.         rp += 3;
  1426.         }
  1427.         pr_string (R_CAL+2+r, C_CAL, row);
  1428.     }
  1429.  
  1430.     /* over print the new and full moons for this month.
  1431.      * TODO: don't really know which dates to use here (see moonnf())
  1432.      *   so try several to be fairly safe. have to go back to 4/29/1988
  1433.      *   to find the full moon on 5/1 for example.
  1434.      */
  1435.     pr_nfmoon (jd0-3, m, f);
  1436.     pr_nfmoon (jd0+15, m, f);
  1437. }
  1438.  
  1439. static
  1440. pr_nfmoon (jd, m, f)
  1441. float jd;
  1442. int m, f;
  1443. {
  1444.     static char nm[] = "NM", fm[] = "FM";
  1445.     float dm;
  1446.     int mm, ym;
  1447.     float jdn, jdf;
  1448.     int di;
  1449.  
  1450.     moonnf (jd, &jdn, &jdf);
  1451.     mjd_cal (jdn, &mm, &dm, &ym);
  1452.     if (m == mm) {
  1453.         di = dm + f - 1;
  1454.         pr_string (R_CAL+2+di/7, C_CAL+3*(di%7), nm);
  1455.     }
  1456.     mjd_cal (jdf, &mm, &dm, &ym);
  1457.     if (m == mm) {
  1458.         di = dm + f - 1;
  1459.         pr_string (R_CAL+2+di/7, C_CAL+3*(di%7), fm);
  1460.     }
  1461. }
  1462.  
  1463.  
  1464. /* print info about object */
  1465. pr_obj(ra, dec, e, np, epoch)
  1466. float ra, dec, e;/* object'a ra, dec, epoch */
  1467. Now *np;    /* now info */
  1468. float epoch;    /* desired print epoch */
  1469. {
  1470.     Sky sky;
  1471.  
  1472.     /* fill sky as much as possible for object at ra/dec@EOD now */
  1473.     obj_cir (ra, dec, e, np, &sky);
  1474.  
  1475.     if (epoch != EOD)
  1476.         precess ((float)mjd, epoch, &sky.s_ra, &sky.s_dec);
  1477.     pr_ra (R_OBJ, C_RA, sky.s_ra);
  1478.     pr_angle (R_OBJ, C_DEC, sky.s_dec);
  1479.     pr_angle (R_OBJ, C_ALT, sky.s_alt);
  1480.     pr_angle (R_OBJ, C_AZ, sky.s_az);
  1481. }
  1482. xXx
  1483. echo extracting pr0.c
  1484. cat > pr0.c << 'xXx'
  1485. /* basic print routines.
  1486.  */
  1487.  
  1488. #include <stdio.h>
  1489. #include <math.h>
  1490. #include "astro.h"
  1491. #include "screen.h"
  1492.  
  1493. /* the pr_ functions draw on the screen and in here so we can redraw
  1494.  * the screen via pr_redraw.
  1495.  */
  1496. static char screen_shadow[NR][NC];
  1497.  
  1498.  
  1499. pr_newcir (y)
  1500. int y;
  1501. {
  1502.     static char ncmsg[] = "NEW CIRCUMSTANCES";
  1503.     static char nomsg[] = "                 ";
  1504.     static int last_y = -1;
  1505.  
  1506.     if (y != last_y) {
  1507.         pr_string (R_NEWCIR, C_NEWCIR, y ? ncmsg : nomsg);
  1508.         last_y = y;
  1509.     }
  1510. }
  1511.  
  1512. /* draw n blanks at the given cursor position.  */
  1513. pr_blanks (r, c, n)
  1514. int r, c, n;
  1515. {
  1516.     char bl[NC+1];
  1517.     sprintf (bl, "%*s", n, "");
  1518.     pr_string (r, c, bl);
  1519. }
  1520.  
  1521. /* erase the planet info on the given row */
  1522. pr_noplanet (r)
  1523. int r;
  1524. {
  1525.     pr_blanks (r, C_RA, 80-C_RA+1);
  1526. }
  1527.  
  1528. /* print the given value, v, in "sexadecimal" format at [r,c]
  1529.  * ie, in the form A:m.P, where A is a digits wide, P is p digits.
  1530.  * if p == 0, then no decimal point either.
  1531.  */
  1532. pr_sexad (r, c, a, p, mod, v)
  1533. int r, c;
  1534. int a, p;    /* left space, min precision */
  1535. int mod;    /* don't let whole portion get this big */
  1536. float v;
  1537. {
  1538.     char astr[32], str[32];
  1539.     int dec;
  1540.     float frac;
  1541.     int visneg;
  1542.  
  1543.     plt_val (r, c, v);
  1544.     if (v >= 0.0)
  1545.         visneg = 0;
  1546.     else {
  1547.         visneg = 1;
  1548.         v = -v;
  1549.     }
  1550.  
  1551.     dec = v;
  1552.     frac = (v - dec)*60.0;
  1553.     sprintf (str, "59.%.*s5", p, "999999999");
  1554.     if (frac >= atof (str)) {
  1555.         dec += 1;
  1556.         frac = 0.0;
  1557.     }
  1558.     dec %= mod;
  1559.     if (dec == 0 && visneg)
  1560.         strcpy (str, "-0");
  1561.     else
  1562.         sprintf (str, "%d", visneg ? -dec : dec);
  1563.  
  1564.     sprintf (astr, "%*s:%0*.*f", a, str, p == 0 ? 2 : p+3, p, frac);
  1565.     pr_string (r, c, astr);
  1566. }
  1567.  
  1568. /* print the given value, t, in sexagesimal format at [r,c]
  1569.  * ie, in the form T:mm:ss, where T is nd digits wide.
  1570.  * N.B. we assume nd >= 2.
  1571.  */
  1572. pr_sexag (r, c, nd, t)
  1573. int r, c, nd;
  1574. float t;
  1575. {
  1576.     char tstr[32];
  1577.     int h, m, s;
  1578.     int tisneg;
  1579.     
  1580.     plt_val (r, c, t);
  1581.     dec_sex (t, &h, &m, &s, &tisneg);
  1582.     if (h == 0 && tisneg)
  1583.         sprintf (tstr, "%*s-0:%02d:%02d", nd-2, "", m, s);
  1584.     else
  1585.         sprintf (tstr, "%*d:%02d:%02d", nd, tisneg ? -h : h, m, s);
  1586.     pr_string (r, c, tstr);
  1587. }
  1588.  
  1589. /* print angle ra, in radians, in ra hours as hh:mm.m at [r,c]
  1590.  * N.B. we assume ra is >= 0.
  1591.  */
  1592. pr_ra (r, c, ra)
  1593. int r, c;
  1594. float ra;
  1595. {
  1596.     pr_sexad (r, c, 2, 1, 24, radhr(ra));
  1597. }
  1598.  
  1599. /* print time, t, as hh:mm:ss */
  1600. pr_time (r, c, t)
  1601. int r, c;
  1602. float t;
  1603. {
  1604.     pr_sexag (r, c, 2, t);
  1605. }
  1606.  
  1607. /* print time, t, as hh:mm */
  1608. pr_mtime (r, c, t)
  1609. int r, c;
  1610. float t;
  1611. {
  1612.     pr_sexad (r, c, 2, 0, 24, t);
  1613. }
  1614.  
  1615. /* print angle, a, in rads, as degress at [r,c] in form ddd:mm */
  1616. pr_angle(r, c, a)
  1617. int r, c;
  1618. float a;
  1619. {
  1620.     pr_sexad (r, c, 3, 0, 360, raddeg(a));
  1621. }
  1622.  
  1623. /* print angle, a, in rads, as degress at [r,c] in form dddd:mm:ss */
  1624. pr_gangle(r, c, a)
  1625. int r, c;
  1626. float a;
  1627. {
  1628.     pr_sexag (r, c, 4, raddeg(a));
  1629. }
  1630.  
  1631. /* print the given modified Julian date, jd, as the starting date at [r,c]
  1632.  * in the form mm/dd/yyyy.
  1633.  */
  1634. pr_date (r, c, jd)
  1635. int r, c;
  1636. float jd;
  1637. {
  1638.     char dstr[32];
  1639.     int m, y;
  1640.     float d;
  1641.  
  1642.     mjd_cal (jd, &m, &d, &y);
  1643.  
  1644.     /* shadow to the plot subsystem as years
  1645.      * TODO: make this monotonically increasing
  1646.      */
  1647.     plt_val (r, c, y + (m-1 + (d-1)/30.4)/12.0);
  1648.  
  1649.     sprintf (dstr, "%2d/%02d/%04d", m, (int)(d), y);
  1650.     pr_string (r, c, dstr);
  1651. }
  1652.  
  1653. pr_char (row, col, c)
  1654. int row, col;
  1655. char c;
  1656. {
  1657.     c_pos (row, col);
  1658.     putchar (c);
  1659.     screen_shadow[row-1][col-1] = c;
  1660. }
  1661.  
  1662. pr_string (r, c, s)
  1663. int r, c;
  1664. char *s;
  1665. {
  1666.     c_pos (r, c);
  1667.     fputs (s, stdout);
  1668.     strncpy (&screen_shadow[r-1][c-1], s, strlen(s));
  1669. }
  1670.  
  1671. pr_float (r, c, fmt, f)
  1672. int r, c;
  1673. char *fmt;
  1674. float f;
  1675. {
  1676.     char str[80];
  1677.     sprintf (str, fmt, f);
  1678.     pr_string (r, c, str);
  1679.     plt_val (r, c, f);
  1680. }
  1681.  
  1682. pr_erase()
  1683. {
  1684.     int r, c;
  1685.     char *rp;
  1686.  
  1687.     c_erase();
  1688.     for (r = 0; r < NR; r++) {
  1689.         rp = screen_shadow[r];
  1690.         for (c = 0; c < NC; c++)
  1691.         rp[c] = ' ';
  1692.     }
  1693. }
  1694.  
  1695. /* redraw entire screen from the screen_shadow
  1696.  * N.B. might have '\0's in array; print them as ' '
  1697.  * N.B. don't write in lower right corner of screen to avoid scroll.
  1698.  */
  1699. pr_redraw()
  1700. {
  1701.     int r, c;
  1702.     char ch;
  1703.     int nc;
  1704.     char *rp;
  1705.  
  1706.     c_erase();
  1707.     for (r = 0; r < NR; r++) {
  1708.         rp = screen_shadow[r];
  1709.         c_pos (r+1,1);
  1710.         /* set nc <= index of last non-blank char */
  1711.         for (nc = NC; --nc >= 0; ) {
  1712.         ch = rp[nc];
  1713.         if (ch != ' ' && ch != '\0')
  1714.             break;
  1715.         }
  1716.         /* draw chars with index 0..nc */
  1717.         for (c = 0; c <= nc; c++) {
  1718.         ch = *rp++;
  1719.         if (ch == '\0')
  1720.             ch = ' ';
  1721.         putchar (ch);
  1722.         }
  1723.     }
  1724. }
  1725.  
  1726. pr_prompt (p)
  1727. char *p;
  1728. {
  1729.     int c;
  1730.  
  1731.     c_pos (R_PROMPT, C_PROMPT);
  1732.     c_eol ();
  1733.     for (c = C_PROMPT-1; c < NC; c++)
  1734.         screen_shadow[R_PROMPT-1][c] = ' ';
  1735.  
  1736.     pr_string (R_PROMPT, C_PROMPT, p);
  1737. }
  1738. xXx
  1739. echo extracting screen.h
  1740. cat > screen.h << 'xXx'
  1741. /* screen layout details */
  1742.  
  1743. /* size of screen */
  1744. #define    NR    24
  1745. #define    NC    80
  1746.  
  1747. #define    LGAP    5    /* gap between field name and value in left column */
  1748. #define    GAP    6    /* gap between field name and value in other columns */
  1749.  
  1750. /* location of the various fields */
  1751. #define    R_TITLE        1
  1752. #define    C_TITLE        (NC/2)
  1753. #define    R_PROMPT    2
  1754. #define    C_PROMPT    1
  1755. #define    R_NEWCIR    3
  1756. #define    C_NEWCIR    ((NC-17)/2)    /* 17 is length of the message */
  1757.  
  1758. #define    R_JD    4
  1759. #define    C_JD    1
  1760. #define    C_JDV    (C_JD+LGAP)
  1761. #define    R_LST    4
  1762. #define    C_LST    28
  1763. #define    C_LSTV    (C_LST+GAP)
  1764. #define    R_UT    5
  1765. #define    C_UT    1
  1766. #define    C_UTV    (C_UT+LGAP)
  1767. #define    R_UD    R_UT
  1768. #define    C_UD    (C_UT+14)
  1769. #define    R_TZN    6
  1770. #define    C_TZN    1
  1771. #define    R_LT    R_TZN
  1772. #define    C_LT    (C_TZN+LGAP)
  1773. #define    R_LD    R_TZN
  1774. #define    C_LD    (C_TZN+14)
  1775.  
  1776. #define    R_LAT    5
  1777. #define    C_LAT    28
  1778. #define    C_LATV    (C_LAT+4)
  1779. #define    R_LONG    5
  1780. #define    C_LONG    44
  1781. #define    C_LONGV    (C_LONG+4)
  1782. #define    R_TZONE    4
  1783. #define    C_TZONE    44
  1784. #define    C_TZONEV (C_TZONE+GAP)
  1785.  
  1786. #define    R_HEIGHT 8
  1787. #define    C_HEIGHT 28
  1788. #define    C_HEIGHTV (C_HEIGHT+GAP)
  1789. #define    R_TEMP    8
  1790. #define    C_TEMP    44
  1791. #define    C_TEMPV    (C_TEMP+GAP)
  1792. #define    R_PRES    9
  1793. #define    C_PRES    28
  1794. #define    C_PRESV    (C_PRES+GAP)
  1795. #define    R_NSTEP 7
  1796. #define    C_NSTEP    44
  1797. #define    C_NSTEPV (C_NSTEP+GAP)
  1798. #define    R_STPSZ    7
  1799. #define    C_STPSZ    28
  1800. #define    C_STPSZV (C_STPSZ+GAP)
  1801. #define    R_LOD    9
  1802. #define    C_LOD    44
  1803. #define    C_LODV    (C_LOD+GAP+3)
  1804. #define    R_LON    10
  1805. #define    C_LON    44
  1806. #define    C_LONV    (C_LON+GAP+3)
  1807. #define    R_PLOT    10
  1808. #define    C_PLOT    28
  1809. #define    C_PLOTV    (C_PLOT+GAP)
  1810.  
  1811. #define    R_CAL    3
  1812. #define    C_CAL   60
  1813.  
  1814. #define    RS_TGAP    (LGAP+3)
  1815. #define    RS_AZGAP 16
  1816. #define    R_SUNR    7
  1817. #define    C_SUNR    1
  1818. #define    C_SUNRT    (C_SUNR+RS_TGAP)
  1819. #define    C_SUNRAZ (C_SUNR+RS_AZGAP)
  1820. #define    R_SUNS    8
  1821. #define    C_SUNS    1
  1822. #define    C_SUNST (C_SUNS+RS_TGAP)
  1823. #define    C_SUNSAZ (C_SUNS+RS_AZGAP)
  1824.  
  1825. #define    R_MOONR    9
  1826. #define    C_MOONR    1
  1827. #define    C_MOONRT (C_MOONR+RS_TGAP)
  1828. #define    C_MOONRAZ (C_MOONR+RS_AZGAP)
  1829. #define    R_MOONS    10
  1830. #define    C_MOONS    1
  1831. #define    C_MOONST (C_MOONS+RS_TGAP)
  1832. #define    C_MOONSAZ (C_MOONS+RS_AZGAP)
  1833.  
  1834. #define    R_DAWN    6
  1835. #define    C_DAWN    28
  1836. #define    C_DAWNV    (C_DAWN+GAP+3)
  1837. #define    R_DUSK    6
  1838. #define    C_DUSK    44
  1839. #define    C_DUSKV    (C_DUSK+GAP+3)
  1840.  
  1841. /* planet info table */
  1842. #define    R_PLANTAB    12
  1843. #define    R_EPOCH        (R_PLANTAB+1)
  1844. #define    C_EPOCH        C_RA
  1845. #define    R_SUN        (R_PLANTAB+2)
  1846. #define    R_MOON        (R_PLANTAB+3)
  1847. #define    R_MERCURY    (R_PLANTAB+4)
  1848. #define    R_VENUS        (R_PLANTAB+5)
  1849. #define    R_MARS        (R_PLANTAB+6)
  1850. #define    R_JUPITER    (R_PLANTAB+7)
  1851. #define    R_SATURN    (R_PLANTAB+8)
  1852. #define    R_URANUS    (R_PLANTAB+9)
  1853. #define    R_NEPTUNE    (R_PLANTAB+10)
  1854. #define    R_PLUTO        (R_PLANTAB+11)
  1855. #define    R_OBJ        (R_PLANTAB+12)
  1856. #define    C_OBJ    1
  1857. #define    C_RA    4
  1858. #define    C_DEC    12
  1859. #define    C_HLONG    19
  1860. #define    C_HLAT    26
  1861. #define    C_AZ    33
  1862. #define    C_ALT    40
  1863. #define    C_EDIST    47
  1864. #define C_SDIST 54
  1865. #define    C_ELONG    61
  1866. #define    C_SIZE    68
  1867. #define    C_MAG    73
  1868. #define    C_PHASE    78
  1869.  
  1870. #define    PW    (NC-C_PROMPT+1)    /* total prompt line width */
  1871.  
  1872. #define    F_SHFT    12        /* shift to flags fields */
  1873. #define    F_CHG    (1<<F_SHFT)    /* field may be picked for changing */
  1874. #define    F_PLT    (2<<F_SHFT)    /* field may be picked for plotting */
  1875. #define    F_VIS    (4<<F_SHFT)    /* field is visible (may be picked period) */
  1876. #define    rcfpack(r,c,f)    ((f) | ((r) << 7) | (c))
  1877. #define    unpackr(p)    (((p)>>7)&0x1f)
  1878. #define    unpackc(p)    ((p)&0x7f)
  1879. #define    tstpackf(p,f)    (((p)&(f))==(f))
  1880. xXx
  1881. echo extracting sel_lfd.c
  1882. cat > sel_fld.c << 'xXx'
  1883. #include "screen.h"
  1884.  
  1885. #define    cntrl(x)    ((x) & 037)
  1886. #define    ESC        cntrl('[')    /* char to exit input mode */
  1887. #define    QUIT        cntrl('d')    /* char to exit program */
  1888. #define    HELP        '?'        /* char to give help message */
  1889. #define    REDRAW        cntrl('l')    /* char to redraw (like vi) */
  1890. #define    VERSION        cntrl('v')    /* char to display version number */
  1891.  
  1892. /* table of the fields pickable for changing or plotting */
  1893. int fields[] = {
  1894.     rcfpack (R_DAWN, C_DAWN, F_VIS|F_CHG),
  1895.     rcfpack (R_DAWN, C_DAWNV, F_VIS|F_PLT),
  1896.     rcfpack (R_DUSK, C_DUSK, F_VIS|F_CHG),
  1897.     rcfpack (R_DUSK, C_DUSKV, F_VIS|F_PLT),
  1898.     rcfpack (R_EPOCH, C_EPOCH, F_VIS|F_CHG|F_PLT),
  1899.     rcfpack (R_HEIGHT, C_HEIGHTV, F_VIS|F_CHG|F_PLT),
  1900.     rcfpack (R_JUPITER, C_ALT, F_VIS|F_PLT),
  1901.     rcfpack (R_JUPITER, C_AZ, F_VIS|F_PLT),
  1902.     rcfpack (R_JUPITER, C_DEC, F_VIS|F_PLT),
  1903.     rcfpack (R_JUPITER, C_EDIST, F_VIS|F_PLT),
  1904.     rcfpack (R_JUPITER, C_ELONG, F_VIS|F_PLT),
  1905.     rcfpack (R_JUPITER, C_HLAT, F_VIS|F_PLT),
  1906.     rcfpack (R_JUPITER, C_HLONG, F_VIS|F_PLT),
  1907.     rcfpack (R_JUPITER, C_MAG, F_VIS|F_PLT),
  1908.     rcfpack (R_JUPITER, C_OBJ, F_VIS|F_CHG),
  1909.     rcfpack (R_JUPITER, C_PHASE, F_VIS|F_PLT),
  1910.     rcfpack (R_JUPITER, C_RA, F_VIS|F_PLT),
  1911.     rcfpack (R_JUPITER, C_SDIST, F_VIS|F_PLT),
  1912.     rcfpack (R_JUPITER, C_SIZE, F_VIS|F_PLT),
  1913.     rcfpack (R_LAT, C_LATV, F_VIS|F_CHG|F_PLT),
  1914.     rcfpack (R_LD, C_LD, F_VIS|F_PLT|F_CHG),
  1915.     rcfpack (R_LOD, C_LODV, F_VIS|F_CHG|F_PLT),
  1916.     rcfpack (R_LON, C_LONV, F_VIS|F_CHG|F_PLT),
  1917.     rcfpack (R_LONG, C_LONGV, F_VIS|F_CHG|F_PLT),
  1918.     rcfpack (R_LT, C_LT, F_VIS|F_CHG|F_PLT),
  1919.     rcfpack (R_MARS, C_ALT, F_VIS|F_PLT),
  1920.     rcfpack (R_MARS, C_AZ, F_VIS|F_PLT),
  1921.     rcfpack (R_MARS, C_DEC, F_VIS|F_PLT),
  1922.     rcfpack (R_MARS, C_EDIST, F_VIS|F_PLT),
  1923.     rcfpack (R_MARS, C_ELONG, F_VIS|F_PLT),
  1924.     rcfpack (R_MARS, C_HLAT, F_VIS|F_PLT),
  1925.     rcfpack (R_MARS, C_HLONG, F_VIS|F_PLT),
  1926.     rcfpack (R_MARS, C_MAG, F_VIS|F_PLT),
  1927.     rcfpack (R_MARS, C_OBJ, F_VIS|F_CHG),
  1928.     rcfpack (R_MARS, C_PHASE, F_VIS|F_PLT),
  1929.     rcfpack (R_MARS, C_RA, F_VIS|F_PLT),
  1930.     rcfpack (R_MARS, C_SDIST, F_VIS|F_PLT),
  1931.     rcfpack (R_MARS, C_SIZE, F_VIS|F_PLT),
  1932.     rcfpack (R_MERCURY, C_ALT, F_VIS|F_PLT),
  1933.     rcfpack (R_MERCURY, C_AZ, F_VIS|F_PLT),
  1934.     rcfpack (R_MERCURY, C_DEC, F_VIS|F_PLT),
  1935.     rcfpack (R_MERCURY, C_EDIST, F_VIS|F_PLT),
  1936.     rcfpack (R_MERCURY, C_ELONG, F_VIS|F_PLT),
  1937.     rcfpack (R_MERCURY, C_HLAT, F_VIS|F_PLT),
  1938.     rcfpack (R_MERCURY, C_HLONG, F_VIS|F_PLT),
  1939.     rcfpack (R_MERCURY, C_MAG, F_VIS|F_PLT),
  1940.     rcfpack (R_MERCURY, C_OBJ, F_VIS|F_CHG),
  1941.     rcfpack (R_MERCURY, C_PHASE, F_VIS|F_PLT),
  1942.     rcfpack (R_MERCURY, C_RA, F_VIS|F_PLT),
  1943.     rcfpack (R_MERCURY, C_SDIST, F_VIS|F_PLT),
  1944.     rcfpack (R_MERCURY, C_SIZE, F_VIS|F_PLT),
  1945.     rcfpack (R_MOON, C_ALT, F_VIS|F_PLT),
  1946.     rcfpack (R_MOON, C_AZ, F_VIS|F_PLT),
  1947.     rcfpack (R_MOON, C_DEC, F_VIS|F_PLT),
  1948.     rcfpack (R_MOON, C_EDIST, F_VIS|F_PLT),
  1949.     rcfpack (R_MOON, C_ELONG, F_VIS|F_PLT),
  1950.     rcfpack (R_MOON, C_MAG, F_VIS|F_PLT),
  1951.     rcfpack (R_MOON, C_OBJ, F_VIS|F_CHG),
  1952.     rcfpack (R_MOON, C_PHASE, F_VIS|F_PLT),
  1953.     rcfpack (R_MOON, C_RA, F_VIS|F_PLT),
  1954.     rcfpack (R_MOON, C_SDIST, F_VIS|F_PLT),
  1955.     rcfpack (R_MOON, C_SIZE, F_VIS|F_PLT),
  1956.     rcfpack (R_MOONR, C_MOONR, F_VIS|F_CHG),
  1957.     rcfpack (R_MOONR, C_MOONRAZ, F_VIS|F_PLT),
  1958.     rcfpack (R_MOONR, C_MOONRT, F_VIS|F_PLT),
  1959.     rcfpack (R_MOONS, C_MOONS, F_VIS|F_CHG),
  1960.     rcfpack (R_MOONS, C_MOONSAZ, F_VIS|F_PLT),
  1961.     rcfpack (R_MOONS, C_MOONST, F_VIS|F_PLT),
  1962.     rcfpack (R_NEPTUNE, C_ALT, F_VIS|F_PLT),
  1963.     rcfpack (R_NEPTUNE, C_AZ, F_VIS|F_PLT),
  1964.     rcfpack (R_NEPTUNE, C_DEC, F_VIS|F_PLT),
  1965.     rcfpack (R_NEPTUNE, C_EDIST, F_VIS|F_PLT),
  1966.     rcfpack (R_NEPTUNE, C_ELONG, F_VIS|F_PLT),
  1967.     rcfpack (R_NEPTUNE, C_HLAT, F_VIS|F_PLT),
  1968.     rcfpack (R_NEPTUNE, C_HLONG, F_VIS|F_PLT),
  1969.     rcfpack (R_NEPTUNE, C_MAG, F_VIS|F_PLT),
  1970.     rcfpack (R_NEPTUNE, C_OBJ, F_VIS|F_CHG),
  1971.     rcfpack (R_NEPTUNE, C_PHASE, F_VIS|F_PLT),
  1972.     rcfpack (R_NEPTUNE, C_RA, F_VIS|F_PLT),
  1973.     rcfpack (R_NEPTUNE, C_SDIST, F_VIS|F_PLT),
  1974.     rcfpack (R_NEPTUNE, C_SIZE, F_VIS|F_PLT),
  1975.     rcfpack (R_NSTEP, C_NSTEPV, F_VIS|F_CHG),
  1976.     rcfpack (R_OBJ, C_ALT, F_VIS|F_PLT),
  1977.     rcfpack (R_OBJ, C_AZ, F_VIS|F_PLT),
  1978.     rcfpack (R_OBJ, C_DEC, F_VIS|F_CHG|F_PLT),
  1979.     rcfpack (R_OBJ, C_OBJ, F_VIS|F_CHG),
  1980.     rcfpack (R_OBJ, C_RA, F_VIS|F_CHG|F_PLT),
  1981.     rcfpack (R_PLOT, C_PLOT, F_VIS|F_CHG),
  1982.     rcfpack (R_PLOT, C_PLOTV, F_VIS|F_CHG),
  1983.     rcfpack (R_PLUTO, C_ALT, F_VIS|F_PLT),
  1984.     rcfpack (R_PLUTO, C_AZ, F_VIS|F_PLT),
  1985.     rcfpack (R_PLUTO, C_DEC, F_VIS|F_PLT),
  1986.     rcfpack (R_PLUTO, C_EDIST, F_VIS|F_PLT),
  1987.     rcfpack (R_PLUTO, C_ELONG, F_VIS|F_PLT),
  1988.     rcfpack (R_PLUTO, C_HLAT, F_VIS|F_PLT),
  1989.     rcfpack (R_PLUTO, C_HLONG, F_VIS|F_PLT),
  1990.     rcfpack (R_PLUTO, C_MAG, F_VIS|F_PLT),
  1991.     rcfpack (R_PLUTO, C_OBJ, F_VIS|F_CHG),
  1992.     rcfpack (R_PLUTO, C_PHASE, F_VIS|F_PLT),
  1993.     rcfpack (R_PLUTO, C_RA, F_VIS|F_PLT),
  1994.     rcfpack (R_PLUTO, C_SDIST, F_VIS|F_PLT),
  1995.     rcfpack (R_PLUTO, C_SIZE, F_VIS|F_PLT),
  1996.     rcfpack (R_PRES, C_PRESV, F_VIS|F_CHG|F_PLT),
  1997.     rcfpack (R_SATURN, C_ALT, F_VIS|F_PLT),
  1998.     rcfpack (R_SATURN, C_AZ, F_VIS|F_PLT),
  1999.     rcfpack (R_SATURN, C_DEC, F_VIS|F_PLT),
  2000.     rcfpack (R_SATURN, C_EDIST, F_VIS|F_PLT),
  2001.     rcfpack (R_SATURN, C_ELONG, F_VIS|F_PLT),
  2002.     rcfpack (R_SATURN, C_HLAT, F_VIS|F_PLT),
  2003.     rcfpack (R_SATURN, C_HLONG, F_VIS|F_PLT),
  2004.     rcfpack (R_SATURN, C_MAG, F_VIS|F_PLT),
  2005.     rcfpack (R_SATURN, C_OBJ, F_VIS|F_CHG),
  2006.     rcfpack (R_SATURN, C_PHASE, F_VIS|F_PLT),
  2007.     rcfpack (R_SATURN, C_RA, F_VIS|F_PLT),
  2008.     rcfpack (R_SATURN, C_SDIST, F_VIS|F_PLT),
  2009.     rcfpack (R_SATURN, C_SIZE, F_VIS|F_PLT),
  2010.     rcfpack (R_STPSZ, C_STPSZV, F_VIS|F_CHG),
  2011.     rcfpack (R_SUN, C_ALT, F_VIS|F_PLT),
  2012.     rcfpack (R_SUN, C_AZ, F_VIS|F_PLT),
  2013.     rcfpack (R_SUN, C_DEC, F_VIS|F_PLT),
  2014.     rcfpack (R_SUN, C_EDIST, F_VIS|F_PLT),
  2015.     rcfpack (R_SUN, C_HLAT, F_VIS|F_PLT),
  2016.     rcfpack (R_SUN, C_HLONG, F_VIS|F_PLT),
  2017.     rcfpack (R_SUN, C_MAG, F_VIS|F_PLT),
  2018.     rcfpack (R_SUN, C_OBJ, F_VIS|F_CHG),
  2019.     rcfpack (R_SUN, C_RA, F_VIS|F_PLT),
  2020.     rcfpack (R_SUN, C_SIZE, F_VIS|F_PLT),
  2021.     rcfpack (R_SUNR, C_SUNR, F_VIS|F_CHG),
  2022.     rcfpack (R_SUNR, C_SUNRAZ, F_VIS|F_PLT),
  2023.     rcfpack (R_SUNR, C_SUNRT, F_VIS|F_PLT),
  2024.     rcfpack (R_SUNS, C_SUNS, F_VIS|F_CHG),
  2025.     rcfpack (R_SUNS, C_SUNSAZ, F_VIS|F_PLT),
  2026.     rcfpack (R_SUNS, C_SUNST, F_VIS|F_PLT),
  2027.     rcfpack (R_TEMP, C_TEMPV, F_VIS|F_CHG|F_PLT),
  2028.     rcfpack (R_TZN, C_TZN, F_VIS|F_CHG),
  2029.     rcfpack (R_TZONE, C_TZONEV, F_VIS|F_CHG),
  2030.     rcfpack (R_UD, C_UD, F_VIS|F_PLT|F_CHG),
  2031.     rcfpack (R_URANUS, C_ALT, F_VIS|F_PLT),
  2032.     rcfpack (R_URANUS, C_AZ, F_VIS|F_PLT),
  2033.     rcfpack (R_URANUS, C_DEC, F_VIS|F_PLT),
  2034.     rcfpack (R_URANUS, C_EDIST, F_VIS|F_PLT),
  2035.     rcfpack (R_URANUS, C_ELONG, F_VIS|F_PLT),
  2036.     rcfpack (R_URANUS, C_HLAT, F_VIS|F_PLT),
  2037.     rcfpack (R_URANUS, C_HLONG, F_VIS|F_PLT),
  2038.     rcfpack (R_URANUS, C_MAG, F_VIS|F_PLT),
  2039.     rcfpack (R_URANUS, C_OBJ, F_VIS|F_CHG),
  2040.     rcfpack (R_URANUS, C_PHASE, F_VIS|F_PLT),
  2041.     rcfpack (R_URANUS, C_RA, F_VIS|F_PLT),
  2042.     rcfpack (R_URANUS, C_SDIST, F_VIS|F_PLT),
  2043.     rcfpack (R_URANUS, C_SIZE, F_VIS|F_PLT),
  2044.     rcfpack (R_UT, C_UTV, F_VIS|F_PLT|F_CHG),
  2045.     rcfpack (R_VENUS, C_ALT, F_VIS|F_PLT),
  2046.     rcfpack (R_VENUS, C_AZ, F_VIS|F_PLT),
  2047.     rcfpack (R_VENUS, C_DEC, F_VIS|F_PLT),
  2048.     rcfpack (R_VENUS, C_EDIST, F_VIS|F_PLT),
  2049.     rcfpack (R_VENUS, C_ELONG, F_VIS|F_PLT),
  2050.     rcfpack (R_VENUS, C_HLAT, F_VIS|F_PLT),
  2051.     rcfpack (R_VENUS, C_HLONG, F_VIS|F_PLT),
  2052.     rcfpack (R_VENUS, C_MAG, F_VIS|F_PLT),
  2053.     rcfpack (R_VENUS, C_OBJ, F_VIS|F_CHG),
  2054.     rcfpack (R_VENUS, C_PHASE, F_VIS|F_PLT),
  2055.     rcfpack (R_VENUS, C_RA, F_VIS|F_PLT),
  2056.     rcfpack (R_VENUS, C_SDIST, F_VIS|F_PLT),
  2057.     rcfpack (R_VENUS, C_SIZE, F_VIS|F_PLT),
  2058. };
  2059. #define    NFIELDS (sizeof(fields)/sizeof(fields[0]))
  2060.  
  2061. /* let op select a field by moving around and hitting RETURN, or until see ESC.
  2062.  * only allow fields with the given flag mask.
  2063.  * return the rcfpack()'d field, or 0 if typed ESC.
  2064.  * N.B. we might also exit() entirely by calling bye() of op types QUIT.
  2065.  */
  2066. sel_fld (r, c, flag, prmpt, help)
  2067. int r, c;    /* inial row, col */
  2068. int flag;
  2069. char *prmpt, *help;
  2070. {
  2071.     char *lastp;
  2072.     int ch;
  2073.  
  2074.     lastp = 0;
  2075.     while (1) {
  2076.         if (lastp != prmpt) {
  2077.         lastp = prmpt;
  2078.         pr_prompt (lastp);
  2079.         }
  2080.         c_pos (r, c);
  2081.         switch (ch = read_char()) {
  2082.         case REDRAW:
  2083.         pr_redraw();
  2084.         lastp = 0;
  2085.         break;
  2086.         case VERSION:
  2087.         version();
  2088.         lastp = 0;
  2089.         break;
  2090.         case HELP:
  2091.         pr_prompt (help);
  2092.         (void) read_char(); /* hit any key to continue */
  2093.         lastp = 0;
  2094.         break;
  2095.         case QUIT:
  2096.         bye();    /* probably never returns */
  2097.         break;
  2098.         case ESC:
  2099.         return (0);
  2100.         case '\r':
  2101.         return (rcfpack (r, c, 0));
  2102.         default:
  2103.         move_cur (ch, flag, &r, &c);
  2104.         break;
  2105.         }
  2106.     }
  2107. }
  2108.  
  2109. /* move cursor to next field in given direction: hjkl.
  2110.  * limit eligible fields to those with given flag mask.
  2111.  */
  2112. static
  2113. move_cur (dirchar, flag, rp, cp)
  2114. char dirchar;
  2115. int flag;
  2116. int *rp, *cp;
  2117. {
  2118.     int curr = *rp, curc = *cp;
  2119.     int f, newf, *fp;
  2120.     int d, newd;
  2121.  
  2122.     newf = 0;
  2123.     newd = 1000;
  2124.  
  2125.     switch (dirchar) {
  2126.     case 'h': case 'H': /* left */
  2127.         /* go to next field to the left, or wrap.  */
  2128.         for (fp = fields+NFIELDS; --fp >= fields; ) {
  2129.         f = *fp;
  2130.         if (tstpackf(f,flag) && unpackr(f) == curr) {
  2131.             d = curc - unpackc(f);
  2132.             if (d > 0 && d < newd) {
  2133.             newf = f;
  2134.             newd = d;
  2135.             }
  2136.         }
  2137.         }
  2138.         if (newf)
  2139.         curc = unpackc(newf);
  2140.         else {
  2141.         curc = NC;
  2142.         move_cur (dirchar, flag, &curr, &curc);
  2143.         }
  2144.         break;
  2145.  
  2146.     case 'j': case 'J': /* down */
  2147.         /* go to closest field on next row down with anything on it,
  2148.          * or wrap.
  2149.          */
  2150.         for (fp = fields+NFIELDS; --fp >= fields; ) {
  2151.         f = *fp;
  2152.         if (tstpackf(f,flag)) {
  2153.             d = unpackr(f) - curr;
  2154.             if (d > 0 && d < newd) {
  2155.             newf = f;
  2156.             newd = d;
  2157.             }
  2158.         }
  2159.         }
  2160.         if (newf) {
  2161.         newf = nearestfld (unpackr(newf), curc, flag);
  2162.         curr = unpackr(newf);
  2163.         curc = unpackc(newf);
  2164.         } else {
  2165.         curr = 0;
  2166.         move_cur (dirchar, flag, &curr, &curc);
  2167.         }
  2168.         break;
  2169.  
  2170.     case 'k': case 'K': /* up */
  2171.         /* go to closest field on next row up with anything on it, 
  2172.          * or wrap.
  2173.          */
  2174.         for (fp = fields+NFIELDS; --fp >= fields; ) {
  2175.         f = *fp;
  2176.         if (tstpackf(f,flag)) {
  2177.             d = curr - unpackr(f);
  2178.             if (d > 0 && d < newd) {
  2179.             newf = f;
  2180.             newd = d;
  2181.             }
  2182.         }
  2183.         }
  2184.         if (newf) {
  2185.         newf = nearestfld (unpackr(newf), curc, flag);
  2186.         curr = unpackr(newf);
  2187.         curc = unpackc(newf);
  2188.         } else {
  2189.         curr = NR+1;
  2190.         move_cur (dirchar, flag, &curr, &curc);
  2191.         }
  2192.         break;
  2193.  
  2194.     case 'l': case 'L': /* right */
  2195.     case ' ': /* space also goes right */
  2196.         /* go to next field to the right, or wrap.  */
  2197.         for (fp = fields+NFIELDS; --fp >= fields; ) {
  2198.         f = *fp;
  2199.         if (tstpackf(f,flag) && unpackr(f) == curr) {
  2200.             d = unpackc(f) - curc;
  2201.             if (d > 0 && d < newd) {
  2202.             newf = f;
  2203.             newd = d;
  2204.             }
  2205.         }
  2206.         }
  2207.         if (newf)
  2208.         curc = unpackc(newf);
  2209.         else {
  2210.         curc = 0;
  2211.         move_cur (dirchar, flag, &curr, &curc);
  2212.         }
  2213.         break;
  2214.     }
  2215.  
  2216.     *rp = curr;
  2217.     *cp = curc;
  2218. }
  2219.  
  2220. /* return the nearest field with given flag mask, either way, on this row,
  2221.  * else -1 if none.
  2222.  */
  2223. static
  2224. nearestfld (r, c, flag)
  2225. int r, c, flag;
  2226. {
  2227.     int nf, f, *fp;
  2228.     int d, d0;
  2229.  
  2230.     nf = 0;
  2231.     d0 = 1000;
  2232.  
  2233.     for (fp = fields+NFIELDS; --fp >= fields; ) {
  2234.         f = *fp;
  2235.         if (tstpackf(f,flag) && unpackr(f) == r) {
  2236.         d = abs(c - unpackc(f));
  2237.         if (d < d0) {
  2238.             nf = f;
  2239.             d0 = d;
  2240.         }
  2241.         }
  2242.     }
  2243.     return (nf ? nf : -1);
  2244. }
  2245. xXx
  2246. echo extracting time.c
  2247. cat > time.c << 'xXx'
  2248. #include <stdio.h>
  2249. #include <time.h>
  2250. #include "astro.h"
  2251. #include "circum.h"
  2252.  
  2253. /* shorthands into np */
  2254. #define mjd    np->n_mjd
  2255. #define lat    np->n_lat
  2256. #define lng    np->n_lng
  2257. #define tz    np->n_tz
  2258. #define temp    np->n_temp
  2259. #define pressure    np->n_pressure
  2260. #define height    np->n_height
  2261. #define tznm    np->n_tznm
  2262.  
  2263. static long c0;
  2264. static double mjd0;
  2265.  
  2266. /* save current mjd and corresponding system clock for use by inc_mjd().
  2267.  * this establishes the base correspondence between the mjd and system clock.
  2268.  */
  2269. set_t0 (np)
  2270. Now *np;
  2271. {
  2272.     mjd0 = mjd;
  2273.     time (&c0);
  2274. }
  2275.  
  2276. /* fill in n_mjd/tz/tznm from system clock */
  2277. time_fromsys (np)
  2278. Now *np;
  2279. {
  2280.     extern long timezone;
  2281.     extern int daylight;
  2282.     extern char *tzname[2];
  2283.     extern struct tm *gmtime();
  2284.     struct tm *tp;
  2285.     long c;
  2286.     float day, hr;
  2287.  
  2288.     tzset();
  2289.     tz = timezone/3600;
  2290.     strncpy (tznm, tzname[daylight?1:0], sizeof(tznm)-1);
  2291.     tznm[sizeof(tznm)-1] = '\0';    /* insure string is terminated */
  2292.  
  2293.     time (&c);
  2294.     tp = gmtime (&c);
  2295.     cal_mjd (tp->tm_mon+1, (float)tp->tm_mday, tp->tm_year+1900, &day);
  2296.     sex_dec (tp->tm_hour, tp->tm_min, tp->tm_sec, &hr);
  2297.     mjd = (double)day + hr/24.0;
  2298. }
  2299.  
  2300. inc_mjd (np, inc)
  2301. Now *np;
  2302. float inc;
  2303. {
  2304.     if (inc == RTC) {
  2305.         long c;
  2306.         time (&c);
  2307.         mjd = mjd0 + (c - c0)/SPD;
  2308.     } else
  2309.         mjd += inc/24.0;
  2310.  
  2311.     /* round to nearest whole second.
  2312.      * without this, you can get fractional days so close to .5 but
  2313.      * not quite there that mjd_hr() can return 24.0
  2314.      */
  2315.     rnd_second (&mjd);
  2316. }
  2317. xXx
  2318. echo extracting version.c
  2319. cat > version.c << 'xXx'
  2320. /* N.B. edit this any time something is changed.
  2321.  * keep a running history too:
  2322.  *  2.0  9/13/1988 add version ^v option
  2323.  *  2.1  9/14/1988 moon phase always >= 0 to match planets convention
  2324.  *  2.2  9/20/1988 more caution in aaha_aux() guarding acos() arg range
  2325.  *  2.3  9/23/1988 exchange Altitude/Elevation titles (no code changes)
  2326.  *  2.4 10/31/1988 add credits banner, -s turns it off; savings time fix.
  2327.  *  2.5 12/26/1988 remove trace capability; add screen shadowing: ^l.
  2328.  *  2.6 12/28/1988 twilight defined as 18 rather than 15 degrees below horizon
  2329.  *  2.7 12/30/1988 add version to credits.
  2330.  *  3.0 12/31/1988 add graphing; add version to credits.
  2331.  *  3.1   1/1/1989 user def. graph labels; nstep/stpsz control; genuine c_eol
  2332.  *  3.2   1/3/1989 if set date/time then time does not inc first step
  2333.  *  3.3   1/6/1989 add z to plot files (still don't plot it however)
  2334.  *  3.4  1/22/1989 calendar and all rise/set times based on local date, not utc
  2335.  *  3.5   2/2/1989 sunrise/set times based on actual sun size and pressure/temp
  2336.  *  3.6   2/7/1989 try adding .cfg suffix if can't find config file
  2337.  *  3.7  2/13/1989 change to ^d to quit program.
  2338.  *  3.8   3/2/1989 shorten displayed precision, add heliocentric lat/long
  2339.  *  3.9   4/5/1989 discard leading termcap delay digits, for now
  2340.  *  3.10 4/27/1989 allow caps for moving cursor around too
  2341.  *  3.11 5/16/1989 local time prompt said utc; add NiteLn; check for bad plot
  2342.  *                 files; couldn't plot dayln or niteln.
  2343.  */
  2344.  
  2345. #include "screen.h"
  2346.  
  2347. static char vmsg[] = "Version 3.11  May 16, 1989";
  2348.  
  2349. version()
  2350. {
  2351.     pr_prompt (vmsg);
  2352.     (void) read_char(); /* hit any key to continue */
  2353. }
  2354.  
  2355. static char *cre[] = {
  2356. "Ephem - computerized ephemeris",
  2357. vmsg,
  2358. "by Elwood Downey",
  2359. "",
  2360. "Many formulas and tables are based, with permission, on material found in",
  2361. "\"Astronomy with your Personal Computer\"",
  2362. "by Dr. Peter Duffett-Smith, Cambridge University Press, 1985",
  2363. "",
  2364. "type any key to continue..."
  2365. };
  2366. credits()
  2367. {
  2368.     int r = 10;    /* first row of credits message */
  2369.     int l;
  2370.  
  2371.     pr_erase();
  2372.     for (l = 0; l < sizeof(cre)/sizeof(cre[0]); l++)
  2373.         pr_string (r++, (NC - strlen(cre[l]))/2, cre[l]);
  2374.     (void) read_char();    /* wait for any char to continue */
  2375. }
  2376. xXx
  2377.  
  2378.