home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part13 / mainmenu.c next >
Encoding:
C/C++ Source or Header  |  1993-05-15  |  35.0 KB  |  1,340 lines

  1. /* code to manage the stuff on the (permanent) main menu.
  2.  * this is also where the single static Now struct is maintained.
  3.  * the calendar is managed in calmenu.c.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <math.h>
  9. #if defined(__STDC__)
  10. #include <stdlib.h>
  11. #endif
  12. #include <X11/Xlib.h>
  13. #include <X11/keysym.h>
  14. #include <Xm/Xm.h>
  15. #include <Xm/Form.h>
  16. #include <Xm/Frame.h>
  17. #include <Xm/Label.h>
  18. #include <Xm/PushB.h>
  19. #include <Xm/RowColumn.h>
  20. #include <Xm/Separator.h>
  21. #include <Xm/SelectioB.h>
  22. #include "astro.h"
  23. #include "circum.h"
  24. #include "preferences.h"
  25.  
  26. typedef struct {
  27.     int id;        /* see below -- used just as a cross-check */
  28.     char *prompt;    /* used when asking for new value or NULL if can't */
  29.     char *label;    /* used for the menu label or NULL */
  30.     char *name;        /* used when selecting for plotting or NULL if can't */
  31.     char *altp[3];    /* alternate prompts based on preferences */
  32.     Widget pb_w;    /* pushbutton for display and changing/selecting */
  33. } Field;
  34.  
  35. #if defined(__STDC__) || defined(__cplusplus)
  36. #define P_(s) s
  37. #else
  38. #define P_(s) ()
  39. #endif
  40.  
  41. extern double mjd_day P_((double jd));
  42. extern double mjd_hr P_((double jd));
  43. extern int f_ison P_((void));
  44. extern int listing_ison P_((void));
  45. extern int plot_cartesian P_((FILE *pfp, Widget widget, unsigned int nx, unsigned int ny, int flipx, int flipy, int grid));
  46. extern int plot_ison P_((void));
  47. extern int srch_eval P_((double Mjd, double *tmincp));
  48. extern void all_update P_((Now *np, int how_much));
  49. extern void cal_mjd P_((int mn, double dy, int yr, double *Mjd));
  50. extern void calm_set P_((Now *np));
  51. extern void db_invalidate P_((void));
  52. extern void f_date P_((Widget w, double jd));
  53. extern void f_dec_sexsign P_((double x, int *h, int *m, int *s));
  54. extern void f_double P_((Widget w, char *fmt, double f));
  55. extern void f_gangle P_((Widget w, double a));
  56. extern void f_mtime P_((Widget w, double t));
  57. extern void f_off P_((void));
  58. extern void f_on P_((void));
  59. extern void f_signtime P_((Widget w, double t));
  60. extern void f_sscandate P_((char *bp, int pref, int *m, double *d, int *y));
  61. extern void f_sscansex P_((char *bp, int *d, int *m, int *s));
  62. extern void f_string P_((Widget w, char *s));
  63. extern void f_time P_((Widget w, double t));
  64. extern void get_xmstring P_((Widget w, char *resource, char **txtp));
  65. extern void gst_utc P_((double Mjd, double gst, double *utc));
  66. extern void inc_mjd P_((Now *np, double inc));
  67. extern void listing P_((void));
  68. extern void mjd_cal P_((double Mjd, int *mn, double *dy, int *yr));
  69. extern void mjd_year P_((double Mjd, double *yr));
  70. extern void now_lst P_((Now *np, double *lst));
  71. extern void plot P_((void));
  72. extern void plot_manage P_((void));
  73. extern void prompt_map_cb P_((Widget w, XtPointer client, XtPointer call));
  74. extern void range P_((double *v, double r));
  75. extern void register_selection P_((char *name));
  76. extern void set_t0 P_((Now *np));
  77. extern void set_xmstring P_((Widget w, char *resource, char *txt));
  78. extern void sex_dec P_((int hd, int m, int s, double *d));
  79. extern void time_fromsys P_((Now *np));
  80. extern void twilight_cir P_((Now *np, double dis, double *dawn, double *dusk, int *status));
  81. extern void watch_cursor P_((int want));
  82. extern void xe_msg P_((char *msg, int app_modal));
  83. extern void year_mjd P_((double y, double *Mjd));
  84.  
  85. void mm_manage P_((Widget main_window));
  86. void mm_reset P_((void));
  87. void mm_newcaldate P_((double newmjd));
  88. void mm_selection_mode P_((int whether));
  89. Now *mm_get_now P_((void));
  90. void redraw_screen P_((int how_much));
  91. static void create_main_form P_((Widget main_window));
  92. static void read_default_resources P_((void));
  93. static Widget fw P_((int fid));
  94. static void mm_set_buttons P_((int whether));
  95. static void mm_activate_cb P_((Widget w, XtPointer client, XtPointer call));
  96. static void mm_set_pref_prompts P_((Field *fp));
  97. static void mm_timer_cb P_((XtPointer client, XtIntervalId *id));
  98. static void mm_go_cb P_((Widget w, XtPointer client, XtPointer call));
  99. static void mm_go P_((void));
  100. static void print_tminc P_((int force));
  101. static void print_updating P_((void));
  102. static void print_idle P_((void));
  103. static void print_running P_((void));
  104. static void print_status P_((char *s));
  105. static void print_nstep P_((int force));
  106. static void print_spause P_((int force));
  107. static crack_fieldset P_((char *buf));
  108. static chg_fld P_((char *bp, Field *fp));
  109. static void prompt_ok_cb P_((Widget w, XtPointer client, XtPointer call));
  110. static void prompt P_((Field *fp));
  111. static void mm_now P_((int all));
  112. static void mm_twilight P_((int force));
  113. static void mm_newcir P_((int y));
  114.  
  115. #undef P_
  116.  
  117. extern Widget toplevel_w;
  118. extern char *myclass;
  119. extern XtAppContext xe_app;
  120. #define    XtD    XtDisplay(toplevel_w)
  121. extern char *sys_errlist[];
  122. extern errno;
  123. extern Widget calm_create();
  124.  
  125. /* shorthands for fields of a Now structure, now.
  126.  * first undo the ones for a Now pointer from circum.h.
  127.  */
  128. #undef mjd
  129. #undef lat
  130. #undef lng
  131. #undef tz
  132. #undef temp
  133. #undef pressure
  134. #undef elev
  135. #undef dip
  136. #undef epoch
  137. #undef tznm
  138.  
  139. #define mjd    now.n_mjd
  140. #define lat    now.n_lat
  141. #define lng    now.n_lng
  142. #define tz    now.n_tz
  143. #define temp    now.n_temp
  144. #define pressure now.n_pressure
  145. #define elev    now.n_elev
  146. #define    dip    now.n_dip
  147. #define epoch    now.n_epoch
  148. #define tznm    now.n_tznm
  149.  
  150. static Now now;        /* where when and how, right now */
  151. static double tminc;    /* hrs to inc time by each loop; RTC means use clock */
  152. static int nstep;    /* steps to go before stopping */
  153. static int spause;    /* secs to pause between steps */
  154. static int newcir = 1; /* set when circumstances change - means don't tminc */
  155.  
  156. static XtIntervalId mm_interval_id;    /* set while waiting in a pause loop */
  157. static int mm_selecting;        /* set while our fields are being selected */
  158.  
  159. /* field ids
  160.  * N.B. must be in same order as they appear in mm_field_map[].
  161.  */
  162. enum {
  163.     UD_FID, UT_FID, JD_FID, LST_FID,TZN_FID, TZONE_FID, LD_FID, LT_FID, 
  164.     DIP_FID, DAWN_FID, DUSK_FID, LON_FID, GAP, NSTEP_FID, STPSZ_FID, PAUSE_FID,
  165.     LAT_FID, LONG_FID, ELEV_FID, TEMP_FID, PRES_FID, EPOCH_FID
  166. };
  167.  
  168. /* array of label/button pairs.
  169.  * N.B. these must be in the same order as the _FID enums so the XX_FID may
  170.  *   be used as indices into the array.
  171.  * N.B. some of the prompts get set based on preferences but we need to put
  172.  *   *something* in the prompt field of selectable fields to trigger making a
  173.  *   button. These alternate prompts must be set to match the PREF_ enums.
  174.  */
  175. static Field mm_field_map[] = {
  176.     {UD_FID,    "dummy",                "UTC Date:","UD",
  177.     {   "UTC date (m/d/y or year.d): ",
  178.         "UTC date (y/m/d or year.d): ",
  179.         "UTC date (d/m/y or year.d): "
  180.     }
  181.     },
  182.     {UT_FID,    "UTC time (h:m:s): ",            "UTC Time:", "UT"},
  183.     {JD_FID,    "Julian Date: ",            "Julian:", "JD"},
  184.     {LST_FID,    "Local sidereal time (h:m:s): ",    "Sidereal:", "LST"},
  185.     {TZN_FID,    "Timezone abbreviation (3 char max): ",    "TZ Name:", NULL},
  186.     {TZONE_FID,    "Hours behind UTC: ",            "TZ Offset:", "TZ"},
  187.     {LD_FID,    "dummy",                "Local Date:", "LD",
  188.     {   "Local date (m/d/y or year.d): ",
  189.         "Local date (y/m/d or year.d): ",
  190.         "Local date (d/m/y or year.d): "
  191.     }
  192.     },
  193.     {LT_FID,    "Local time (h:m:s): ",    "Local Time:",    "LT"},
  194.     {DIP_FID,    "Sun's twilight dip, degrees below",    "Twilight Dip:", NULL},
  195.     {DAWN_FID,    NULL,                    "Dawn:", "Dawn"},
  196.     {DUSK_FID,    NULL,                    "Dusk:", "Dusk"},
  197.     {LON_FID,    NULL,                    "Night Length:", "NiteLen"},
  198.     {GAP},
  199.     {NSTEP_FID, "Number of steps to run: ",        "N Steps:", NULL},
  200.     {STPSZ_FID,    "\
  201. Step size increment:\n\
  202.     h:m:s, or\n\
  203.     <x>d for x days, or\n\
  204.     <x>s for x sidereal days, or\n\
  205.     r for RTC",                        "Step Size:", NULL},
  206.     {PAUSE_FID,    "Seconds to pause between steps: ",    "Pause:", NULL},
  207.     {LAT_FID,    "Latitude (+ north) (d:m:s): ",        "Latitude:", "Lat"},
  208.     {LONG_FID,    "Longitude (+ west) (d:m:s): ",        "Longitude:", "Long"},
  209.     {ELEV_FID,    "dummy",                "Elevation:", "Elev",
  210.     {   "Elevation above sea level (ft): ",
  211.         "Elevation above sea level (m): "
  212.     }
  213.     },
  214.     {TEMP_FID,    "dummy",                "Temperature:", "Temp",
  215.     {   "Temperature (degrees F): ",
  216.         "Temperature (degrees C): "
  217.     }
  218.     },
  219.     {PRES_FID,    "dummy",                "Atm Pressure:","AtmPr",
  220.     {   "Atmospheric pressure (inches of Mercury):",
  221.         "Atmospheric pressure (mBar):"
  222.     }
  223.     },
  224.     {EPOCH_FID,    "Epoch (decimal year): ", "Epoch:", NULL},
  225. };
  226.  
  227. #define    NFM    XtNumber(mm_field_map)
  228. #define    LFM    (&mm_field_map[NFM])
  229.  
  230. static Widget newcir_w;
  231. static Widget status_w;
  232. static Widget go_w;
  233.  
  234. /* this is the list of keywords that allow some initial values to be set.
  235.  * these are resources to the XEphem class as "XEphem.<keyword>: <value>".
  236.  */
  237. /* N.B. index of item is its switch/case value in crack_fieldset ()
  238.  */
  239. static char *keywords[] = {
  240.     /*  0 */    "Epoch",
  241.     /*  1 */    "Elevation",
  242.     /*  2 */    "JD",
  243.     /*  3 */    "Lat",
  244.     /*  4 */    "Long",
  245.     /*  5 */    "NSteps",
  246.     /*  6 */    "Pause",
  247.     /*  7 */    "Pressure",
  248.     /*  8 */    "StepSize",
  249.     /*  9 */    "Temp",
  250.     /* 10 */    "TZName",
  251.     /* 11 */    "TZone",
  252.     /* 12 */    "UD",
  253.     /* 13 */    "UT",
  254.     /* 14 */    "TwilightDip",
  255.     /* 15 */    "LD",
  256.     /* 16 */    "LT",
  257.     /* 17 */    "LST",
  258. };
  259.  
  260. /* called exactly once when the main form is made.
  261.  * create and manage all the widgets as children of the form_w.
  262.  */
  263. void
  264. mm_manage (main_window)
  265. Widget main_window;
  266. {
  267.     create_main_form(main_window);
  268.     mm_reset();
  269. }
  270.  
  271. /* reset things to their initial resource settings */
  272. void
  273. mm_reset()
  274. {
  275.     read_default_resources ();
  276.     redraw_screen (1);
  277.     mm_newcir(0);
  278.     mm_set_buttons (mm_selecting);
  279.     print_idle();
  280. }
  281.  
  282. /* called by the calendar subsystem to set a new UT date.
  283.  * newmjd is the new UT date/time as a modifed Julian date.
  284.  */
  285. void
  286. mm_newcaldate (newmjd)
  287. double newmjd;
  288. {
  289.     mjd = newmjd;
  290.     set_t0 (&now);
  291.     mm_now (1);
  292.     mm_newcir(1);
  293.     newcir = 1;
  294. }
  295.  
  296. /* called by other menus as they want to hear from our buttons or not.
  297.  * the "on"s and "off"s stack - only really redo the buttons if it's the
  298.  * first on or the last off.
  299.  */
  300. void
  301. mm_selection_mode (whether)
  302. int whether;    /* whether setting up for plotting or for not plotting */
  303. {
  304.     mm_selecting += whether ? 1 : -1;
  305.  
  306.     if (whether && mm_selecting == 1     /* first one to want on */
  307.         || !whether && mm_selecting == 0 /* last one to want off */)
  308.         mm_set_buttons (whether);
  309. }
  310.  
  311. /* a way for anyone to know what now is */
  312. Now *
  313. mm_get_now()
  314. {
  315.     return (&now);
  316. }
  317.  
  318. /* draw all the stuff on the managed menus.
  319.  * if how_much == 0 then just update fields that need it;
  320.  * if how_much == 1 then redraw all fields;
  321.  */
  322. void
  323. redraw_screen (how_much)
  324. int how_much;
  325. {
  326.     watch_cursor(1);
  327.  
  328.     /* invalidate any cached values in the database */
  329.     db_invalidate();
  330.  
  331.     /* print the single-step message if this is the last loop */
  332.     if (nstep < 1)
  333.         print_updating();
  334.  
  335.     /* if just updating changed fields while plotting or listing
  336.      * unattended then suppress most screen updates except
  337.      * always show nstep to show plot loops to go and
  338.      * always show tminc to show search convergence progress.
  339.      */
  340.     print_nstep(how_much);
  341.     print_tminc(how_much);
  342.     print_spause(how_much);
  343.     if (how_much == 0 && nstep > 0 && spause == 0)
  344.         f_off();
  345.  
  346.     /* print all the time-related fields */
  347.     mm_now (how_much);
  348.  
  349.     mm_twilight (how_much);
  350.  
  351.     /* print stuff on other menus */
  352.     all_update(&now, how_much);
  353.  
  354.     f_on();
  355.  
  356.     watch_cursor(0);
  357. }
  358.  
  359. static void
  360. create_main_form(main_window)
  361. Widget main_window;
  362. {
  363.     static int fmi[4] = {0, 8, 16, NFM};
  364.     XmString str;
  365.     Widget mrc_w, hrc_w, rc_w;
  366.     Widget sep_w;
  367.     Widget w;
  368.     Arg args[20];
  369.     int i, n;
  370.  
  371.     /* create the main vertical r/c */
  372.     n = 0;
  373.     XtSetArg (args[n], XmNisAligned, False); n++;
  374.     mrc_w = XmCreateRowColumn (main_window, "MainRC", args, n);
  375.  
  376.     /* make the status label */
  377.     n = 0;
  378.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  379.     XtSetArg (args[n], XmNrecomputeSize, False); n++;
  380.     status_w = XmCreateLabel (mrc_w, "Status", args, n);
  381.     XtManageChild (status_w);
  382.  
  383.     /* make a separator widget */
  384.     n = 0;
  385.     sep_w = XmCreateSeparator (mrc_w, "HSep2", args, n);
  386.     XtManageChild (sep_w);
  387.  
  388.     /* make the "NEW CIRCUMSTANCES" label */
  389.     n = 0;
  390.     XtSetArg (args[n], XmNrecomputeSize, False); n++;
  391.     newcir_w = XmCreateLabel (mrc_w, "NewCir", args, n);
  392.     XtManageChild(newcir_w);
  393.  
  394.     /* make a separator widget */
  395.     n = 0;
  396.     sep_w = XmCreateSeparator (mrc_w, "HSep3", args, n);
  397.     XtManageChild (sep_w);
  398.  
  399.     /* make a horizontal r/c across the bottom.
  400.      * fill it in with three vertical r/cs and the calendar, with
  401.      * separators.
  402.      */
  403.  
  404.     n = 0;
  405.     XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
  406.     hrc_w = XmCreateRowColumn (mrc_w, "BottomRC", args, n);
  407.     XtManageChild (hrc_w);
  408.  
  409.     for (i = 0; i < 3; i++) {
  410.         int f;
  411.  
  412.         n = 0;
  413.         rc_w = XmCreateRowColumn (hrc_w, "MainRC", args, n);
  414.         XtManageChild (rc_w);
  415.  
  416.         for (f = fmi[i]; f < fmi[i+1]; f++) {
  417.         Field *fp = &mm_field_map[f];
  418.         Widget f_w;
  419.  
  420.         switch (fp->id) {
  421.         case GAP: /* make a gap label */
  422.             n = 0;
  423.             w = XmCreateSeparator (rc_w, "GapSep", args, n);
  424.             XtManageChild (w);
  425.             n = 0;
  426.             fp->pb_w = XmCreatePushButton (rc_w, "Gap", args, n);
  427.             XtManageChild (fp->pb_w);
  428.             set_xmstring (fp->pb_w, XmNlabelString, " ");
  429.             continue;
  430.         }
  431.  
  432.         /* make a form */
  433.         n = 0;
  434.         f_w = XmCreateForm (rc_w, "MainF", args, n);
  435.         XtManageChild (f_w);
  436.  
  437.         /* make the pushbutton in the right half. */
  438.         n = 0;
  439.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  440.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  441.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  442.         XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  443.         if (fp->name)
  444.             XtSetArg (args[n], XmNuserData, fp->name); n++;
  445.         fp->pb_w = XmCreatePushButton (f_w, "MainPB", args, n);
  446.         if (fp->prompt || fp->name)
  447.             XtAddCallback (fp->pb_w, XmNactivateCallback,
  448.                             mm_activate_cb, fp);
  449.         XtManageChild(fp->pb_w);
  450.  
  451.         /* make the label in the left half */
  452.         n = 0;
  453.         str = XmStringCreateLtoR(fp->label, XmSTRING_DEFAULT_CHARSET);
  454.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  455.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  456.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  457.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  458.         XtSetArg (args[n], XmNrightWidget, fp->pb_w); n++;
  459.         XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  460.         XtSetArg (args[n], XmNlabelString, str); n++;
  461.         w = XmCreateLabel (f_w, "MainLabel", args, n);
  462.         XtManageChild(w);
  463.         XmStringFree (str);
  464.         }
  465.  
  466.         /* make a separator widget */
  467.         n = 0;
  468.         XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
  469.         sep_w = XmCreateSeparator (hrc_w, "VSep", args, n);
  470.         XtManageChild (sep_w);
  471.     }
  472.  
  473.     /* make the calendar */
  474.  
  475.     w = calm_create (hrc_w);
  476.     XtManageChild (w);
  477.  
  478.     /* make a separator widget */
  479.     n = 0;
  480.     sep_w = XmCreateSeparator (mrc_w, "HSep4", args, n);
  481.     XtManageChild (sep_w);
  482.  
  483.     /* put a wide and thick "go" button below all */
  484.     n = 0;
  485.     XtSetArg (args[n], XmNshowAsDefault, True); n++;
  486.     XtSetArg (args[n], XmNrecomputeSize, False); n++;
  487.     XtSetArg (args[n], XmNmarginTop, 3); n++;
  488.     XtSetArg (args[n], XmNmarginBottom, 3); n++;
  489.     go_w = XmCreatePushButton (mrc_w, "Update", args, n);
  490.     XtAddCallback (go_w, XmNactivateCallback, mm_go_cb, 0);
  491.     XtManageChild (go_w);
  492.  
  493.     XtManageChild (mrc_w);
  494. }
  495.  
  496. /* set the initial stuff in the Now struct and looping params from the XEphem
  497.  * resources.
  498.  */
  499. static void
  500. read_default_resources()
  501. {
  502.     int i;
  503.  
  504.     for (i = 0; i < XtNumber(keywords); i++) {
  505.         char *dp = XGetDefault (XtD, myclass, keywords[i]);
  506.         if (dp) {
  507.         char buf[128];
  508.         (void) sprintf (buf, "%s=%s", keywords[i], dp);
  509.         if (crack_fieldset (buf) < 0) {
  510.             printf ("Bad resource spec: %s", buf);
  511.             exit (1);
  512.         }
  513.         }
  514.     }
  515. }
  516.  
  517. /* get the widget associated with this _FID.
  518.  * We do some error checking.
  519.  */
  520. static Widget
  521. fw(fid)
  522. int fid;
  523. {
  524.     Field *fp;
  525.  
  526.     if (fid < 0 || fid >= NFM || (fp = &mm_field_map[fid])->id != fid) {
  527.         printf ("mainmenu:fw(): bad field id: %d\n", fid);
  528.         exit(1);
  529.     }
  530.     return (fp->pb_w);
  531. }
  532.  
  533. /* go through all the buttons just pickable for plotting and set whether they
  534.  * should appear to look like buttons or just flat labels.
  535.  */
  536. static void
  537. mm_set_buttons (whether)
  538. int whether;
  539. {
  540.     static Arg look_like_button[] = {
  541.         {XmNtopShadowColor, (XtArgVal) 0},
  542.         {XmNbottomShadowColor, (XtArgVal) 0},
  543.         {XmNfillOnArm, (XtArgVal) True},
  544.     };
  545.     static Arg look_like_label[] = {
  546.         {XmNtopShadowColor, (XtArgVal) 0},
  547.         {XmNbottomShadowColor, (XtArgVal) 0},
  548.         {XmNfillOnArm, (XtArgVal) False},
  549.     };
  550.     static int called;
  551.     Field *fp;
  552.  
  553.     if (!called) {
  554.         /* get baseline label and shadow appearances.
  555.          * arbitrarily get these from the go_w button.
  556.          */
  557.         Pixel topshad, botshad, bgcol;
  558.         Arg args[20];
  559.         int n;
  560.  
  561.         n = 0;
  562.         XtSetArg (args[n], XmNtopShadowColor, &topshad); n++;
  563.         XtSetArg (args[n], XmNbottomShadowColor, &botshad); n++;
  564.         XtSetArg (args[n], XmNbackground, &bgcol); n++;
  565.         XtGetValues (go_w, args, n);
  566.  
  567.         look_like_button[0].value = topshad;
  568.         look_like_button[1].value = botshad;
  569.         look_like_label[0].value = bgcol;
  570.         look_like_label[1].value = bgcol;
  571.  
  572.         called = 1;
  573.     }
  574.  
  575.     for (fp = mm_field_map; fp < LFM; fp++)
  576.         if (whether) {
  577.           if (fp->name)
  578.             XtSetValues(fp->pb_w, look_like_button,
  579.                             XtNumber(look_like_button));
  580.           else
  581.             XtSetValues(fp->pb_w, look_like_label,
  582.                             XtNumber(look_like_label));
  583.         } else {
  584.           if (fp->prompt)
  585.             XtSetValues(fp->pb_w, look_like_button,
  586.                             XtNumber(look_like_button));
  587.           else
  588.             XtSetValues(fp->pb_w, look_like_label,
  589.                             XtNumber(look_like_label));
  590.         }
  591. }
  592.  
  593. /* callback from any of the main menu buttons being activated.
  594.  * if we are currently selecting fields to plot and the field has a name
  595.  *   then inform all the potentially interested parties;
  596.  * else if the field has a prompt then ask the user for a new value.
  597.  */
  598. /* ARGSUSED */
  599. static void
  600. mm_activate_cb (w, client, call)
  601. Widget w;
  602. XtPointer client;
  603. XtPointer call;
  604. {
  605.     Field *fp = (Field *)client;
  606.  
  607.     if (mm_selecting) {
  608.         if (fp->name)
  609.         register_selection (fp->name);
  610.     } else {
  611.         if (fp->prompt) {
  612.         mm_set_pref_prompts (fp);
  613.         prompt (fp);
  614.         }
  615.     }
  616. }
  617.  
  618. /* set up those prompts that depend in preferences.
  619.  */
  620. static void
  621. mm_set_pref_prompts(fp)
  622. Field *fp;
  623. {
  624.     switch (fp->id) {
  625.     case UD_FID:
  626.     case LD_FID:
  627.         fp->prompt = fp->altp[pref_get(PREF_DATE_FORMAT)];
  628.         break;
  629.     case ELEV_FID:
  630.     case TEMP_FID:
  631.     case PRES_FID:
  632.         fp->prompt = fp->altp[pref_get(PREF_UNITS)];
  633.         break;
  634.     }
  635. }
  636.  
  637. /* function called from the interval timer used to implement the
  638.  * auto repeat feature.
  639.  */
  640. /* ARGSUSED */
  641. static void
  642. mm_timer_cb (client, id)
  643. XtPointer client;
  644. XtIntervalId *id;
  645. {
  646.     int waited_so_far = (int)client + 1;
  647.  
  648.     mm_interval_id = 0;
  649.  
  650.     if (waited_so_far < spause)
  651.         mm_interval_id = XtAppAddTimeOut (xe_app, 1000, mm_timer_cb,
  652.                             (XtPointer)waited_so_far);
  653.     else
  654.         mm_go();
  655. }
  656.  
  657. /* callback from the main "go" button being armed.
  658.  * if we are looping (as evidenced by an active timer) then stop, else go.
  659.  */
  660. /* ARGSUSED */
  661. static void
  662. mm_go_cb (w, client, call)
  663. Widget w;
  664. XtPointer client;
  665. XtPointer call;
  666. {
  667.     if (mm_interval_id != 0) {
  668.         XtRemoveTimeOut (mm_interval_id);
  669.         mm_interval_id = 0;
  670.         redraw_screen (1);
  671.         print_idle();
  672.     } else {
  673.         if (nstep > 1)
  674.         print_running();
  675.         mm_go();
  676.     }
  677. }
  678.  
  679. /* increment, update all fields, and go again if more steps.
  680.  */
  681. static void
  682. mm_go()
  683. {
  684.     int srchdone;
  685.  
  686.     /* increment time only if op didn't change cirumstances */
  687.     if (!newcir)
  688.         inc_mjd (&now, tminc);
  689.  
  690.     nstep -= 1;
  691.  
  692.     /* recalculate everything and update all the fields */
  693.     redraw_screen(newcir);
  694.     mm_newcir(0);
  695.  
  696.     /* let searching functions change tminc and check for done */
  697.     srchdone = srch_eval (mjd, &tminc) < 0;
  698.     print_tminc(0); /* to show possibly new search increment */
  699.  
  700.     /* update plot and listing files, now that all fields are up
  701.      * to date and search function has been evaluated.
  702.      */
  703.     plot();
  704.     listing();
  705.  
  706.     /* stop loop to allow op to change parameters:
  707.      * if a search evaluation converges (or errors out),
  708.      * or if steps are done,
  709.      * or if op hits any key.
  710.      */
  711.     newcir = 0;
  712.     if (srchdone || nstep <= 0) {
  713.  
  714.         /* update screen with the current stuff if stopped during
  715.          * searching, unattended plotting or listing since last
  716.          * redraw_screen() didn't.
  717.          */
  718.         if ((srchdone || plot_ison() || listing_ison()) && nstep > 0)
  719.         redraw_screen (1);
  720.  
  721.         /* return nstep to default of 1 */
  722.         if (nstep <= 0) {
  723.         nstep = 1;
  724.         print_nstep (0);
  725.         }
  726.         print_idle();
  727.     } else {
  728.         mm_interval_id =
  729.         XtAppAddTimeOut (xe_app, spause>0 ? 1000 : 120, mm_timer_cb, 0);
  730.     }
  731. }
  732.  
  733. static void
  734. print_tminc(force)
  735. int force;
  736. {
  737.     static double last = -123.456;    /* anything unlikely */
  738.  
  739.     if (force || tminc != last) {
  740.         if (tminc == RTC)
  741.         f_string (fw(STPSZ_FID), " RT CLOCK");
  742.         else if (fabs(tminc) >= 24.0)
  743.         f_double (fw(STPSZ_FID), "%6.4g dy", tminc/24.0);
  744.         else
  745.         f_signtime (fw(STPSZ_FID), tminc);
  746.         last = tminc;
  747.     }
  748. }
  749.  
  750. static void
  751. print_updating()
  752. {
  753.     print_status ("Updating...");
  754. }
  755.  
  756. static void
  757. print_idle()
  758. {
  759.     print_status ("Make changes as desired or select Update to run.");
  760.     f_string (go_w, "Update");
  761. }
  762.  
  763. static void
  764. print_running()
  765. {
  766.     print_status ("Running... select Stop to stop.");
  767.     f_string (go_w, "Stop");
  768. }
  769.  
  770. static void
  771. print_status (s)
  772. char *s;
  773. {
  774.     static char *last_s;
  775.  
  776.     if (s != last_s) {
  777.         f_string (status_w, s);
  778.         XFlush (XtD);
  779.         last_s = s;
  780.     }
  781. }
  782.  
  783. static void
  784. print_nstep(force)
  785. int force;
  786. {
  787.     static int last;
  788.  
  789.     if (force || nstep != last) {
  790.         char buf[16];
  791.         (void) sprintf (buf, "%8d", nstep);
  792.         f_string (fw(NSTEP_FID), buf);
  793.         last = nstep;
  794.     }
  795. }
  796.  
  797. static void
  798. print_spause(force)
  799. int force;
  800. {
  801.     static int last;
  802.  
  803.     if (force || spause != last) {
  804.         char buf[16];
  805.         (void) sprintf (buf, "%8d", spause);
  806.         f_string (fw(PAUSE_FID), buf);
  807.         last = spause;
  808.     }
  809. }
  810.  
  811. /* process a field spec in buf, either from config file or argv.
  812.  * return 0 if recognized ok, else -1.
  813.  */
  814. static
  815. crack_fieldset (buf)
  816. char *buf;
  817. {
  818.     int i;
  819.  
  820.     for (i = 0; i < XtNumber(keywords); i++) {
  821.         int l = strlen(keywords[i]);
  822.         if (strncmp (buf, keywords[i], l) == 0) {
  823.         buf += l+1;    /* skip keyword and its subsequent delimiter */
  824.         break;
  825.         }
  826.     }
  827.  
  828.     /* N.B. the switch entries must match the order in keywords[] */
  829.     switch (i) {
  830.     case 0:  (void) chg_fld (buf, &mm_field_map[EPOCH_FID]); break;
  831.     case 1:  (void) chg_fld (buf, &mm_field_map[ELEV_FID]); break;
  832.     case 2:  (void) chg_fld (buf, &mm_field_map[JD_FID]); break;
  833.     case 3:  (void) chg_fld (buf, &mm_field_map[LAT_FID]); break;
  834.     case 4:  (void) chg_fld (buf, &mm_field_map[LONG_FID]); break;
  835.     case 5:  (void) chg_fld (buf, &mm_field_map[NSTEP_FID]); break;
  836.     case 6:  (void) chg_fld (buf, &mm_field_map[PAUSE_FID]); break;
  837.     case 7:  (void) chg_fld (buf, &mm_field_map[PRES_FID]); break;
  838.     case 8:  (void) chg_fld (buf, &mm_field_map[STPSZ_FID]); break;
  839.     case 9:  (void) chg_fld (buf, &mm_field_map[TEMP_FID]); break;
  840.     case 10: (void) chg_fld (buf, &mm_field_map[TZN_FID]); break;
  841.     case 11: (void) chg_fld (buf, &mm_field_map[TZONE_FID]); break;
  842.     case 12: (void) chg_fld (buf, &mm_field_map[UD_FID]); break;
  843.     case 13: (void) chg_fld (buf, &mm_field_map[UT_FID]); break;
  844.     case 14: (void) chg_fld (buf, &mm_field_map[DIP_FID]); break;
  845.     case 15: (void) chg_fld (buf, &mm_field_map[LD_FID]); break;
  846.     case 16: (void) chg_fld (buf, &mm_field_map[LT_FID]); break;
  847.     case 17: (void) chg_fld (buf, &mm_field_map[LST_FID]); break;
  848.     default: return (-1);
  849.     }
  850.     return (0);
  851. }
  852.  
  853. /* react to the field at *fp according to the string input at bp.
  854.  * crack the buffer and update the corresponding (global) variable(s)
  855.  * or do whatever a pick at that field should do.
  856.  * return 1 if we change a field that invalidates any of the times or
  857.  * to update all related fields.
  858.  */
  859. static
  860. chg_fld (bp, fp)
  861. char *bp;
  862. Field *fp;
  863. {
  864.     int deghrs = 0, mins = 0, secs = 0;
  865.     int new = 0;
  866.     double tmp;
  867.  
  868.     switch (fp->id) {
  869.     case JD_FID:
  870.         if (bp[0] == 'n' || bp[0] == 'N')
  871.         time_fromsys (&now);
  872.         else
  873.         mjd = atof(bp) - MJD0;
  874.         set_t0 (&now);
  875.         new = 1;
  876.         break;
  877.     case UD_FID:
  878.         if (bp[0] == 'n' || bp[0] == 'N')
  879.         time_fromsys (&now);
  880.         else {
  881.         double day, newmjd0;
  882.         int month, year;
  883.  
  884.         mjd_cal (mjd, &month, &day, &year); /* init with now */
  885.         f_sscandate (bp, pref_get(PREF_DATE_FORMAT),
  886.                             &month, &day, &year);
  887.         cal_mjd (month, day, year, &newmjd0);
  888.  
  889.         /* if don't give a fractional part to days
  890.          * then retain current hours.
  891.          */
  892.         if ((long)day == day)
  893.             mjd = newmjd0 + mjd_hr(mjd)/24.0;
  894.         else
  895.             mjd = newmjd0;
  896.         }
  897.         set_t0 (&now);
  898.         new = 1;
  899.         break;
  900.     case UT_FID:
  901.         if (bp[0] == 'n' || bp[0] == 'N')
  902.         time_fromsys (&now);
  903.         else {
  904.         double newutc = (mjd-mjd_day(mjd)) * 24.0;
  905.         f_dec_sexsign (newutc, °hrs, &mins, &secs);
  906.         f_sscansex (bp, °hrs, &mins, &secs);
  907.         sex_dec (deghrs, mins, secs, &newutc);
  908.         mjd = mjd_day(mjd) + newutc/24.0;
  909.         }
  910.         set_t0 (&now);
  911.         new = 1;
  912.         break;
  913.     case LD_FID:
  914.         if (bp[0] == 'n' || bp[0] == 'N')
  915.         time_fromsys (&now);
  916.         else {
  917.         double day, newlmjd0;
  918.         int month, year;
  919.  
  920.         mjd_cal (mjd-tz/24.0, &month, &day, &year); /* now */
  921.         f_sscandate (bp, pref_get(PREF_DATE_FORMAT),
  922.                             &month, &day, &year);
  923.         cal_mjd (month, day, year, &newlmjd0);
  924.  
  925.         /* if don't give a fractional part to days
  926.          * then retain current hours.
  927.          */
  928.         if ((long)day == day)
  929.             mjd = newlmjd0 + mjd_hr(mjd-tz/24.0)/24.0;
  930.         else
  931.             mjd = newlmjd0;
  932.         mjd += tz/24.0;
  933.         }
  934.         set_t0 (&now);
  935.         new = 1;
  936.         break;
  937.     case LT_FID:
  938.         if (bp[0] == 'n' || bp[0] == 'N')
  939.         time_fromsys (&now);
  940.         else {
  941.         double newlt = (mjd-mjd_day(mjd)) * 24.0 - tz;
  942.         range (&newlt, 24.0);
  943.         f_dec_sexsign (newlt, °hrs, &mins, &secs);
  944.         f_sscansex (bp, °hrs, &mins, &secs);
  945.         sex_dec (deghrs, mins, secs, &newlt);
  946.         mjd = mjd_day(mjd-tz/24.0) + (newlt + tz)/24.0;
  947.         }
  948.         set_t0 (&now);
  949.         new = 1;
  950.         break;
  951.     case LST_FID:
  952.         if (bp[0] == 'n' || bp[0] == 'N')
  953.         time_fromsys (&now);
  954.         else {
  955.         double lst, utc;
  956.         now_lst (&now, &lst);
  957.         f_dec_sexsign (lst, °hrs, &mins, &secs);
  958.         f_sscansex (bp, °hrs, &mins, &secs);
  959.         sex_dec (deghrs, mins, secs, &lst);
  960.         lst -= radhr(lng); /* convert to gst */
  961.         range (&lst, 24.0);
  962.         gst_utc (mjd_day(mjd), lst, &utc);
  963.         mjd = mjd_day(mjd) + utc/24.0;
  964.         }
  965.         set_t0 (&now);
  966.         new = 1;
  967.         break;
  968.     case TZN_FID:
  969.         (void) strncpy (tznm, bp, sizeof(tznm)-1);
  970.         new = 1;
  971.         break;
  972.     case TZONE_FID:
  973.         f_dec_sexsign (tz, °hrs, &mins, &secs);
  974.         f_sscansex (bp, °hrs, &mins, &secs);
  975.         sex_dec (deghrs, mins, secs, &tz);
  976.         new = 1;
  977.         break;
  978.     case LONG_FID:
  979.         f_dec_sexsign (-raddeg(lng), °hrs, &mins, &secs);
  980.         f_sscansex (bp, °hrs, &mins, &secs);
  981.         sex_dec (deghrs, mins, secs, &lng);
  982.         lng = degrad (-lng);         /* want - radians west */
  983.         new = 1;
  984.         break;
  985.     case LAT_FID:
  986.         f_dec_sexsign (raddeg(lat), °hrs, &mins, &secs);
  987.         f_sscansex (bp, °hrs, &mins, &secs);
  988.         sex_dec (deghrs, mins, secs, &lat);
  989.         lat = degrad (lat);
  990.         new = 1;
  991.         break;
  992.     case ELEV_FID:
  993.         if (sscanf (bp, "%lf", &elev) == 1) {
  994.         if (pref_get(PREF_UNITS) == PREF_ENGLISH)
  995.             elev /= (ERAD*FTPM);    /* ft to earth radii */
  996.         else
  997.             elev /= ERAD;        /* m to earth radii */
  998.         new = 1;
  999.         }
  1000.         break;
  1001.     case DIP_FID:
  1002.         if (sscanf (bp, "%lf", &tmp) == 1) {
  1003.         if (tmp < 0)
  1004.             xe_msg ("Twilight dip must be at least 0", 1);
  1005.         else {
  1006.             dip = degrad(tmp);
  1007.             mm_twilight (1);
  1008.         }
  1009.         }
  1010.         break;
  1011.     case NSTEP_FID:
  1012.         (void) sscanf (bp, "%d", &nstep);
  1013.         print_nstep (0);
  1014.         break;
  1015.     case PAUSE_FID:
  1016.         (void) sscanf (bp, "%d", &spause);
  1017.         print_spause (0);
  1018.         break;
  1019.     case TEMP_FID:
  1020.         if (sscanf (bp, "%lf", &temp) == 1) {
  1021.         if (pref_get(PREF_UNITS) == PREF_ENGLISH)
  1022.             temp = 5./9.*(temp - 32.0);    /* want degs C */
  1023.         new = 1;
  1024.         }
  1025.         break;
  1026.     case PRES_FID:
  1027.         if (sscanf (bp, "%lf", &pressure) == 1) {
  1028.         if (pref_get(PREF_UNITS) == PREF_ENGLISH)
  1029.             pressure *= 33.86;        /* want mBar */
  1030.         new = 1;
  1031.         }
  1032.         break;
  1033.     case EPOCH_FID:
  1034.         if (bp[0] == 'e' || bp[0] == 'E')
  1035.         epoch = EOD;
  1036.         else {
  1037.         double e;
  1038.         e = atof(bp);
  1039.         year_mjd (e, &epoch);
  1040.         }
  1041.         new = 1;
  1042.         break;
  1043.     case STPSZ_FID:
  1044.         if (bp[0] == 'r' || bp[0] == 'R')
  1045.         tminc = RTC;
  1046.         else {
  1047.         char lastc = bp[strlen(bp)-1];
  1048.         if (lastc == 'd' || lastc == 'D') {
  1049.             /* ends in d so treat as a number of days */
  1050.             double x;
  1051.             if (sscanf (bp, "%lf", &x) == 1)
  1052.             tminc = x * 24.0;
  1053.         } else if (lastc == 's' || lastc == 'S') {
  1054.             /* ends in s so treat as a number of sidereal days */
  1055.             double x;
  1056.             if (sscanf (bp, "%lf", &x) == 1)
  1057.             tminc = x * 24.0 * SIDRATE;
  1058.         } else {
  1059.             if (tminc == RTC)
  1060.             deghrs = mins = secs = 0;
  1061.             else
  1062.             f_dec_sexsign (tminc, °hrs, &mins, &secs);
  1063.             f_sscansex (bp, °hrs, &mins, &secs);
  1064.             sex_dec (deghrs, mins, secs, &tminc);
  1065.         }
  1066.         }
  1067.         print_tminc(0);
  1068.         set_t0 (&now);
  1069.         break;
  1070.     default:
  1071.         printf ("chg_fld: unknown id: 0x%x\n", fp->id);
  1072.         exit (1);
  1073.     }
  1074.  
  1075.     return (new);
  1076. }
  1077.  
  1078. /* user typed OK to a prompt for fp. get his new value and use it */
  1079. static void
  1080. prompt_ok_cb (w, client, call)
  1081. Widget w;
  1082. XtPointer client;
  1083. XtPointer call;
  1084. {
  1085.     XmSelectionBoxCallbackStruct *s = (XmSelectionBoxCallbackStruct *)call;
  1086.     Field *fp = (Field *)client;
  1087.     char *text, *tmptext;
  1088.     
  1089.     switch (s->reason) {
  1090.     case XmCR_OK:
  1091.         get_xmstring(w, XmNtextString, &text);
  1092.         break;
  1093.     case XmCR_APPLY:    /* used for several special short cuts */
  1094.         switch (fp->id) {
  1095.         case STPSZ_FID:
  1096.         tmptext = "r";    /* command to mean "RTC" */
  1097.         break;
  1098.         case EPOCH_FID:
  1099.         tmptext = "e";    /* command to mean "EOD" */
  1100.         break;
  1101.         case NSTEP_FID:
  1102.         tmptext = "99999999";    /* command to mean "Many steps" */
  1103.         break;
  1104.         case PAUSE_FID:
  1105.         tmptext = "0";    /* command to mean "no pause" */
  1106.         break;
  1107.         case PRES_FID:
  1108.         tmptext = "0";    /* command to mean "no refraction" */
  1109.         break;
  1110.         case UD_FID:
  1111.         case JD_FID:
  1112.         case LST_FID:
  1113.         case LD_FID:
  1114.         case LT_FID:
  1115.         tmptext = "n";    /* command to mean "Now" */
  1116.         break;
  1117.         case UT_FID:
  1118.         tmptext = "0:00:00";    /* command to mean midnight */
  1119.         break;
  1120.         default:
  1121.         printf ("mainmenu:prompt_ok_cb: bad fid=%d\n", fp->id);
  1122.         exit (1);
  1123.         break;
  1124.         }
  1125.         (void) strcpy (text = XtMalloc(strlen(tmptext)+1), tmptext);
  1126.         break;
  1127.     default:
  1128.         return;
  1129.     }
  1130.  
  1131.     if (chg_fld (text, fp)) {
  1132.         mm_now (1);
  1133.         mm_newcir(1);
  1134.         newcir = 1;
  1135.     }
  1136.     XtDestroyWidget (w);
  1137.     XtFree (text);
  1138. }
  1139.  
  1140. /* put up a prompt dialog near the cursor to ask about fp.
  1141.  * use the Apply button for special shortcuts.
  1142.  */
  1143. static void
  1144. prompt (fp)
  1145. Field *fp;
  1146. {
  1147.     Widget w, sw, hw, aw;
  1148.     XmString str, title;
  1149.     Arg args[20];
  1150.     int n;
  1151.     
  1152.     str = XmStringCreateLtoR (fp->prompt, XmSTRING_DEFAULT_CHARSET);
  1153.     title = XmStringCreateLtoR ("xephem Prompt", XmSTRING_DEFAULT_CHARSET);
  1154.     n = 0;
  1155.     XtSetArg(args[n], XmNselectionLabelString, str);  n++;
  1156.     XtSetArg(args[n], XmNdefaultPosition, False);  n++;
  1157.     XtSetArg(args[n], XmNdialogTitle, title);  n++;
  1158.     XtSetArg(args[n], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL);  n++;
  1159.     sw = XmCreatePromptDialog(toplevel_w, "MainPrompt", args, n);
  1160.     XtAddCallback (sw, XmNmapCallback, prompt_map_cb, NULL);
  1161.     XtAddCallback (sw, XmNokCallback, prompt_ok_cb, fp);
  1162.     XmStringFree (str);
  1163.     XmStringFree (title);
  1164.  
  1165.     /* we don't use the Help button at all. */
  1166.     hw = XmSelectionBoxGetChild (sw, XmDIALOG_HELP_BUTTON);
  1167.     XtUnmanageChild (hw);
  1168.  
  1169.     /* we don't use the Apply button except for the special shortcuts */
  1170.     aw = XmSelectionBoxGetChild (sw, XmDIALOG_APPLY_BUTTON);
  1171.     XtUnmanageChild (aw);
  1172.  
  1173.     /* use the Apply button for several special shortcuts */
  1174.     switch (fp->id) {
  1175.     case JD_FID: case UD_FID:
  1176.     case LD_FID: case LT_FID: case LST_FID:
  1177.         XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1178.         XtManageChild (aw);
  1179.         set_xmstring (sw, XmNapplyLabelString, "Now");
  1180.         break;
  1181.     case UT_FID:
  1182.         XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1183.         XtManageChild (aw);
  1184.         set_xmstring (sw, XmNapplyLabelString, "0:00:00");
  1185.         break;
  1186.     case STPSZ_FID:
  1187.         XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1188.         XtManageChild (aw);
  1189.         set_xmstring (sw, XmNapplyLabelString, "RTC");
  1190.         break;
  1191.     case EPOCH_FID:
  1192.         XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1193.         XtManageChild (aw);
  1194.         set_xmstring (sw, XmNapplyLabelString, "Of Date");
  1195.         break;
  1196.     case NSTEP_FID:
  1197.         XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1198.         XtManageChild (aw);
  1199.         set_xmstring (sw, XmNapplyLabelString, "Many");
  1200.         break;
  1201.     case PAUSE_FID:
  1202.         XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1203.         XtManageChild (aw);
  1204.         set_xmstring (sw, XmNapplyLabelString, "No Pause");
  1205.         break;
  1206.     case PRES_FID:
  1207.         XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1208.         XtManageChild (aw);
  1209.         set_xmstring (sw, XmNapplyLabelString, "No Refraction");
  1210.         break;
  1211.     }
  1212.  
  1213.     XtManageChild (sw);
  1214.  
  1215. #if XmVersion >= 1001
  1216.     w = XmSelectionBoxGetChild (sw, XmDIALOG_TEXT);
  1217.     XmProcessTraversal (w, XmTRAVERSE_CURRENT);
  1218.     XmProcessTraversal (w, XmTRAVERSE_CURRENT); /* yes, twice!! */
  1219. #endif
  1220. }
  1221.  
  1222. /* print all the time/date/where related stuff: the Now structure.
  1223.  * print in a nice order, based on the field locations, as much as possible.
  1224.  */
  1225. static void
  1226. mm_now (all)
  1227. int all;
  1228. {
  1229.     char buf[32];
  1230.     double lmjd = mjd - tz/24.0;
  1231.     double jd = mjd + MJD0;
  1232.     double tmp;
  1233.  
  1234.     (void) sprintf (buf, "%-3.3s", tznm);
  1235.     f_string (fw(TZN_FID), buf);
  1236.     f_time (fw(LT_FID), mjd_hr(lmjd));
  1237.     f_date (fw(LD_FID), lmjd);
  1238.  
  1239.     f_time (fw(UT_FID), mjd_hr(mjd));
  1240.     f_date (fw(UD_FID), mjd);
  1241.  
  1242.     f_double (fw(JD_FID), "%14.5f", jd);
  1243.  
  1244.     now_lst (&now, &tmp);
  1245.     f_time (fw(LST_FID), tmp);
  1246.  
  1247.     if (all) {
  1248.         f_gangle (fw(LAT_FID), lat);
  1249.         f_gangle (fw(LONG_FID), -lng);    /* + west */
  1250.  
  1251.         if (pref_get(PREF_UNITS) == PREF_ENGLISH) {
  1252.         tmp = elev * (ERAD*FTPM);    /* want ft, not earth radii*/
  1253.         f_double (fw(ELEV_FID), "%8.1f ft", tmp);
  1254.         } else {
  1255.         tmp = elev * ERAD;        /* want m, not earth radii */
  1256.         f_double (fw(ELEV_FID), "%8.1f m", tmp);
  1257.         }
  1258.  
  1259.         tmp = temp;
  1260.         if (pref_get(PREF_UNITS) == PREF_ENGLISH) {
  1261.         tmp = 9.*temp/5. + 32.0;   /* want to see degrees F, not C */
  1262. #ifdef XK_degree
  1263.         (void) sprintf (buf, "%%5.1f %cF", XK_degree);
  1264.         } else
  1265.         (void) sprintf (buf, "%%5.1f %cC", XK_degree);
  1266. #else
  1267.         (void) sprintf (buf, "%%5.1f F");
  1268.         } else
  1269.         (void) sprintf (buf, "%%5.1f C");
  1270. #endif
  1271.         f_double (fw(TEMP_FID), buf, tmp);
  1272.  
  1273.         tmp = pressure;
  1274.         if (pref_get(PREF_UNITS) == PREF_ENGLISH) {
  1275.         tmp /= 33.86;    /* want to see in. Hg, not mBar */
  1276.         f_double (fw(PRES_FID), "%5.2f in", tmp);
  1277.         } else {
  1278.         f_double (fw(PRES_FID), "%5.0f mB", tmp);
  1279.         }
  1280.  
  1281.         f_signtime (fw(TZONE_FID), tz);
  1282.  
  1283.         if (epoch == EOD)
  1284.         f_string (fw(EPOCH_FID), "Of Date");
  1285.         else {
  1286.         mjd_year (epoch, &tmp);
  1287.         f_double (fw(EPOCH_FID), "%8.1f", tmp);
  1288.         }
  1289.     }
  1290.  
  1291.     if (f_ison())
  1292.         calm_set (&now);
  1293. }
  1294.  
  1295. /* display dawn/dusk/length-of-night times.
  1296.  */
  1297. /* ARGSUSED */
  1298. static void
  1299. mm_twilight (force)
  1300. int force;
  1301. {
  1302.     double dusk, dawn;
  1303.     int status;
  1304.     char buf[64];
  1305.  
  1306.     twilight_cir (&now, dip, &dawn, &dusk, &status);
  1307.     if (status & (RS_NORISE|RS_RISERR|RS_NOSET|RS_CIRCUMPOLAR|RS_NEVERUP)) {
  1308.         static char nope[] = "-----";
  1309.         f_string (fw(DAWN_FID), nope);
  1310.         f_string (fw(DUSK_FID), nope);
  1311.         f_string (fw(LON_FID), nope);
  1312.     } else {
  1313.         double tmp;
  1314.         f_mtime (fw(DAWN_FID), dawn);
  1315.         f_mtime (fw(DUSK_FID), dusk);
  1316.         tmp = dawn - dusk; range (&tmp, 24.0);
  1317.         f_mtime (fw(LON_FID), tmp);
  1318.     }
  1319. #ifdef XK_degree
  1320.     (void) sprintf (buf, "%%g%c", XK_degree);
  1321. #else
  1322.     (void) sprintf (buf, "%%g degs");
  1323. #endif
  1324.     f_double (fw(DIP_FID), buf, raddeg(dip));
  1325. }
  1326.  
  1327. static void
  1328. mm_newcir (y)
  1329. int y;
  1330. {
  1331.     static char ncmsg[] = "NEW CIRCUMSTANCES";
  1332.     static char nomsg[] = "                 ";
  1333.     static int last_y = -1;
  1334.  
  1335.     if (y != last_y) {
  1336.         f_string (newcir_w, y ? ncmsg : nomsg);
  1337.         last_y = y;
  1338.     }
  1339. }
  1340.