home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part17 / jupmenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-15  |  26.1 KB  |  907 lines

  1. /* code to manage the stuff on the "jupiter" menu.
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <math.h>
  7. #if defined(__STDC__)
  8. #include <stdlib.h>
  9. #endif
  10. #include <X11/Xlib.h>
  11. #include <Xm/Xm.h>
  12. #include <Xm/Form.h>
  13. #include <Xm/Frame.h>
  14. #include <Xm/Label.h>
  15. #include <Xm/PushB.h>
  16. #include <Xm/RowColumn.h>
  17. #include <Xm/DrawingA.h>
  18. #include <Xm/ToggleB.h>
  19. #include <Xm/Scale.h>
  20. #include "astro.h"
  21. #include "circum.h"
  22.  
  23.  
  24. typedef struct {
  25.     double x, y, z;
  26. } MoonData;
  27.  
  28. #if defined(__STDC__) || defined(__cplusplus)
  29. #define P_(s) s
  30. #else
  31. #define P_(s) ()
  32. #endif
  33.  
  34. extern Now *mm_get_now P_((void));
  35. extern int any_ison P_((void));
  36. extern void f_double P_((Widget w, char *fmt, double f));
  37. extern void get_something P_((Widget w, char *resource, char *value));
  38. extern void range P_((double *v, double r));
  39. extern void register_selection P_((char *name));
  40. extern void set_xmstring P_((Widget w, char *resource, char *txt));
  41. extern void timestamp P_((Now *np, Widget w));
  42.  
  43. void jm_manage P_((void));
  44. int jm_ison P_((void));
  45. void jm_selection_mode P_((int whether));
  46. void jm_update P_((Now *np, int how_much));
  47. void jm_cursor P_((Cursor c));
  48. static void jm_create_form_w P_((void));
  49. static void jm_set_buttons P_((int whether));
  50. static void jm_set_a_button P_((Widget pbw, int whether));
  51. static void jm_bigd_cb P_((Widget w, XtPointer client, XtPointer call));
  52. static void jm_tags_cb P_((Widget w, XtPointer client, XtPointer call));
  53. static void jm_scale_cb P_((Widget w, XtPointer client, XtPointer call));
  54. static void jm_activate_cb P_((Widget w, XtPointer client, XtPointer call));
  55. static void jm_close_cb P_((Widget w, XtPointer client, XtPointer call));
  56. static void jm_da_exp_cb P_((Widget w, XtPointer client, XtPointer call));
  57. static void jm_draw_map P_((Widget w, MoonData moons[4], double sIcml, double sIIcml));
  58. static void jupinfo P_((double d, MoonData moons[4], double *sIcml, double *sIIcml));
  59.  
  60. #undef P_
  61.  
  62. extern Widget toplevel_w;
  63. #define    XtD    XtDisplay(toplevel_w)
  64.  
  65. static Widget jupform_w;    /* main form */
  66. static Widget jda_w;        /* drawing area */
  67. static Widget cml_w[2];        /* display widgets for CMLs */
  68. static Widget scale_w;        /* size scale */
  69. static Widget dt_w;        /* date/time stamp widget */
  70. enum {CMLI, CMLII};        /* cml indexes */
  71. #define    NM    4        /* number of moons */
  72. static Widget j_w[NM][3];    /* the data display widgets */
  73. enum {X, Y, Z};            /* j_w column index */
  74. static int jm_selecting;    /* set while our fields are being selected */
  75. static int bigdots;        /* whether we want big dots */
  76. static int j_tags;        /* whether we want tags on the drawing */
  77.  
  78. #define    MAXSCALE    10.0    /* max scale mag factor */
  79.  
  80. static struct MoonNames {
  81.     char *full;
  82.     char *tag;
  83. } mnames[NM] = {
  84.     {"Io", "I"},
  85.     {"Europa", "II"},
  86.     {"Ganymede", "III"},
  87.     {"Callisto", "IV"}
  88. };
  89.  
  90. /* called when the jupiter menu is activated via the main menu pulldown.
  91.  * if never called before, create and manage all the widgets as a child of a
  92.  * form. otherwise, just toggle whether the form is managed.
  93.  */
  94. void
  95. jm_manage ()
  96. {
  97.     if (!jupform_w)
  98.         jm_create_form_w();
  99.     
  100.     if (XtIsManaged(jupform_w))
  101.         XtUnmanageChild (jupform_w);
  102.     else {
  103.         XtManageChild (jupform_w);
  104.         jm_set_buttons(jm_selecting);
  105.     }
  106. }
  107.  
  108. jm_ison()
  109. {
  110.     return (jupform_w && XtIsManaged(jupform_w));
  111. }
  112.  
  113. /* called by other menus as they want to hear from our buttons or not.
  114.  * the "on"s and "off"s stack - only really redo the buttons if it's the
  115.  * first on or the last off.
  116.  */
  117. void
  118. jm_selection_mode (whether)
  119. int whether;    /* whether setting up for plotting or for not plotting */
  120. {
  121.     jm_selecting += whether ? 1 : -1;
  122.  
  123.     if (jupform_w && XtIsManaged(jupform_w))
  124.         if (whether && jm_selecting == 1     /* first one to want on */
  125.         || !whether && jm_selecting == 0 /* last one to want off */)
  126.         jm_set_buttons (whether);
  127. }
  128.  
  129. /* called to recompute and fill in values for the jupiter menu.
  130.  * don't bother if it doesn't exist or is unmanaged now and we are not logging.
  131.  */
  132. void
  133. jm_update (np, how_much)
  134. Now *np;
  135. int how_much;
  136. {
  137.     static char fmt[] = "%7.3f";
  138.     MoonData moons[NM];
  139.     double sIcml, sIIcml;
  140.     int i;
  141.  
  142.     if (!jupform_w)
  143.         return;
  144.     if (!XtIsManaged(jupform_w) && !any_ison() && !how_much)
  145.         return;
  146.  
  147.     /* compute jupiter info.
  148.      */
  149.     jupinfo (mjd, moons, &sIcml, &sIIcml);
  150.  
  151.     f_double (cml_w[CMLI], fmt, sIcml);
  152.     f_double (cml_w[CMLII], fmt, sIIcml);
  153.  
  154.     for (i = 0; i < NM; i++) {
  155.         f_double (j_w[i][X], fmt, moons[i].x);
  156.         f_double (j_w[i][Y], fmt, moons[i].y);
  157.         f_double (j_w[i][Z], fmt, moons[i].z);
  158.     }
  159.  
  160.     if (XtIsManaged(jupform_w)) {
  161.         jm_draw_map (jda_w, moons, sIcml, sIIcml);
  162.         timestamp (np, dt_w);
  163.     }
  164. }
  165.  
  166. /* called to put up or remove the watch cursor.  */
  167. void
  168. jm_cursor (c)
  169. Cursor c;
  170. {
  171.     Window win;
  172.  
  173.     if (jupform_w && (win = XtWindow(jupform_w))) {
  174.         Display *dsp = XtDisplay(jupform_w);
  175.         if (c)
  176.         XDefineCursor (dsp, win, c);
  177.         else
  178.         XUndefineCursor (dsp, win);
  179.     }
  180. }
  181.  
  182. static void
  183. jm_create_form_w()
  184. {
  185.     Widget w;
  186.     Widget frame_w, r_w, title_w, col_w;
  187.     Widget f_w, fr_w;
  188.     XmString str;
  189.     Arg args[20];
  190.     int n;
  191.     int i;
  192.  
  193.     /* create form */
  194.     n = 0;
  195.     XtSetArg (args[n], XmNautoUnmanage, False); n++;
  196.     XtSetArg (args[n], XmNdefaultPosition, False); n++;
  197.     XtSetArg (args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
  198.     jupform_w = XmCreateFormDialog (toplevel_w, "Jupiter", args, n);
  199.  
  200.     /* set some stuff in the parent DialogShell.
  201.      * setting XmNdialogTitle in the Form didn't work..
  202.      */
  203.     n = 0;
  204.     XtSetArg (args[n], XmNtitle, "xephem Jupiter Table"); n++;
  205.     XtSetValues (XtParent(jupform_w), args, n);
  206.  
  207.     /* make top two title rows */
  208.  
  209.     n = 0;
  210.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  211.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  212.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  213.     r_w = XmCreateLabel (jupform_w, "Heading", args, n);
  214.     XtManageChild (r_w);
  215.     set_xmstring (r_w, XmNlabelString, 
  216.         "Central Meridian Longitude (degs):\n(GRS is at 30 degs in System II)");
  217.  
  218.     /* make row for CMLs */
  219.  
  220.     n = 0;
  221.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  222.     XtSetArg (args[n], XmNtopWidget, r_w); n++;
  223.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  224.     XtSetArg (args[n], XmNuserData, "Jupiter.CMLI"); n++;
  225.     w = cml_w[CMLI] = XmCreatePushButton(jupform_w, "CMLI", args, n);
  226.     XtAddCallback(w, XmNactivateCallback, jm_activate_cb, 0);
  227.     XtManageChild (w);
  228.  
  229.     n = 0;
  230.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  231.     XtSetArg (args[n], XmNtopWidget, r_w); n++;
  232.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  233.     XtSetArg (args[n], XmNleftWidget, w); n++;
  234.     w = XmCreatePushButton (jupform_w, "CMLIL", args, n);
  235.     XtManageChild (w);
  236.     jm_set_a_button (w, False);
  237.     set_xmstring (w, XmNlabelString, "(Sys I)");
  238.  
  239.     n = 0;
  240.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  241.     XtSetArg (args[n], XmNtopWidget, r_w); n++;
  242.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  243.     w = XmCreatePushButton (jupform_w, "CMLIIL", args, n);
  244.     XtManageChild (w);
  245.     jm_set_a_button (w, False);
  246.     set_xmstring (w, XmNlabelString, "(Sys II)");
  247.  
  248.     n = 0;
  249.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  250.     XtSetArg (args[n], XmNtopWidget, r_w); n++;
  251.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  252.     XtSetArg (args[n], XmNrightWidget, w); n++;
  253.     XtSetArg (args[n], XmNuserData, "Jupiter.CMLII"); n++;
  254.     w = cml_w[CMLII] = XmCreatePushButton(jupform_w, "CMLII", args, n);
  255.     XtAddCallback(w, XmNactivateCallback, jm_activate_cb, 0);
  256.     XtManageChild (w);
  257.  
  258.     /* make table title label */
  259.  
  260.     n = 0;
  261.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  262.     XtSetArg (args[n], XmNtopWidget, w); n++;
  263.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  264.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  265.     title_w = XmCreateLabel (jupform_w, "TableLabel", args, n);
  266.     XtManageChild (title_w);
  267.     set_xmstring (title_w, XmNlabelString,
  268.                 " \nMoon positions -- in Jupiter Radii");
  269.  
  270.     /* make the moon table, one column at a time */
  271.  
  272.     /* moon designator column */
  273.  
  274.     n = 0;
  275.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  276.     XtSetArg (args[n], XmNtopWidget, title_w); n++;
  277.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  278.     XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  279.     XtSetArg (args[n], XmNisAligned, True); n++;
  280.     col_w = XmCreateRowColumn (jupform_w, "MoonDes", args, n);
  281.     XtManageChild (col_w);
  282.  
  283.         n = 0;
  284.         w = XmCreatePushButton (col_w, " ", args, n);
  285.         XtManageChild (w);
  286.         jm_set_a_button (w, False);
  287.  
  288.         for (i = 0; i < NM; i++) {
  289.         n = 0;
  290.         w = XmCreatePushButton (col_w, mnames[i].tag, args, n);
  291.         XtManageChild (w);
  292.         jm_set_a_button (w, False);
  293.         }
  294.  
  295.     /* moon name column */
  296.  
  297.     n = 0;
  298.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  299.     XtSetArg (args[n], XmNtopWidget, title_w); n++;
  300.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  301.     XtSetArg (args[n], XmNleftPosition, 10); n++;
  302.     XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_BEGINNING); n++;
  303.     XtSetArg (args[n], XmNisAligned, True); n++;
  304.     col_w = XmCreateRowColumn (jupform_w, "MoonName", args, n);
  305.     XtManageChild (col_w);
  306.  
  307.         n = 0;
  308.         w = XmCreatePushButton (col_w, " ", args, n);
  309.         XtManageChild (w);
  310.         jm_set_a_button (w, False);
  311.  
  312.         for (i = 0; i < NM; i++) {
  313.         n = 0;
  314.         w = XmCreatePushButton (col_w, mnames[i].full, args, n);
  315.         XtManageChild (w);
  316.         jm_set_a_button (w, False);
  317.         }
  318.  
  319.     /* moon X column */
  320.  
  321.     n = 0;
  322.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  323.     XtSetArg (args[n], XmNtopWidget, title_w); n++;
  324.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  325.     XtSetArg (args[n], XmNleftPosition, 35); n++;
  326.     XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  327.     XtSetArg (args[n], XmNisAligned, True); n++;
  328.     col_w = XmCreateRowColumn (jupform_w, "MoonXRC", args, n);
  329.     XtManageChild (col_w);
  330.  
  331.         n = 0;
  332.         w = XmCreatePushButton (col_w, "MoonX", args, n);
  333.         XtManageChild (w);
  334.         jm_set_a_button (w, False);
  335.         set_xmstring (w, XmNlabelString, "X (+E)");
  336.  
  337.         for (i = 0; i < NM; i++) {
  338.         char *sel;
  339.         sel = XtMalloc (strlen(mnames[i].full) + 3); /* '.X\0' */
  340.         (void) sprintf (sel, "%s.X", mnames[i].full);
  341.         n = 0;
  342.         XtSetArg (args[n], XmNuserData, sel); n++;
  343.         w = j_w[i][X] = XmCreatePushButton(col_w, "MoonXPB", args, n);
  344.         XtAddCallback(w, XmNactivateCallback, jm_activate_cb, 0);
  345.         XtManageChild (w);
  346.         }
  347.  
  348.     /* moon Y column */
  349.  
  350.     n = 0;
  351.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  352.     XtSetArg (args[n], XmNtopWidget, title_w); n++;
  353.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  354.     XtSetArg (args[n], XmNleftPosition, 55); n++;
  355.     XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  356.     XtSetArg (args[n], XmNisAligned, True); n++;
  357.     col_w = XmCreateRowColumn (jupform_w, "MoonYRC", args, n);
  358.     XtManageChild (col_w);
  359.  
  360.         n = 0;
  361.         w = XmCreatePushButton (col_w, "MoonYLabel", args, n);
  362.         XtManageChild (w);
  363.         set_xmstring (w, XmNlabelString, "Y (+S)");
  364.         jm_set_a_button (w, False);
  365.  
  366.         for (i = 0; i < NM; i++) {
  367.         char *sel;
  368.         sel = XtMalloc (strlen(mnames[i].full) + 3); /* '.Y\0' */
  369.         (void) sprintf (sel, "%s.Y", mnames[i].full);
  370.         n = 0;
  371.         XtSetArg (args[n], XmNuserData, sel); n++;
  372.         w = j_w[i][Y] = XmCreatePushButton(col_w, "MoonYPB", args, n);
  373.         XtAddCallback(w, XmNactivateCallback, jm_activate_cb, 0);
  374.         XtManageChild (w);
  375.         }
  376.  
  377.     /* moon Z column */
  378.  
  379.     n = 0;
  380.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  381.     XtSetArg (args[n], XmNtopWidget, title_w); n++;
  382.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  383.     XtSetArg (args[n], XmNleftPosition, 75); n++;
  384.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  385.     XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  386.     XtSetArg (args[n], XmNisAligned, True); n++;
  387.     col_w = XmCreateRowColumn (jupform_w, "MoonZRC", args, n);
  388.     XtManageChild (col_w);
  389.  
  390.         n = 0;
  391.         w = XmCreatePushButton (col_w, "MoonZ", args, n);
  392.         XtManageChild (w);
  393.         set_xmstring (w, XmNlabelString, "Z (+front)");
  394.         jm_set_a_button (w, False);
  395.  
  396.         for (i = 0; i < NM; i++) {
  397.         char *sel;
  398.         sel = XtMalloc (strlen(mnames[i].full) + 3); /* '.Z\0' */
  399.         (void) sprintf (sel, "%s.Z", mnames[i].full);
  400.         n = 0;
  401.         XtSetArg (args[n], XmNuserData, sel); n++;
  402.         w = j_w[i][Z] = XmCreatePushButton(col_w, "MoonZPB", args, n);
  403.         XtAddCallback(w, XmNactivateCallback, jm_activate_cb, 0);
  404.         XtManageChild (w);
  405.         }
  406.  
  407.     /* make a Form to hold the bottom controls */
  408.  
  409.     n = 0;
  410.     XtSetArg (args[n], XmNfractionBase, 15); n++;
  411.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  412.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  413.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  414.     f_w = XmCreateForm (jupform_w, "CtlForm", args, n);
  415.     XtManageChild (f_w);
  416.  
  417.         /* make the close button */
  418.  
  419.         n = 0;
  420.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  421.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  422.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  423.         XtSetArg (args[n], XmNleftPosition, 1); n++;
  424.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  425.         XtSetArg (args[n], XmNrightPosition, 4); n++;
  426.         w = XmCreatePushButton (f_w, "Close", args, n);
  427.         XtAddCallback (w, XmNactivateCallback, jm_close_cb, 0);
  428.         XtManageChild (w);
  429.  
  430.         /* make the tags toggle button in a frame */
  431.  
  432.         n = 0;
  433.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  434.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  435.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  436.         XtSetArg (args[n], XmNleftPosition, 6); n++;
  437.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  438.         XtSetArg (args[n], XmNrightPosition, 9); n++;
  439.         fr_w = XmCreateFrame (f_w, "TagsFr", args, n);
  440.         XtManageChild (fr_w);
  441.         n = 0;
  442.         w = XmCreateToggleButton (fr_w, "Tags", args, n);
  443.         XtAddCallback (w, XmNvalueChangedCallback, jm_tags_cb, 0);
  444.         XtManageChild (w);
  445.         j_tags = XmToggleButtonGetState(w);
  446.  
  447.         /* "big dots" toggle button in a frame */
  448.  
  449.         n = 0;
  450.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  451.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  452.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  453.         XtSetArg (args[n], XmNleftPosition, 11); n++;
  454.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  455.         XtSetArg (args[n], XmNrightPosition, 14); n++;
  456.         fr_w = XmCreateFrame(f_w,"BigDotsFr",args,n);
  457.         XtManageChild (fr_w);
  458.         str = XmStringCreate("Big dots", XmSTRING_DEFAULT_CHARSET);
  459.         n = 0;
  460.         XtSetArg (args[n], XmNlabelString, str); n++;
  461.         w = XmCreateToggleButton(fr_w,"BigDots",args,n);
  462.         XtAddCallback(w, XmNvalueChangedCallback, jm_bigd_cb, 0);
  463.         XtManageChild (w);
  464.         XmStringFree (str);
  465.         bigdots = XmToggleButtonGetState(w);
  466.  
  467.     /* make the date/time stamp label */
  468.  
  469.     n = 0;
  470.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  471.     XtSetArg (args[n], XmNbottomWidget, f_w); n++;
  472.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  473.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  474.     dt_w = XmCreateLabel (jupform_w, "DateStamp", args, n);
  475.     timestamp (mm_get_now(), dt_w);    /* establishes size */
  476.     XtManageChild (dt_w);
  477.  
  478.     /* make the scale widget
  479.      * attach both top and bottom so it's the one to follow resizing.
  480.      */
  481.  
  482.     n = 0;
  483.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  484.     XtSetArg (args[n], XmNtopWidget, col_w); n++;
  485.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  486.     XtSetArg (args[n], XmNbottomWidget, dt_w); n++;
  487.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  488.     XtSetArg (args[n], XmNmaximum, 100); n++;
  489.     XtSetArg (args[n], XmNminimum, 0); n++;
  490.     XtSetArg (args[n], XmNscaleMultiple, 10); n++;
  491.     XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
  492.     XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
  493.     scale_w = XmCreateScale (jupform_w, "Scale", args, n);
  494.     XtAddCallback (scale_w, XmNdragCallback, jm_scale_cb, 0);
  495.     XtAddCallback (scale_w, XmNvalueChangedCallback, jm_scale_cb, 0);
  496.     XtManageChild (scale_w);
  497.  
  498.     /* make a frame for the drawing area.
  499.      * attach both top and bottom so it's the one to follow resizing.
  500.      */
  501.  
  502.     n = 0;
  503.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  504.     XtSetArg (args[n], XmNtopWidget, col_w); n++;
  505.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  506.     XtSetArg (args[n], XmNbottomWidget, dt_w); n++;
  507.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  508.     XtSetArg (args[n], XmNleftWidget, scale_w); n++;
  509.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  510.     XtSetArg (args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
  511.     frame_w = XmCreateFrame (jupform_w, "DAFrame", args, n);
  512.     XtManageChild (frame_w);
  513.  
  514.         /* make a drawing area for drawing the little map */
  515.  
  516.         n = 0;
  517.         jda_w = XmCreateDrawingArea (frame_w, "Map", args, n);
  518.         XtAddCallback (jda_w, XmNexposeCallback, jm_da_exp_cb, 0);
  519.         XtManageChild (jda_w);
  520. }
  521.  
  522. /* go through all the buttons pickable for plotting and set whether they
  523.  * should appear to look like buttons or just flat labels.
  524.  */
  525. static void
  526. jm_set_buttons (whether)
  527. int whether;    /* whether setting up for plotting or for not plotting */
  528. {
  529.     int i;
  530.  
  531.     for (i = 0; i < NM; i++) {
  532.         jm_set_a_button (j_w[i][X], whether);
  533.         jm_set_a_button (j_w[i][Y], whether);
  534.         jm_set_a_button (j_w[i][Z], whether);
  535.     }
  536.  
  537.     jm_set_a_button (cml_w[CMLI], whether);
  538.     jm_set_a_button (cml_w[CMLII], whether);
  539. }
  540.  
  541. /* set whether the given button looks like a label.
  542.  */
  543. static void
  544. jm_set_a_button(pbw, whether)
  545. Widget pbw;
  546. int whether;
  547. {
  548.     static Arg look_like_button[] = {
  549.         {XmNtopShadowColor, (XtArgVal) 0},
  550.         {XmNbottomShadowColor, (XtArgVal) 0},
  551.         {XmNfillOnArm, (XtArgVal) True},
  552.     };
  553.     static Arg look_like_label[] = {
  554.         {XmNtopShadowColor, (XtArgVal) 0},
  555.         {XmNbottomShadowColor, (XtArgVal) 0},
  556.         {XmNfillOnArm, (XtArgVal) False},
  557.     };
  558.     static int called;
  559.     Arg *ap;
  560.     int na;
  561.  
  562.     if (!called) {
  563.         /* get baseline label and shadow appearances.
  564.          */
  565.         Pixel topshad, botshad, bgcol;
  566.         Arg args[20];
  567.         Widget tmpw;
  568.         int n;
  569.  
  570.         n = 0;
  571.         tmpw = XmCreatePushButton (jupform_w, "tmp", args, n);
  572.  
  573.         n = 0;
  574.         XtSetArg (args[n], XmNtopShadowColor, &topshad); n++;
  575.         XtSetArg (args[n], XmNbottomShadowColor, &botshad); n++;
  576.         XtSetArg (args[n], XmNbackground, &bgcol); n++;
  577.         XtGetValues (tmpw, args, n);
  578.  
  579.         look_like_button[0].value = topshad;
  580.         look_like_button[1].value = botshad;
  581.         look_like_label[0].value = bgcol;
  582.         look_like_label[1].value = bgcol;
  583.  
  584.         XtDestroyWidget (tmpw);
  585.          
  586.         called = 1;
  587.     }
  588.  
  589.     if (whether) {
  590.         ap = look_like_button;
  591.         na = XtNumber(look_like_button);
  592.     } else {
  593.         ap = look_like_label;
  594.         na = XtNumber(look_like_label);
  595.     }
  596.  
  597.     XtSetValues (pbw, ap, na);
  598. }
  599.  
  600. /* callback from the big dots toggle button
  601.  * TODO: really shouldn't get present time, just redo dots in same location.
  602.  */
  603. /* ARGSUSED */
  604. static void
  605. jm_bigd_cb (w, client, call)
  606. Widget w;
  607. XtPointer client;
  608. XtPointer call;
  609. {
  610.     bigdots = XmToggleButtonGetState(w);
  611.     jm_update (mm_get_now(), 1);
  612. }
  613.  
  614. /* callback from the tags toggle button
  615.  * TODO: really shouldn't get present time, just redo dots in same location.
  616.  */
  617. /* ARGSUSED */
  618. static void
  619. jm_tags_cb (w, client, call)
  620. Widget w;
  621. XtPointer client;
  622. XtPointer call;
  623. {
  624.     j_tags = XmToggleButtonGetState(w);
  625.     jm_update (mm_get_now(), 1);
  626. }
  627.  
  628. /* callback from the scale.
  629.  * TODO: really shouldn't get present time, just redo dots in same location.
  630.  */
  631. /* ARGSUSED */
  632. static void
  633. jm_scale_cb (w, client, call)
  634. Widget w;
  635. XtPointer client;
  636. XtPointer call;
  637. {
  638.     jm_update (mm_get_now(), 1);
  639. }
  640.  
  641. /* callback from any of the data menu buttons being activated.
  642.  */
  643. /* ARGSUSED */
  644. static void
  645. jm_activate_cb (w, client, call)
  646. Widget w;
  647. XtPointer client;
  648. XtPointer call;
  649. {
  650.     if (jm_selecting) {
  651.         char *name;
  652.         get_something (w, XmNuserData, (char *)&name);
  653.         register_selection (name);
  654.     }
  655. }
  656.  
  657. /* callback from the Close button
  658.  */
  659. /* ARGSUSED */
  660. static void
  661. jm_close_cb (w, client, call)
  662. Widget w;
  663. XtPointer client;
  664. XtPointer call;
  665. {
  666.     XtUnmanageChild (jupform_w);
  667. }
  668.  
  669. /* callback from either expose of the drawing area.
  670.  */
  671. /* ARGSUSED */
  672. static void
  673. jm_da_exp_cb (w, client, call)
  674. Widget w;
  675. XtPointer client;
  676. XtPointer call;
  677. {
  678.     XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
  679.  
  680.     /* filter out a few oddball cases */
  681.     switch (c->reason) {
  682.     case XmCR_EXPOSE: {
  683.         /* turn off gravity so we get expose events for either shrink or
  684.          * expand.
  685.          */
  686.         static before;
  687.         XExposeEvent *e = &c->event->xexpose;
  688.  
  689.         if (!before) {
  690.         XSetWindowAttributes swa;
  691.         swa.bit_gravity = ForgetGravity;
  692.         XChangeWindowAttributes (e->display, e->window, 
  693.                                 CWBitGravity, &swa);
  694.         before = 1;
  695.         }
  696.         /* wait for the last in the series */
  697.         if (e->count != 0)
  698.         return;
  699.         break;
  700.         }
  701.     default:
  702.         printf ("Unexpected jupform_w event. type=%d\n", c->reason);
  703.         exit(1);
  704.     }
  705.  
  706.     jm_update (mm_get_now(), 1);
  707. }
  708.  
  709. /* given the loc of the moons, draw a nifty little picture.
  710.  * scale of the locations is in terms of jupiter radii == 1.
  711.  */
  712. /* ARGSUSED */
  713. static void
  714. jm_draw_map (w, moons, sIcml, sIIcml)
  715. Widget w;
  716. MoonData moons[NM];
  717. double sIcml, sIIcml;
  718. {
  719.     static GC j_fgc, j_bgc, j_xgc;
  720.     static XFontStruct *j_fs;
  721.     static last_nx, last_ny;
  722.     static int cw, ch;
  723.     static Pixmap pm;
  724.     Display *dsp = XtDisplay(w);
  725.     Window win = XtWindow(w);
  726.     Window root;
  727.     double scale;
  728.     int sv;
  729.     char c;
  730.     int x, y;
  731.     unsigned int nx, ny, bw, d;
  732.     int i;
  733. #define    NORM    27.0    /* max callisto orbit radius; used to normalize */
  734. #define    MAPSCALE(v)    ((v)*((int)nx)/NORM/2*scale)
  735. #define    XCORD(x)    ((int)(((int)nx)/2.0 + MAPSCALE(x) + 0.5))
  736. #define    YCORD(y)    ((int)(((int)ny)/2.0 - MAPSCALE(y) + 0.5))
  737.  
  738.     if (!j_fgc) {
  739.         XGCValues gcv;
  740.         unsigned int gcm;
  741.         Pixel fg, bg;
  742.  
  743.         gcm = GCForeground;
  744.         get_something (w, XmNforeground, (char *)&fg);
  745.         gcv.foreground = fg;
  746.         j_fgc = XCreateGC (dsp, win, gcm, &gcv);
  747.         j_fs = XQueryFont (dsp, XGContextFromGC (j_fgc));
  748.         cw = j_fs->max_bounds.width;
  749.         ch = j_fs->max_bounds.ascent + j_fs->max_bounds.descent;
  750.  
  751.         gcm = GCForeground;
  752.         get_something (w, XmNbackground, (char *)&bg);
  753.         gcv.foreground = bg;
  754.         j_bgc = XCreateGC (dsp, win, gcm, &gcv);
  755.  
  756.         gcm = GCForeground | GCFunction;
  757.         gcv.foreground = fg ^ bg;
  758.         gcv.function = GXxor;
  759.         j_xgc = XCreateGC (dsp, win, gcm, &gcv);
  760.     }
  761.  
  762.     XmScaleGetValue (scale_w, &sv);
  763.     scale = pow(MAXSCALE, sv/100.0);
  764.  
  765.     XGetGeometry(dsp, win, &root, &x, &y, &nx, &ny, &bw, &d);
  766.     if (!pm || nx != last_nx || ny != last_ny) {
  767.         if (pm)
  768.         XFreePixmap (dsp, pm);
  769.         pm = XCreatePixmap (dsp, win, nx, ny, d);
  770.         last_nx = nx;
  771.         last_ny = ny;
  772.     }
  773.  
  774.     XFillRectangle (dsp, pm, j_bgc, 0, 0, nx, ny);
  775.  
  776.     c = 'E'; XDrawString(dsp, pm, j_fgc, nx-cw-1, ny/2-2, &c, 1);
  777.     c = 'S'; XDrawString(dsp, pm, j_fgc, (nx-cw)/2-1, j_fs->ascent, &c, 1);
  778.  
  779.     /* draw Jupiter of unit radius */
  780.     XFillArc (dsp, pm, j_fgc, XCORD(-1), YCORD(1), 2*(int)MAPSCALE(1),
  781.                         2*(int)MAPSCALE(1), 0, 360*64);
  782.  
  783.     /* draw each moon that is visible.
  784.      */
  785.     for (i = 0; i < NM; i++) {
  786.         double mx = moons[i].x;
  787.         double my = moons[i].y;
  788.         double mz = moons[i].z;
  789.         int outside = mx*mx + my*my > 1.0;
  790.         int infront = mz > 0.0;
  791.  
  792.         if (!outside && !infront)
  793.         continue;    /* behind jupiter */
  794.  
  795.         x = XCORD(mx);
  796.         y = YCORD(my);
  797.         XDrawPoint (dsp, pm, j_xgc, x, y);
  798.         if (bigdots) {
  799.         XDrawPoint(dsp, pm, j_xgc, x+1, y);
  800.         XDrawPoint(dsp, pm, j_xgc, x,   y+1);
  801.         XDrawPoint(dsp, pm, j_xgc, x+1, y+1);
  802.         }
  803.         if (j_tags)
  804.         XDrawString(dsp, pm, j_xgc, x-cw/2, y+2*ch,
  805.                     mnames[i].tag, strlen(mnames[i].tag));
  806.     }
  807.  
  808.     XCopyArea (dsp, pm, win, j_fgc, 0, 0, nx, ny, 0, 0);
  809. }
  810.  
  811.  
  812. #define    dsin(x)    sin(degrad(x))
  813. #define    dcos(x)    cos(degrad(x))
  814.  
  815. /* given a modified julian date (ie, days since Jan .5 1900), d, return x, y, z
  816.  *   location of each Galilean moon as a multiple of Jupiter's radius. on this
  817.  *   scale, Callisto is never more than 26.5593. +x is easterly, +y is
  818.  *   southerly, +z is towards earth. x and z are relative to the equator
  819.  *   of Jupiter; y is further corrected for earth's position above or below
  820.  *   this plane. also, return the system I and II central meridian longitude,
  821.  *   in degress, relative to the true disk of jupiter and corrected for light
  822.  *   travel time.
  823.  * from "Astronomical Formulae for Calculators", 2nd ed, by Jean Meeus,
  824.  *   Willmann-Bell, Richmond, Va., U.S.A. (c) 1982, chapters 35 and 36.
  825.  */
  826. static void
  827. jupinfo (d, moons, sIcml, sIIcml)
  828. double d;
  829. MoonData moons[NM];    /* Io, Europa, Ganymede, Callisto */
  830. double *sIcml, *sIIcml;
  831. {
  832.     double A, B, Del, J, K, M, N, R, V;
  833.     double cor_u1, cor_u2, cor_u3, cor_u4;
  834.     double solc, tmp, G, H, psi, r, r1, r2, r3, r4;
  835.     double u1, u2, u3, u4;
  836.     double lam, Ds;
  837.     double z1, z2, z3,  z4;
  838.     double De, dsinDe;
  839.  
  840.     V = 134.63 + 0.00111587 * d;
  841.  
  842.     M = (358.47583 + 0.98560003*d);
  843.     N = (225.32833 + 0.0830853*d) + 0.33 * dsin (V);
  844.  
  845.     J = 221.647 + 0.9025179*d - 0.33 * dsin(V);;
  846.  
  847.     A = 1.916*dsin(M) + 0.02*dsin(2*M);
  848.     B = 5.552*dsin(N) + 0.167*dsin(2*N);
  849.     K = (J+A-B);
  850.     R = 1.00014 - 0.01672 * dcos(M) - 0.00014 * dcos(2*M);
  851.     r = 5.20867 - 0.25192 * dcos(N) - 0.00610 * dcos(2*N);
  852.     Del = sqrt (R*R + r*r - 2*R*r*dcos(K));
  853.     psi = raddeg (asin (R/Del*dsin(K)));
  854.  
  855.     solc = (d - Del/173.);    /* speed of light correction */
  856.     tmp = psi - B;
  857.  
  858.     u1 = 84.5506 + 203.4058630 * solc + tmp;
  859.     u2 = 41.5015 + 101.2916323 * solc + tmp;
  860.     u3 = 109.9770 + 50.2345169 * solc + tmp;
  861.     u4 = 176.3586 + 21.4879802 * solc + tmp;
  862.  
  863.     G = 187.3 + 50.310674 * solc;
  864.     H = 311.1 + 21.569229 * solc;
  865.       
  866.     cor_u1 =  0.472 * dsin (2*(u1-u2));
  867.     cor_u2 =  1.073 * dsin (2*(u2-u3));
  868.     cor_u3 =  0.174 * dsin (G);
  869.     cor_u4 =  0.845 * dsin (H);
  870.       
  871.     r1 = 5.9061 - 0.0244 * dcos (2*(u1-u2));
  872.     r2 = 9.3972 - 0.0889 * dcos (2*(u2-u3));
  873.     r3 = 14.9894 - 0.0227 * dcos (G);
  874.     r4 = 26.3649 - 0.1944 * dcos (H);
  875.  
  876.     moons[0].x = -r1 * dsin (u1+cor_u1);
  877.     moons[1].x = -r2 * dsin (u2+cor_u2);
  878.     moons[2].x = -r3 * dsin (u3+cor_u3);
  879.     moons[3].x = -r4 * dsin (u4+cor_u4);
  880.  
  881.     lam = 238.05 + 0.083091*d + 0.33*dsin(V) + B;
  882.     Ds = 3.07*dsin(lam + 44.5);
  883.     De = Ds - 2.15*dsin(psi)*dcos(lam+24.)
  884.         - 1.31*(r-Del)/Del*dsin(lam-99.4);
  885.     dsinDe = dsin(De);
  886.  
  887.     z1 = r1 * dcos(u1+cor_u1);
  888.     z2 = r2 * dcos(u2+cor_u2);
  889.     z3 = r3 * dcos(u3+cor_u3);
  890.     z4 = r4 * dcos(u4+cor_u4);
  891.  
  892.     moons[0].y = z1*dsinDe;
  893.     moons[1].y = z2*dsinDe;
  894.     moons[2].y = z3*dsinDe;
  895.     moons[3].y = z4*dsinDe;
  896.  
  897.     moons[0].z = z1;
  898.     moons[1].z = z2;
  899.     moons[2].z = z3;
  900.     moons[3].z = z4;
  901.  
  902.     *sIcml  = 268.28 + 877.8169088*(d - Del/173) + psi - B;
  903.     range (sIcml, 360.0);
  904.     *sIIcml = 290.28 + 870.1869088*(d - Del/173) + psi - B;
  905.     range (sIIcml, 360.0);
  906. }
  907.