home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume19 / xephem / part13 < prev    next >
Encoding:
Text File  |  1993-05-15  |  76.3 KB  |  2,737 lines

  1. Newsgroups: comp.sources.x
  2. From: ecdowney@pobox.cca.cr.rockwell.com (Elwood Downey)
  3. Subject: v19i101:  xephem - astronomical ephemeris program, Part13/21
  4. Message-ID: <1993May10.221132.9035@sparky.imd.sterling.com>
  5. X-Md4-Signature: bca8025bd4c95e0807b6324109fdda78
  6. Date: Mon, 10 May 1993 22:11:32 GMT
  7. Approved: chris@sparky.imd.sterling.com
  8.  
  9. Submitted-by: ecdowney@pobox.cca.cr.rockwell.com (Elwood Downey)
  10. Posting-number: Volume 19, Issue 101
  11. Archive-name: xephem/part13
  12. Environment: X11r4, OSF/Motif
  13. Supersedes: xephem: Volume 16, Issue 112-134
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  mainmenu.c satmenu.c
  22. # Wrapped by chris@nova on Mon May 10 16:41:49 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 13 (of 21)."'
  26. if test -f 'mainmenu.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'mainmenu.c'\"
  28. else
  29.   echo shar: Extracting \"'mainmenu.c'\" \(35808 characters\)
  30.   sed "s/^X//" >'mainmenu.c' <<'END_OF_FILE'
  31. X/* code to manage the stuff on the (permanent) main menu.
  32. X * this is also where the single static Now struct is maintained.
  33. X * the calendar is managed in calmenu.c.
  34. X */
  35. X
  36. X#include <stdio.h>
  37. X#include <ctype.h>
  38. X#include <math.h>
  39. X#if defined(__STDC__)
  40. X#include <stdlib.h>
  41. X#endif
  42. X#include <X11/Xlib.h>
  43. X#include <X11/keysym.h>
  44. X#include <Xm/Xm.h>
  45. X#include <Xm/Form.h>
  46. X#include <Xm/Frame.h>
  47. X#include <Xm/Label.h>
  48. X#include <Xm/PushB.h>
  49. X#include <Xm/RowColumn.h>
  50. X#include <Xm/Separator.h>
  51. X#include <Xm/SelectioB.h>
  52. X#include "astro.h"
  53. X#include "circum.h"
  54. X#include "preferences.h"
  55. X
  56. Xtypedef struct {
  57. X    int id;        /* see below -- used just as a cross-check */
  58. X    char *prompt;    /* used when asking for new value or NULL if can't */
  59. X    char *label;    /* used for the menu label or NULL */
  60. X    char *name;        /* used when selecting for plotting or NULL if can't */
  61. X    char *altp[3];    /* alternate prompts based on preferences */
  62. X    Widget pb_w;    /* pushbutton for display and changing/selecting */
  63. X} Field;
  64. X
  65. X#if defined(__STDC__) || defined(__cplusplus)
  66. X#define P_(s) s
  67. X#else
  68. X#define P_(s) ()
  69. X#endif
  70. X
  71. Xextern double mjd_day P_((double jd));
  72. Xextern double mjd_hr P_((double jd));
  73. Xextern int f_ison P_((void));
  74. Xextern int listing_ison P_((void));
  75. Xextern int plot_cartesian P_((FILE *pfp, Widget widget, unsigned int nx, unsigned int ny, int flipx, int flipy, int grid));
  76. Xextern int plot_ison P_((void));
  77. Xextern int srch_eval P_((double Mjd, double *tmincp));
  78. Xextern void all_update P_((Now *np, int how_much));
  79. Xextern void cal_mjd P_((int mn, double dy, int yr, double *Mjd));
  80. Xextern void calm_set P_((Now *np));
  81. Xextern void db_invalidate P_((void));
  82. Xextern void f_date P_((Widget w, double jd));
  83. Xextern void f_dec_sexsign P_((double x, int *h, int *m, int *s));
  84. Xextern void f_double P_((Widget w, char *fmt, double f));
  85. Xextern void f_gangle P_((Widget w, double a));
  86. Xextern void f_mtime P_((Widget w, double t));
  87. Xextern void f_off P_((void));
  88. Xextern void f_on P_((void));
  89. Xextern void f_signtime P_((Widget w, double t));
  90. Xextern void f_sscandate P_((char *bp, int pref, int *m, double *d, int *y));
  91. Xextern void f_sscansex P_((char *bp, int *d, int *m, int *s));
  92. Xextern void f_string P_((Widget w, char *s));
  93. Xextern void f_time P_((Widget w, double t));
  94. Xextern void get_xmstring P_((Widget w, char *resource, char **txtp));
  95. Xextern void gst_utc P_((double Mjd, double gst, double *utc));
  96. Xextern void inc_mjd P_((Now *np, double inc));
  97. Xextern void listing P_((void));
  98. Xextern void mjd_cal P_((double Mjd, int *mn, double *dy, int *yr));
  99. Xextern void mjd_year P_((double Mjd, double *yr));
  100. Xextern void now_lst P_((Now *np, double *lst));
  101. Xextern void plot P_((void));
  102. Xextern void plot_manage P_((void));
  103. Xextern void prompt_map_cb P_((Widget w, XtPointer client, XtPointer call));
  104. Xextern void range P_((double *v, double r));
  105. Xextern void register_selection P_((char *name));
  106. Xextern void set_t0 P_((Now *np));
  107. Xextern void set_xmstring P_((Widget w, char *resource, char *txt));
  108. Xextern void sex_dec P_((int hd, int m, int s, double *d));
  109. Xextern void time_fromsys P_((Now *np));
  110. Xextern void twilight_cir P_((Now *np, double dis, double *dawn, double *dusk, int *status));
  111. Xextern void watch_cursor P_((int want));
  112. Xextern void xe_msg P_((char *msg, int app_modal));
  113. Xextern void year_mjd P_((double y, double *Mjd));
  114. X
  115. Xvoid mm_manage P_((Widget main_window));
  116. Xvoid mm_reset P_((void));
  117. Xvoid mm_newcaldate P_((double newmjd));
  118. Xvoid mm_selection_mode P_((int whether));
  119. XNow *mm_get_now P_((void));
  120. Xvoid redraw_screen P_((int how_much));
  121. Xstatic void create_main_form P_((Widget main_window));
  122. Xstatic void read_default_resources P_((void));
  123. Xstatic Widget fw P_((int fid));
  124. Xstatic void mm_set_buttons P_((int whether));
  125. Xstatic void mm_activate_cb P_((Widget w, XtPointer client, XtPointer call));
  126. Xstatic void mm_set_pref_prompts P_((Field *fp));
  127. Xstatic void mm_timer_cb P_((XtPointer client, XtIntervalId *id));
  128. Xstatic void mm_go_cb P_((Widget w, XtPointer client, XtPointer call));
  129. Xstatic void mm_go P_((void));
  130. Xstatic void print_tminc P_((int force));
  131. Xstatic void print_updating P_((void));
  132. Xstatic void print_idle P_((void));
  133. Xstatic void print_running P_((void));
  134. Xstatic void print_status P_((char *s));
  135. Xstatic void print_nstep P_((int force));
  136. Xstatic void print_spause P_((int force));
  137. Xstatic crack_fieldset P_((char *buf));
  138. Xstatic chg_fld P_((char *bp, Field *fp));
  139. Xstatic void prompt_ok_cb P_((Widget w, XtPointer client, XtPointer call));
  140. Xstatic void prompt P_((Field *fp));
  141. Xstatic void mm_now P_((int all));
  142. Xstatic void mm_twilight P_((int force));
  143. Xstatic void mm_newcir P_((int y));
  144. X
  145. X#undef P_
  146. X
  147. Xextern Widget toplevel_w;
  148. Xextern char *myclass;
  149. Xextern XtAppContext xe_app;
  150. X#define    XtD    XtDisplay(toplevel_w)
  151. Xextern char *sys_errlist[];
  152. Xextern errno;
  153. Xextern Widget calm_create();
  154. X
  155. X/* shorthands for fields of a Now structure, now.
  156. X * first undo the ones for a Now pointer from circum.h.
  157. X */
  158. X#undef mjd
  159. X#undef lat
  160. X#undef lng
  161. X#undef tz
  162. X#undef temp
  163. X#undef pressure
  164. X#undef elev
  165. X#undef dip
  166. X#undef epoch
  167. X#undef tznm
  168. X
  169. X#define mjd    now.n_mjd
  170. X#define lat    now.n_lat
  171. X#define lng    now.n_lng
  172. X#define tz    now.n_tz
  173. X#define temp    now.n_temp
  174. X#define pressure now.n_pressure
  175. X#define elev    now.n_elev
  176. X#define    dip    now.n_dip
  177. X#define epoch    now.n_epoch
  178. X#define tznm    now.n_tznm
  179. X
  180. Xstatic Now now;        /* where when and how, right now */
  181. Xstatic double tminc;    /* hrs to inc time by each loop; RTC means use clock */
  182. Xstatic int nstep;    /* steps to go before stopping */
  183. Xstatic int spause;    /* secs to pause between steps */
  184. Xstatic int newcir = 1; /* set when circumstances change - means don't tminc */
  185. X
  186. Xstatic XtIntervalId mm_interval_id;    /* set while waiting in a pause loop */
  187. Xstatic int mm_selecting;        /* set while our fields are being selected */
  188. X
  189. X/* field ids
  190. X * N.B. must be in same order as they appear in mm_field_map[].
  191. X */
  192. Xenum {
  193. X    UD_FID, UT_FID, JD_FID, LST_FID,TZN_FID, TZONE_FID, LD_FID, LT_FID, 
  194. X    DIP_FID, DAWN_FID, DUSK_FID, LON_FID, GAP, NSTEP_FID, STPSZ_FID, PAUSE_FID,
  195. X    LAT_FID, LONG_FID, ELEV_FID, TEMP_FID, PRES_FID, EPOCH_FID
  196. X};
  197. X
  198. X/* array of label/button pairs.
  199. X * N.B. these must be in the same order as the _FID enums so the XX_FID may
  200. X *   be used as indices into the array.
  201. X * N.B. some of the prompts get set based on preferences but we need to put
  202. X *   *something* in the prompt field of selectable fields to trigger making a
  203. X *   button. These alternate prompts must be set to match the PREF_ enums.
  204. X */
  205. Xstatic Field mm_field_map[] = {
  206. X    {UD_FID,    "dummy",                "UTC Date:","UD",
  207. X    {   "UTC date (m/d/y or year.d): ",
  208. X        "UTC date (y/m/d or year.d): ",
  209. X        "UTC date (d/m/y or year.d): "
  210. X    }
  211. X    },
  212. X    {UT_FID,    "UTC time (h:m:s): ",            "UTC Time:", "UT"},
  213. X    {JD_FID,    "Julian Date: ",            "Julian:", "JD"},
  214. X    {LST_FID,    "Local sidereal time (h:m:s): ",    "Sidereal:", "LST"},
  215. X    {TZN_FID,    "Timezone abbreviation (3 char max): ",    "TZ Name:", NULL},
  216. X    {TZONE_FID,    "Hours behind UTC: ",            "TZ Offset:", "TZ"},
  217. X    {LD_FID,    "dummy",                "Local Date:", "LD",
  218. X    {   "Local date (m/d/y or year.d): ",
  219. X        "Local date (y/m/d or year.d): ",
  220. X        "Local date (d/m/y or year.d): "
  221. X    }
  222. X    },
  223. X    {LT_FID,    "Local time (h:m:s): ",    "Local Time:",    "LT"},
  224. X    {DIP_FID,    "Sun's twilight dip, degrees below",    "Twilight Dip:", NULL},
  225. X    {DAWN_FID,    NULL,                    "Dawn:", "Dawn"},
  226. X    {DUSK_FID,    NULL,                    "Dusk:", "Dusk"},
  227. X    {LON_FID,    NULL,                    "Night Length:", "NiteLen"},
  228. X    {GAP},
  229. X    {NSTEP_FID, "Number of steps to run: ",        "N Steps:", NULL},
  230. X    {STPSZ_FID,    "\
  231. XStep size increment:\n\
  232. X    h:m:s, or\n\
  233. X    <x>d for x days, or\n\
  234. X    <x>s for x sidereal days, or\n\
  235. X    r for RTC",                        "Step Size:", NULL},
  236. X    {PAUSE_FID,    "Seconds to pause between steps: ",    "Pause:", NULL},
  237. X    {LAT_FID,    "Latitude (+ north) (d:m:s): ",        "Latitude:", "Lat"},
  238. X    {LONG_FID,    "Longitude (+ west) (d:m:s): ",        "Longitude:", "Long"},
  239. X    {ELEV_FID,    "dummy",                "Elevation:", "Elev",
  240. X    {   "Elevation above sea level (ft): ",
  241. X        "Elevation above sea level (m): "
  242. X    }
  243. X    },
  244. X    {TEMP_FID,    "dummy",                "Temperature:", "Temp",
  245. X    {   "Temperature (degrees F): ",
  246. X        "Temperature (degrees C): "
  247. X    }
  248. X    },
  249. X    {PRES_FID,    "dummy",                "Atm Pressure:","AtmPr",
  250. X    {   "Atmospheric pressure (inches of Mercury):",
  251. X        "Atmospheric pressure (mBar):"
  252. X    }
  253. X    },
  254. X    {EPOCH_FID,    "Epoch (decimal year): ", "Epoch:", NULL},
  255. X};
  256. X
  257. X#define    NFM    XtNumber(mm_field_map)
  258. X#define    LFM    (&mm_field_map[NFM])
  259. X
  260. Xstatic Widget newcir_w;
  261. Xstatic Widget status_w;
  262. Xstatic Widget go_w;
  263. X
  264. X/* this is the list of keywords that allow some initial values to be set.
  265. X * these are resources to the XEphem class as "XEphem.<keyword>: <value>".
  266. X */
  267. X/* N.B. index of item is its switch/case value in crack_fieldset ()
  268. X */
  269. Xstatic char *keywords[] = {
  270. X    /*  0 */    "Epoch",
  271. X    /*  1 */    "Elevation",
  272. X    /*  2 */    "JD",
  273. X    /*  3 */    "Lat",
  274. X    /*  4 */    "Long",
  275. X    /*  5 */    "NSteps",
  276. X    /*  6 */    "Pause",
  277. X    /*  7 */    "Pressure",
  278. X    /*  8 */    "StepSize",
  279. X    /*  9 */    "Temp",
  280. X    /* 10 */    "TZName",
  281. X    /* 11 */    "TZone",
  282. X    /* 12 */    "UD",
  283. X    /* 13 */    "UT",
  284. X    /* 14 */    "TwilightDip",
  285. X    /* 15 */    "LD",
  286. X    /* 16 */    "LT",
  287. X    /* 17 */    "LST",
  288. X};
  289. X
  290. X/* called exactly once when the main form is made.
  291. X * create and manage all the widgets as children of the form_w.
  292. X */
  293. Xvoid
  294. Xmm_manage (main_window)
  295. XWidget main_window;
  296. X{
  297. X    create_main_form(main_window);
  298. X    mm_reset();
  299. X}
  300. X
  301. X/* reset things to their initial resource settings */
  302. Xvoid
  303. Xmm_reset()
  304. X{
  305. X    read_default_resources ();
  306. X    redraw_screen (1);
  307. X    mm_newcir(0);
  308. X    mm_set_buttons (mm_selecting);
  309. X    print_idle();
  310. X}
  311. X
  312. X/* called by the calendar subsystem to set a new UT date.
  313. X * newmjd is the new UT date/time as a modifed Julian date.
  314. X */
  315. Xvoid
  316. Xmm_newcaldate (newmjd)
  317. Xdouble newmjd;
  318. X{
  319. X    mjd = newmjd;
  320. X    set_t0 (&now);
  321. X    mm_now (1);
  322. X    mm_newcir(1);
  323. X    newcir = 1;
  324. X}
  325. X
  326. X/* called by other menus as they want to hear from our buttons or not.
  327. X * the "on"s and "off"s stack - only really redo the buttons if it's the
  328. X * first on or the last off.
  329. X */
  330. Xvoid
  331. Xmm_selection_mode (whether)
  332. Xint whether;    /* whether setting up for plotting or for not plotting */
  333. X{
  334. X    mm_selecting += whether ? 1 : -1;
  335. X
  336. X    if (whether && mm_selecting == 1     /* first one to want on */
  337. X        || !whether && mm_selecting == 0 /* last one to want off */)
  338. X        mm_set_buttons (whether);
  339. X}
  340. X
  341. X/* a way for anyone to know what now is */
  342. XNow *
  343. Xmm_get_now()
  344. X{
  345. X    return (&now);
  346. X}
  347. X
  348. X/* draw all the stuff on the managed menus.
  349. X * if how_much == 0 then just update fields that need it;
  350. X * if how_much == 1 then redraw all fields;
  351. X */
  352. Xvoid
  353. Xredraw_screen (how_much)
  354. Xint how_much;
  355. X{
  356. X    watch_cursor(1);
  357. X
  358. X    /* invalidate any cached values in the database */
  359. X    db_invalidate();
  360. X
  361. X    /* print the single-step message if this is the last loop */
  362. X    if (nstep < 1)
  363. X        print_updating();
  364. X
  365. X    /* if just updating changed fields while plotting or listing
  366. X     * unattended then suppress most screen updates except
  367. X     * always show nstep to show plot loops to go and
  368. X     * always show tminc to show search convergence progress.
  369. X     */
  370. X    print_nstep(how_much);
  371. X    print_tminc(how_much);
  372. X    print_spause(how_much);
  373. X    if (how_much == 0 && nstep > 0 && spause == 0)
  374. X        f_off();
  375. X
  376. X    /* print all the time-related fields */
  377. X    mm_now (how_much);
  378. X
  379. X    mm_twilight (how_much);
  380. X
  381. X    /* print stuff on other menus */
  382. X    all_update(&now, how_much);
  383. X
  384. X    f_on();
  385. X
  386. X    watch_cursor(0);
  387. X}
  388. X
  389. Xstatic void
  390. Xcreate_main_form(main_window)
  391. XWidget main_window;
  392. X{
  393. X    static int fmi[4] = {0, 8, 16, NFM};
  394. X    XmString str;
  395. X    Widget mrc_w, hrc_w, rc_w;
  396. X    Widget sep_w;
  397. X    Widget w;
  398. X    Arg args[20];
  399. X    int i, n;
  400. X
  401. X    /* create the main vertical r/c */
  402. X    n = 0;
  403. X    XtSetArg (args[n], XmNisAligned, False); n++;
  404. X    mrc_w = XmCreateRowColumn (main_window, "MainRC", args, n);
  405. X
  406. X    /* make the status label */
  407. X    n = 0;
  408. X    XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  409. X    XtSetArg (args[n], XmNrecomputeSize, False); n++;
  410. X    status_w = XmCreateLabel (mrc_w, "Status", args, n);
  411. X    XtManageChild (status_w);
  412. X
  413. X    /* make a separator widget */
  414. X    n = 0;
  415. X    sep_w = XmCreateSeparator (mrc_w, "HSep2", args, n);
  416. X    XtManageChild (sep_w);
  417. X
  418. X    /* make the "NEW CIRCUMSTANCES" label */
  419. X    n = 0;
  420. X    XtSetArg (args[n], XmNrecomputeSize, False); n++;
  421. X    newcir_w = XmCreateLabel (mrc_w, "NewCir", args, n);
  422. X    XtManageChild(newcir_w);
  423. X
  424. X    /* make a separator widget */
  425. X    n = 0;
  426. X    sep_w = XmCreateSeparator (mrc_w, "HSep3", args, n);
  427. X    XtManageChild (sep_w);
  428. X
  429. X    /* make a horizontal r/c across the bottom.
  430. X     * fill it in with three vertical r/cs and the calendar, with
  431. X     * separators.
  432. X     */
  433. X
  434. X    n = 0;
  435. X    XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
  436. X    hrc_w = XmCreateRowColumn (mrc_w, "BottomRC", args, n);
  437. X    XtManageChild (hrc_w);
  438. X
  439. X    for (i = 0; i < 3; i++) {
  440. X        int f;
  441. X
  442. X        n = 0;
  443. X        rc_w = XmCreateRowColumn (hrc_w, "MainRC", args, n);
  444. X        XtManageChild (rc_w);
  445. X
  446. X        for (f = fmi[i]; f < fmi[i+1]; f++) {
  447. X        Field *fp = &mm_field_map[f];
  448. X        Widget f_w;
  449. X
  450. X        switch (fp->id) {
  451. X        case GAP: /* make a gap label */
  452. X            n = 0;
  453. X            w = XmCreateSeparator (rc_w, "GapSep", args, n);
  454. X            XtManageChild (w);
  455. X            n = 0;
  456. X            fp->pb_w = XmCreatePushButton (rc_w, "Gap", args, n);
  457. X            XtManageChild (fp->pb_w);
  458. X            set_xmstring (fp->pb_w, XmNlabelString, " ");
  459. X            continue;
  460. X        }
  461. X
  462. X        /* make a form */
  463. X        n = 0;
  464. X        f_w = XmCreateForm (rc_w, "MainF", args, n);
  465. X        XtManageChild (f_w);
  466. X
  467. X        /* make the pushbutton in the right half. */
  468. X        n = 0;
  469. X        XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  470. X        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  471. X        XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  472. X        XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  473. X        if (fp->name)
  474. X            XtSetArg (args[n], XmNuserData, fp->name); n++;
  475. X        fp->pb_w = XmCreatePushButton (f_w, "MainPB", args, n);
  476. X        if (fp->prompt || fp->name)
  477. X            XtAddCallback (fp->pb_w, XmNactivateCallback,
  478. X                            mm_activate_cb, fp);
  479. X        XtManageChild(fp->pb_w);
  480. X
  481. X        /* make the label in the left half */
  482. X        n = 0;
  483. X        str = XmStringCreateLtoR(fp->label, XmSTRING_DEFAULT_CHARSET);
  484. X        XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  485. X        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  486. X        XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  487. X        XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  488. X        XtSetArg (args[n], XmNrightWidget, fp->pb_w); n++;
  489. X        XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  490. X        XtSetArg (args[n], XmNlabelString, str); n++;
  491. X        w = XmCreateLabel (f_w, "MainLabel", args, n);
  492. X        XtManageChild(w);
  493. X        XmStringFree (str);
  494. X        }
  495. X
  496. X        /* make a separator widget */
  497. X        n = 0;
  498. X        XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
  499. X        sep_w = XmCreateSeparator (hrc_w, "VSep", args, n);
  500. X        XtManageChild (sep_w);
  501. X    }
  502. X
  503. X    /* make the calendar */
  504. X
  505. X    w = calm_create (hrc_w);
  506. X    XtManageChild (w);
  507. X
  508. X    /* make a separator widget */
  509. X    n = 0;
  510. X    sep_w = XmCreateSeparator (mrc_w, "HSep4", args, n);
  511. X    XtManageChild (sep_w);
  512. X
  513. X    /* put a wide and thick "go" button below all */
  514. X    n = 0;
  515. X    XtSetArg (args[n], XmNshowAsDefault, True); n++;
  516. X    XtSetArg (args[n], XmNrecomputeSize, False); n++;
  517. X    XtSetArg (args[n], XmNmarginTop, 3); n++;
  518. X    XtSetArg (args[n], XmNmarginBottom, 3); n++;
  519. X    go_w = XmCreatePushButton (mrc_w, "Update", args, n);
  520. X    XtAddCallback (go_w, XmNactivateCallback, mm_go_cb, 0);
  521. X    XtManageChild (go_w);
  522. X
  523. X    XtManageChild (mrc_w);
  524. X}
  525. X
  526. X/* set the initial stuff in the Now struct and looping params from the XEphem
  527. X * resources.
  528. X */
  529. Xstatic void
  530. Xread_default_resources()
  531. X{
  532. X    int i;
  533. X
  534. X    for (i = 0; i < XtNumber(keywords); i++) {
  535. X        char *dp = XGetDefault (XtD, myclass, keywords[i]);
  536. X        if (dp) {
  537. X        char buf[128];
  538. X        (void) sprintf (buf, "%s=%s", keywords[i], dp);
  539. X        if (crack_fieldset (buf) < 0) {
  540. X            printf ("Bad resource spec: %s", buf);
  541. X            exit (1);
  542. X        }
  543. X        }
  544. X    }
  545. X}
  546. X
  547. X/* get the widget associated with this _FID.
  548. X * We do some error checking.
  549. X */
  550. Xstatic Widget
  551. Xfw(fid)
  552. Xint fid;
  553. X{
  554. X    Field *fp;
  555. X
  556. X    if (fid < 0 || fid >= NFM || (fp = &mm_field_map[fid])->id != fid) {
  557. X        printf ("mainmenu:fw(): bad field id: %d\n", fid);
  558. X        exit(1);
  559. X    }
  560. X    return (fp->pb_w);
  561. X}
  562. X
  563. X/* go through all the buttons just pickable for plotting and set whether they
  564. X * should appear to look like buttons or just flat labels.
  565. X */
  566. Xstatic void
  567. Xmm_set_buttons (whether)
  568. Xint whether;
  569. X{
  570. X    static Arg look_like_button[] = {
  571. X        {XmNtopShadowColor, (XtArgVal) 0},
  572. X        {XmNbottomShadowColor, (XtArgVal) 0},
  573. X        {XmNfillOnArm, (XtArgVal) True},
  574. X    };
  575. X    static Arg look_like_label[] = {
  576. X        {XmNtopShadowColor, (XtArgVal) 0},
  577. X        {XmNbottomShadowColor, (XtArgVal) 0},
  578. X        {XmNfillOnArm, (XtArgVal) False},
  579. X    };
  580. X    static int called;
  581. X    Field *fp;
  582. X
  583. X    if (!called) {
  584. X        /* get baseline label and shadow appearances.
  585. X         * arbitrarily get these from the go_w button.
  586. X         */
  587. X        Pixel topshad, botshad, bgcol;
  588. X        Arg args[20];
  589. X        int n;
  590. X
  591. X        n = 0;
  592. X        XtSetArg (args[n], XmNtopShadowColor, &topshad); n++;
  593. X        XtSetArg (args[n], XmNbottomShadowColor, &botshad); n++;
  594. X        XtSetArg (args[n], XmNbackground, &bgcol); n++;
  595. X        XtGetValues (go_w, args, n);
  596. X
  597. X        look_like_button[0].value = topshad;
  598. X        look_like_button[1].value = botshad;
  599. X        look_like_label[0].value = bgcol;
  600. X        look_like_label[1].value = bgcol;
  601. X
  602. X        called = 1;
  603. X    }
  604. X
  605. X    for (fp = mm_field_map; fp < LFM; fp++)
  606. X        if (whether) {
  607. X          if (fp->name)
  608. X            XtSetValues(fp->pb_w, look_like_button,
  609. X                            XtNumber(look_like_button));
  610. X          else
  611. X            XtSetValues(fp->pb_w, look_like_label,
  612. X                            XtNumber(look_like_label));
  613. X        } else {
  614. X          if (fp->prompt)
  615. X            XtSetValues(fp->pb_w, look_like_button,
  616. X                            XtNumber(look_like_button));
  617. X          else
  618. X            XtSetValues(fp->pb_w, look_like_label,
  619. X                            XtNumber(look_like_label));
  620. X        }
  621. X}
  622. X
  623. X/* callback from any of the main menu buttons being activated.
  624. X * if we are currently selecting fields to plot and the field has a name
  625. X *   then inform all the potentially interested parties;
  626. X * else if the field has a prompt then ask the user for a new value.
  627. X */
  628. X/* ARGSUSED */
  629. Xstatic void
  630. Xmm_activate_cb (w, client, call)
  631. XWidget w;
  632. XXtPointer client;
  633. XXtPointer call;
  634. X{
  635. X    Field *fp = (Field *)client;
  636. X
  637. X    if (mm_selecting) {
  638. X        if (fp->name)
  639. X        register_selection (fp->name);
  640. X    } else {
  641. X        if (fp->prompt) {
  642. X        mm_set_pref_prompts (fp);
  643. X        prompt (fp);
  644. X        }
  645. X    }
  646. X}
  647. X
  648. X/* set up those prompts that depend in preferences.
  649. X */
  650. Xstatic void
  651. Xmm_set_pref_prompts(fp)
  652. XField *fp;
  653. X{
  654. X    switch (fp->id) {
  655. X    case UD_FID:
  656. X    case LD_FID:
  657. X        fp->prompt = fp->altp[pref_get(PREF_DATE_FORMAT)];
  658. X        break;
  659. X    case ELEV_FID:
  660. X    case TEMP_FID:
  661. X    case PRES_FID:
  662. X        fp->prompt = fp->altp[pref_get(PREF_UNITS)];
  663. X        break;
  664. X    }
  665. X}
  666. X
  667. X/* function called from the interval timer used to implement the
  668. X * auto repeat feature.
  669. X */
  670. X/* ARGSUSED */
  671. Xstatic void
  672. Xmm_timer_cb (client, id)
  673. XXtPointer client;
  674. XXtIntervalId *id;
  675. X{
  676. X    int waited_so_far = (int)client + 1;
  677. X
  678. X    mm_interval_id = 0;
  679. X
  680. X    if (waited_so_far < spause)
  681. X        mm_interval_id = XtAppAddTimeOut (xe_app, 1000, mm_timer_cb,
  682. X                            (XtPointer)waited_so_far);
  683. X    else
  684. X        mm_go();
  685. X}
  686. X
  687. X/* callback from the main "go" button being armed.
  688. X * if we are looping (as evidenced by an active timer) then stop, else go.
  689. X */
  690. X/* ARGSUSED */
  691. Xstatic void
  692. Xmm_go_cb (w, client, call)
  693. XWidget w;
  694. XXtPointer client;
  695. XXtPointer call;
  696. X{
  697. X    if (mm_interval_id != 0) {
  698. X        XtRemoveTimeOut (mm_interval_id);
  699. X        mm_interval_id = 0;
  700. X        redraw_screen (1);
  701. X        print_idle();
  702. X    } else {
  703. X        if (nstep > 1)
  704. X        print_running();
  705. X        mm_go();
  706. X    }
  707. X}
  708. X
  709. X/* increment, update all fields, and go again if more steps.
  710. X */
  711. Xstatic void
  712. Xmm_go()
  713. X{
  714. X    int srchdone;
  715. X
  716. X    /* increment time only if op didn't change cirumstances */
  717. X    if (!newcir)
  718. X        inc_mjd (&now, tminc);
  719. X
  720. X    nstep -= 1;
  721. X
  722. X    /* recalculate everything and update all the fields */
  723. X    redraw_screen(newcir);
  724. X    mm_newcir(0);
  725. X
  726. X    /* let searching functions change tminc and check for done */
  727. X    srchdone = srch_eval (mjd, &tminc) < 0;
  728. X    print_tminc(0); /* to show possibly new search increment */
  729. X
  730. X    /* update plot and listing files, now that all fields are up
  731. X     * to date and search function has been evaluated.
  732. X     */
  733. X    plot();
  734. X    listing();
  735. X
  736. X    /* stop loop to allow op to change parameters:
  737. X     * if a search evaluation converges (or errors out),
  738. X     * or if steps are done,
  739. X     * or if op hits any key.
  740. X     */
  741. X    newcir = 0;
  742. X    if (srchdone || nstep <= 0) {
  743. X
  744. X        /* update screen with the current stuff if stopped during
  745. X         * searching, unattended plotting or listing since last
  746. X         * redraw_screen() didn't.
  747. X         */
  748. X        if ((srchdone || plot_ison() || listing_ison()) && nstep > 0)
  749. X        redraw_screen (1);
  750. X
  751. X        /* return nstep to default of 1 */
  752. X        if (nstep <= 0) {
  753. X        nstep = 1;
  754. X        print_nstep (0);
  755. X        }
  756. X        print_idle();
  757. X    } else {
  758. X        mm_interval_id =
  759. X        XtAppAddTimeOut (xe_app, spause>0 ? 1000 : 120, mm_timer_cb, 0);
  760. X    }
  761. X}
  762. X
  763. Xstatic void
  764. Xprint_tminc(force)
  765. Xint force;
  766. X{
  767. X    static double last = -123.456;    /* anything unlikely */
  768. X
  769. X    if (force || tminc != last) {
  770. X        if (tminc == RTC)
  771. X        f_string (fw(STPSZ_FID), " RT CLOCK");
  772. X        else if (fabs(tminc) >= 24.0)
  773. X        f_double (fw(STPSZ_FID), "%6.4g dy", tminc/24.0);
  774. X        else
  775. X        f_signtime (fw(STPSZ_FID), tminc);
  776. X        last = tminc;
  777. X    }
  778. X}
  779. X
  780. Xstatic void
  781. Xprint_updating()
  782. X{
  783. X    print_status ("Updating...");
  784. X}
  785. X
  786. Xstatic void
  787. Xprint_idle()
  788. X{
  789. X    print_status ("Make changes as desired or select Update to run.");
  790. X    f_string (go_w, "Update");
  791. X}
  792. X
  793. Xstatic void
  794. Xprint_running()
  795. X{
  796. X    print_status ("Running... select Stop to stop.");
  797. X    f_string (go_w, "Stop");
  798. X}
  799. X
  800. Xstatic void
  801. Xprint_status (s)
  802. Xchar *s;
  803. X{
  804. X    static char *last_s;
  805. X
  806. X    if (s != last_s) {
  807. X        f_string (status_w, s);
  808. X        XFlush (XtD);
  809. X        last_s = s;
  810. X    }
  811. X}
  812. X
  813. Xstatic void
  814. Xprint_nstep(force)
  815. Xint force;
  816. X{
  817. X    static int last;
  818. X
  819. X    if (force || nstep != last) {
  820. X        char buf[16];
  821. X        (void) sprintf (buf, "%8d", nstep);
  822. X        f_string (fw(NSTEP_FID), buf);
  823. X        last = nstep;
  824. X    }
  825. X}
  826. X
  827. Xstatic void
  828. Xprint_spause(force)
  829. Xint force;
  830. X{
  831. X    static int last;
  832. X
  833. X    if (force || spause != last) {
  834. X        char buf[16];
  835. X        (void) sprintf (buf, "%8d", spause);
  836. X        f_string (fw(PAUSE_FID), buf);
  837. X        last = spause;
  838. X    }
  839. X}
  840. X
  841. X/* process a field spec in buf, either from config file or argv.
  842. X * return 0 if recognized ok, else -1.
  843. X */
  844. Xstatic
  845. Xcrack_fieldset (buf)
  846. Xchar *buf;
  847. X{
  848. X    int i;
  849. X
  850. X    for (i = 0; i < XtNumber(keywords); i++) {
  851. X        int l = strlen(keywords[i]);
  852. X        if (strncmp (buf, keywords[i], l) == 0) {
  853. X        buf += l+1;    /* skip keyword and its subsequent delimiter */
  854. X        break;
  855. X        }
  856. X    }
  857. X
  858. X    /* N.B. the switch entries must match the order in keywords[] */
  859. X    switch (i) {
  860. X    case 0:  (void) chg_fld (buf, &mm_field_map[EPOCH_FID]); break;
  861. X    case 1:  (void) chg_fld (buf, &mm_field_map[ELEV_FID]); break;
  862. X    case 2:  (void) chg_fld (buf, &mm_field_map[JD_FID]); break;
  863. X    case 3:  (void) chg_fld (buf, &mm_field_map[LAT_FID]); break;
  864. X    case 4:  (void) chg_fld (buf, &mm_field_map[LONG_FID]); break;
  865. X    case 5:  (void) chg_fld (buf, &mm_field_map[NSTEP_FID]); break;
  866. X    case 6:  (void) chg_fld (buf, &mm_field_map[PAUSE_FID]); break;
  867. X    case 7:  (void) chg_fld (buf, &mm_field_map[PRES_FID]); break;
  868. X    case 8:  (void) chg_fld (buf, &mm_field_map[STPSZ_FID]); break;
  869. X    case 9:  (void) chg_fld (buf, &mm_field_map[TEMP_FID]); break;
  870. X    case 10: (void) chg_fld (buf, &mm_field_map[TZN_FID]); break;
  871. X    case 11: (void) chg_fld (buf, &mm_field_map[TZONE_FID]); break;
  872. X    case 12: (void) chg_fld (buf, &mm_field_map[UD_FID]); break;
  873. X    case 13: (void) chg_fld (buf, &mm_field_map[UT_FID]); break;
  874. X    case 14: (void) chg_fld (buf, &mm_field_map[DIP_FID]); break;
  875. X    case 15: (void) chg_fld (buf, &mm_field_map[LD_FID]); break;
  876. X    case 16: (void) chg_fld (buf, &mm_field_map[LT_FID]); break;
  877. X    case 17: (void) chg_fld (buf, &mm_field_map[LST_FID]); break;
  878. X    default: return (-1);
  879. X    }
  880. X    return (0);
  881. X}
  882. X
  883. X/* react to the field at *fp according to the string input at bp.
  884. X * crack the buffer and update the corresponding (global) variable(s)
  885. X * or do whatever a pick at that field should do.
  886. X * return 1 if we change a field that invalidates any of the times or
  887. X * to update all related fields.
  888. X */
  889. Xstatic
  890. Xchg_fld (bp, fp)
  891. Xchar *bp;
  892. XField *fp;
  893. X{
  894. X    int deghrs = 0, mins = 0, secs = 0;
  895. X    int new = 0;
  896. X    double tmp;
  897. X
  898. X    switch (fp->id) {
  899. X    case JD_FID:
  900. X        if (bp[0] == 'n' || bp[0] == 'N')
  901. X        time_fromsys (&now);
  902. X        else
  903. X        mjd = atof(bp) - MJD0;
  904. X        set_t0 (&now);
  905. X        new = 1;
  906. X        break;
  907. X    case UD_FID:
  908. X        if (bp[0] == 'n' || bp[0] == 'N')
  909. X        time_fromsys (&now);
  910. X        else {
  911. X        double day, newmjd0;
  912. X        int month, year;
  913. X
  914. X        mjd_cal (mjd, &month, &day, &year); /* init with now */
  915. X        f_sscandate (bp, pref_get(PREF_DATE_FORMAT),
  916. X                            &month, &day, &year);
  917. X        cal_mjd (month, day, year, &newmjd0);
  918. X
  919. X        /* if don't give a fractional part to days
  920. X         * then retain current hours.
  921. X         */
  922. X        if ((long)day == day)
  923. X            mjd = newmjd0 + mjd_hr(mjd)/24.0;
  924. X        else
  925. X            mjd = newmjd0;
  926. X        }
  927. X        set_t0 (&now);
  928. X        new = 1;
  929. X        break;
  930. X    case UT_FID:
  931. X        if (bp[0] == 'n' || bp[0] == 'N')
  932. X        time_fromsys (&now);
  933. X        else {
  934. X        double newutc = (mjd-mjd_day(mjd)) * 24.0;
  935. X        f_dec_sexsign (newutc, °hrs, &mins, &secs);
  936. X        f_sscansex (bp, °hrs, &mins, &secs);
  937. X        sex_dec (deghrs, mins, secs, &newutc);
  938. X        mjd = mjd_day(mjd) + newutc/24.0;
  939. X        }
  940. X        set_t0 (&now);
  941. X        new = 1;
  942. X        break;
  943. X    case LD_FID:
  944. X        if (bp[0] == 'n' || bp[0] == 'N')
  945. X        time_fromsys (&now);
  946. X        else {
  947. X        double day, newlmjd0;
  948. X        int month, year;
  949. X
  950. X        mjd_cal (mjd-tz/24.0, &month, &day, &year); /* now */
  951. X        f_sscandate (bp, pref_get(PREF_DATE_FORMAT),
  952. X                            &month, &day, &year);
  953. X        cal_mjd (month, day, year, &newlmjd0);
  954. X
  955. X        /* if don't give a fractional part to days
  956. X         * then retain current hours.
  957. X         */
  958. X        if ((long)day == day)
  959. X            mjd = newlmjd0 + mjd_hr(mjd-tz/24.0)/24.0;
  960. X        else
  961. X            mjd = newlmjd0;
  962. X        mjd += tz/24.0;
  963. X        }
  964. X        set_t0 (&now);
  965. X        new = 1;
  966. X        break;
  967. X    case LT_FID:
  968. X        if (bp[0] == 'n' || bp[0] == 'N')
  969. X        time_fromsys (&now);
  970. X        else {
  971. X        double newlt = (mjd-mjd_day(mjd)) * 24.0 - tz;
  972. X        range (&newlt, 24.0);
  973. X        f_dec_sexsign (newlt, °hrs, &mins, &secs);
  974. X        f_sscansex (bp, °hrs, &mins, &secs);
  975. X        sex_dec (deghrs, mins, secs, &newlt);
  976. X        mjd = mjd_day(mjd-tz/24.0) + (newlt + tz)/24.0;
  977. X        }
  978. X        set_t0 (&now);
  979. X        new = 1;
  980. X        break;
  981. X    case LST_FID:
  982. X        if (bp[0] == 'n' || bp[0] == 'N')
  983. X        time_fromsys (&now);
  984. X        else {
  985. X        double lst, utc;
  986. X        now_lst (&now, &lst);
  987. X        f_dec_sexsign (lst, °hrs, &mins, &secs);
  988. X        f_sscansex (bp, °hrs, &mins, &secs);
  989. X        sex_dec (deghrs, mins, secs, &lst);
  990. X        lst -= radhr(lng); /* convert to gst */
  991. X        range (&lst, 24.0);
  992. X        gst_utc (mjd_day(mjd), lst, &utc);
  993. X        mjd = mjd_day(mjd) + utc/24.0;
  994. X        }
  995. X        set_t0 (&now);
  996. X        new = 1;
  997. X        break;
  998. X    case TZN_FID:
  999. X        (void) strncpy (tznm, bp, sizeof(tznm)-1);
  1000. X        new = 1;
  1001. X        break;
  1002. X    case TZONE_FID:
  1003. X        f_dec_sexsign (tz, °hrs, &mins, &secs);
  1004. X        f_sscansex (bp, °hrs, &mins, &secs);
  1005. X        sex_dec (deghrs, mins, secs, &tz);
  1006. X        new = 1;
  1007. X        break;
  1008. X    case LONG_FID:
  1009. X        f_dec_sexsign (-raddeg(lng), °hrs, &mins, &secs);
  1010. X        f_sscansex (bp, °hrs, &mins, &secs);
  1011. X        sex_dec (deghrs, mins, secs, &lng);
  1012. X        lng = degrad (-lng);         /* want - radians west */
  1013. X        new = 1;
  1014. X        break;
  1015. X    case LAT_FID:
  1016. X        f_dec_sexsign (raddeg(lat), °hrs, &mins, &secs);
  1017. X        f_sscansex (bp, °hrs, &mins, &secs);
  1018. X        sex_dec (deghrs, mins, secs, &lat);
  1019. X        lat = degrad (lat);
  1020. X        new = 1;
  1021. X        break;
  1022. X    case ELEV_FID:
  1023. X        if (sscanf (bp, "%lf", &elev) == 1) {
  1024. X        if (pref_get(PREF_UNITS) == PREF_ENGLISH)
  1025. X            elev /= (ERAD*FTPM);    /* ft to earth radii */
  1026. X        else
  1027. X            elev /= ERAD;        /* m to earth radii */
  1028. X        new = 1;
  1029. X        }
  1030. X        break;
  1031. X    case DIP_FID:
  1032. X        if (sscanf (bp, "%lf", &tmp) == 1) {
  1033. X        if (tmp < 0)
  1034. X            xe_msg ("Twilight dip must be at least 0", 1);
  1035. X        else {
  1036. X            dip = degrad(tmp);
  1037. X            mm_twilight (1);
  1038. X        }
  1039. X        }
  1040. X        break;
  1041. X    case NSTEP_FID:
  1042. X        (void) sscanf (bp, "%d", &nstep);
  1043. X        print_nstep (0);
  1044. X        break;
  1045. X    case PAUSE_FID:
  1046. X        (void) sscanf (bp, "%d", &spause);
  1047. X        print_spause (0);
  1048. X        break;
  1049. X    case TEMP_FID:
  1050. X        if (sscanf (bp, "%lf", &temp) == 1) {
  1051. X        if (pref_get(PREF_UNITS) == PREF_ENGLISH)
  1052. X            temp = 5./9.*(temp - 32.0);    /* want degs C */
  1053. X        new = 1;
  1054. X        }
  1055. X        break;
  1056. X    case PRES_FID:
  1057. X        if (sscanf (bp, "%lf", &pressure) == 1) {
  1058. X        if (pref_get(PREF_UNITS) == PREF_ENGLISH)
  1059. X            pressure *= 33.86;        /* want mBar */
  1060. X        new = 1;
  1061. X        }
  1062. X        break;
  1063. X    case EPOCH_FID:
  1064. X        if (bp[0] == 'e' || bp[0] == 'E')
  1065. X        epoch = EOD;
  1066. X        else {
  1067. X        double e;
  1068. X        e = atof(bp);
  1069. X        year_mjd (e, &epoch);
  1070. X        }
  1071. X        new = 1;
  1072. X        break;
  1073. X    case STPSZ_FID:
  1074. X        if (bp[0] == 'r' || bp[0] == 'R')
  1075. X        tminc = RTC;
  1076. X        else {
  1077. X        char lastc = bp[strlen(bp)-1];
  1078. X        if (lastc == 'd' || lastc == 'D') {
  1079. X            /* ends in d so treat as a number of days */
  1080. X            double x;
  1081. X            if (sscanf (bp, "%lf", &x) == 1)
  1082. X            tminc = x * 24.0;
  1083. X        } else if (lastc == 's' || lastc == 'S') {
  1084. X            /* ends in s so treat as a number of sidereal days */
  1085. X            double x;
  1086. X            if (sscanf (bp, "%lf", &x) == 1)
  1087. X            tminc = x * 24.0 * SIDRATE;
  1088. X        } else {
  1089. X            if (tminc == RTC)
  1090. X            deghrs = mins = secs = 0;
  1091. X            else
  1092. X            f_dec_sexsign (tminc, °hrs, &mins, &secs);
  1093. X            f_sscansex (bp, °hrs, &mins, &secs);
  1094. X            sex_dec (deghrs, mins, secs, &tminc);
  1095. X        }
  1096. X        }
  1097. X        print_tminc(0);
  1098. X        set_t0 (&now);
  1099. X        break;
  1100. X    default:
  1101. X        printf ("chg_fld: unknown id: 0x%x\n", fp->id);
  1102. X        exit (1);
  1103. X    }
  1104. X
  1105. X    return (new);
  1106. X}
  1107. X
  1108. X/* user typed OK to a prompt for fp. get his new value and use it */
  1109. Xstatic void
  1110. Xprompt_ok_cb (w, client, call)
  1111. XWidget w;
  1112. XXtPointer client;
  1113. XXtPointer call;
  1114. X{
  1115. X    XmSelectionBoxCallbackStruct *s = (XmSelectionBoxCallbackStruct *)call;
  1116. X    Field *fp = (Field *)client;
  1117. X    char *text, *tmptext;
  1118. X    
  1119. X    switch (s->reason) {
  1120. X    case XmCR_OK:
  1121. X        get_xmstring(w, XmNtextString, &text);
  1122. X        break;
  1123. X    case XmCR_APPLY:    /* used for several special short cuts */
  1124. X        switch (fp->id) {
  1125. X        case STPSZ_FID:
  1126. X        tmptext = "r";    /* command to mean "RTC" */
  1127. X        break;
  1128. X        case EPOCH_FID:
  1129. X        tmptext = "e";    /* command to mean "EOD" */
  1130. X        break;
  1131. X        case NSTEP_FID:
  1132. X        tmptext = "99999999";    /* command to mean "Many steps" */
  1133. X        break;
  1134. X        case PAUSE_FID:
  1135. X        tmptext = "0";    /* command to mean "no pause" */
  1136. X        break;
  1137. X        case PRES_FID:
  1138. X        tmptext = "0";    /* command to mean "no refraction" */
  1139. X        break;
  1140. X        case UD_FID:
  1141. X        case JD_FID:
  1142. X        case LST_FID:
  1143. X        case LD_FID:
  1144. X        case LT_FID:
  1145. X        tmptext = "n";    /* command to mean "Now" */
  1146. X        break;
  1147. X        case UT_FID:
  1148. X        tmptext = "0:00:00";    /* command to mean midnight */
  1149. X        break;
  1150. X        default:
  1151. X        printf ("mainmenu:prompt_ok_cb: bad fid=%d\n", fp->id);
  1152. X        exit (1);
  1153. X        break;
  1154. X        }
  1155. X        (void) strcpy (text = XtMalloc(strlen(tmptext)+1), tmptext);
  1156. X        break;
  1157. X    default:
  1158. X        return;
  1159. X    }
  1160. X
  1161. X    if (chg_fld (text, fp)) {
  1162. X        mm_now (1);
  1163. X        mm_newcir(1);
  1164. X        newcir = 1;
  1165. X    }
  1166. X    XtDestroyWidget (w);
  1167. X    XtFree (text);
  1168. X}
  1169. X
  1170. X/* put up a prompt dialog near the cursor to ask about fp.
  1171. X * use the Apply button for special shortcuts.
  1172. X */
  1173. Xstatic void
  1174. Xprompt (fp)
  1175. XField *fp;
  1176. X{
  1177. X    Widget w, sw, hw, aw;
  1178. X    XmString str, title;
  1179. X    Arg args[20];
  1180. X    int n;
  1181. X    
  1182. X    str = XmStringCreateLtoR (fp->prompt, XmSTRING_DEFAULT_CHARSET);
  1183. X    title = XmStringCreateLtoR ("xephem Prompt", XmSTRING_DEFAULT_CHARSET);
  1184. X    n = 0;
  1185. X    XtSetArg(args[n], XmNselectionLabelString, str);  n++;
  1186. X    XtSetArg(args[n], XmNdefaultPosition, False);  n++;
  1187. X    XtSetArg(args[n], XmNdialogTitle, title);  n++;
  1188. X    XtSetArg(args[n], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL);  n++;
  1189. X    sw = XmCreatePromptDialog(toplevel_w, "MainPrompt", args, n);
  1190. X    XtAddCallback (sw, XmNmapCallback, prompt_map_cb, NULL);
  1191. X    XtAddCallback (sw, XmNokCallback, prompt_ok_cb, fp);
  1192. X    XmStringFree (str);
  1193. X    XmStringFree (title);
  1194. X
  1195. X    /* we don't use the Help button at all. */
  1196. X    hw = XmSelectionBoxGetChild (sw, XmDIALOG_HELP_BUTTON);
  1197. X    XtUnmanageChild (hw);
  1198. X
  1199. X    /* we don't use the Apply button except for the special shortcuts */
  1200. X    aw = XmSelectionBoxGetChild (sw, XmDIALOG_APPLY_BUTTON);
  1201. X    XtUnmanageChild (aw);
  1202. X
  1203. X    /* use the Apply button for several special shortcuts */
  1204. X    switch (fp->id) {
  1205. X    case JD_FID: case UD_FID:
  1206. X    case LD_FID: case LT_FID: case LST_FID:
  1207. X        XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1208. X        XtManageChild (aw);
  1209. X        set_xmstring (sw, XmNapplyLabelString, "Now");
  1210. X        break;
  1211. X    case UT_FID:
  1212. X        XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1213. X        XtManageChild (aw);
  1214. X        set_xmstring (sw, XmNapplyLabelString, "0:00:00");
  1215. X        break;
  1216. X    case STPSZ_FID:
  1217. X        XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1218. X        XtManageChild (aw);
  1219. X        set_xmstring (sw, XmNapplyLabelString, "RTC");
  1220. X        break;
  1221. X    case EPOCH_FID:
  1222. X        XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1223. X        XtManageChild (aw);
  1224. X        set_xmstring (sw, XmNapplyLabelString, "Of Date");
  1225. X        break;
  1226. X    case NSTEP_FID:
  1227. X        XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1228. X        XtManageChild (aw);
  1229. X        set_xmstring (sw, XmNapplyLabelString, "Many");
  1230. X        break;
  1231. X    case PAUSE_FID:
  1232. X        XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1233. X        XtManageChild (aw);
  1234. X        set_xmstring (sw, XmNapplyLabelString, "No Pause");
  1235. X        break;
  1236. X    case PRES_FID:
  1237. X        XtAddCallback (sw, XmNapplyCallback, prompt_ok_cb, fp);
  1238. X        XtManageChild (aw);
  1239. X        set_xmstring (sw, XmNapplyLabelString, "No Refraction");
  1240. X        break;
  1241. X    }
  1242. X
  1243. X    XtManageChild (sw);
  1244. X
  1245. X#if XmVersion >= 1001
  1246. X    w = XmSelectionBoxGetChild (sw, XmDIALOG_TEXT);
  1247. X    XmProcessTraversal (w, XmTRAVERSE_CURRENT);
  1248. X    XmProcessTraversal (w, XmTRAVERSE_CURRENT); /* yes, twice!! */
  1249. X#endif
  1250. X}
  1251. X
  1252. X/* print all the time/date/where related stuff: the Now structure.
  1253. X * print in a nice order, based on the field locations, as much as possible.
  1254. X */
  1255. Xstatic void
  1256. Xmm_now (all)
  1257. Xint all;
  1258. X{
  1259. X    char buf[32];
  1260. X    double lmjd = mjd - tz/24.0;
  1261. X    double jd = mjd + MJD0;
  1262. X    double tmp;
  1263. X
  1264. X    (void) sprintf (buf, "%-3.3s", tznm);
  1265. X    f_string (fw(TZN_FID), buf);
  1266. X    f_time (fw(LT_FID), mjd_hr(lmjd));
  1267. X    f_date (fw(LD_FID), lmjd);
  1268. X
  1269. X    f_time (fw(UT_FID), mjd_hr(mjd));
  1270. X    f_date (fw(UD_FID), mjd);
  1271. X
  1272. X    f_double (fw(JD_FID), "%14.5f", jd);
  1273. X
  1274. X    now_lst (&now, &tmp);
  1275. X    f_time (fw(LST_FID), tmp);
  1276. X
  1277. X    if (all) {
  1278. X        f_gangle (fw(LAT_FID), lat);
  1279. X        f_gangle (fw(LONG_FID), -lng);    /* + west */
  1280. X
  1281. X        if (pref_get(PREF_UNITS) == PREF_ENGLISH) {
  1282. X        tmp = elev * (ERAD*FTPM);    /* want ft, not earth radii*/
  1283. X        f_double (fw(ELEV_FID), "%8.1f ft", tmp);
  1284. X        } else {
  1285. X        tmp = elev * ERAD;        /* want m, not earth radii */
  1286. X        f_double (fw(ELEV_FID), "%8.1f m", tmp);
  1287. X        }
  1288. X
  1289. X        tmp = temp;
  1290. X        if (pref_get(PREF_UNITS) == PREF_ENGLISH) {
  1291. X        tmp = 9.*temp/5. + 32.0;   /* want to see degrees F, not C */
  1292. X#ifdef XK_degree
  1293. X        (void) sprintf (buf, "%%5.1f %cF", XK_degree);
  1294. X        } else
  1295. X        (void) sprintf (buf, "%%5.1f %cC", XK_degree);
  1296. X#else
  1297. X        (void) sprintf (buf, "%%5.1f F");
  1298. X        } else
  1299. X        (void) sprintf (buf, "%%5.1f C");
  1300. X#endif
  1301. X        f_double (fw(TEMP_FID), buf, tmp);
  1302. X
  1303. X        tmp = pressure;
  1304. X        if (pref_get(PREF_UNITS) == PREF_ENGLISH) {
  1305. X        tmp /= 33.86;    /* want to see in. Hg, not mBar */
  1306. X        f_double (fw(PRES_FID), "%5.2f in", tmp);
  1307. X        } else {
  1308. X        f_double (fw(PRES_FID), "%5.0f mB", tmp);
  1309. X        }
  1310. X
  1311. X        f_signtime (fw(TZONE_FID), tz);
  1312. X
  1313. X        if (epoch == EOD)
  1314. X        f_string (fw(EPOCH_FID), "Of Date");
  1315. X        else {
  1316. X        mjd_year (epoch, &tmp);
  1317. X        f_double (fw(EPOCH_FID), "%8.1f", tmp);
  1318. X        }
  1319. X    }
  1320. X
  1321. X    if (f_ison())
  1322. X        calm_set (&now);
  1323. X}
  1324. X
  1325. X/* display dawn/dusk/length-of-night times.
  1326. X */
  1327. X/* ARGSUSED */
  1328. Xstatic void
  1329. Xmm_twilight (force)
  1330. Xint force;
  1331. X{
  1332. X    double dusk, dawn;
  1333. X    int status;
  1334. X    char buf[64];
  1335. X
  1336. X    twilight_cir (&now, dip, &dawn, &dusk, &status);
  1337. X    if (status & (RS_NORISE|RS_RISERR|RS_NOSET|RS_CIRCUMPOLAR|RS_NEVERUP)) {
  1338. X        static char nope[] = "-----";
  1339. X        f_string (fw(DAWN_FID), nope);
  1340. X        f_string (fw(DUSK_FID), nope);
  1341. X        f_string (fw(LON_FID), nope);
  1342. X    } else {
  1343. X        double tmp;
  1344. X        f_mtime (fw(DAWN_FID), dawn);
  1345. X        f_mtime (fw(DUSK_FID), dusk);
  1346. X        tmp = dawn - dusk; range (&tmp, 24.0);
  1347. X        f_mtime (fw(LON_FID), tmp);
  1348. X    }
  1349. X#ifdef XK_degree
  1350. X    (void) sprintf (buf, "%%g%c", XK_degree);
  1351. X#else
  1352. X    (void) sprintf (buf, "%%g degs");
  1353. X#endif
  1354. X    f_double (fw(DIP_FID), buf, raddeg(dip));
  1355. X}
  1356. X
  1357. Xstatic void
  1358. Xmm_newcir (y)
  1359. Xint y;
  1360. X{
  1361. X    static char ncmsg[] = "NEW CIRCUMSTANCES";
  1362. X    static char nomsg[] = "                 ";
  1363. X    static int last_y = -1;
  1364. X
  1365. X    if (y != last_y) {
  1366. X        f_string (newcir_w, y ? ncmsg : nomsg);
  1367. X        last_y = y;
  1368. X    }
  1369. X}
  1370. END_OF_FILE
  1371.   if test 35808 -ne `wc -c <'mainmenu.c'`; then
  1372.     echo shar: \"'mainmenu.c'\" unpacked with wrong size!
  1373.   fi
  1374.   # end of 'mainmenu.c'
  1375. fi
  1376. if test -f 'satmenu.c' -a "${1}" != "-c" ; then 
  1377.   echo shar: Will not clobber existing file \"'satmenu.c'\"
  1378. else
  1379.   echo shar: Extracting \"'satmenu.c'\" \(36774 characters\)
  1380.   sed "s/^X//" >'satmenu.c' <<'END_OF_FILE'
  1381. X/* code to manage the stuff on the "saturn" menu.
  1382. X */
  1383. X
  1384. X#include <stdio.h>
  1385. X#include <ctype.h>
  1386. X#include <math.h>
  1387. X#if defined(__STDC__)
  1388. X#include <stdlib.h>
  1389. X#endif
  1390. X#include <X11/Xlib.h>
  1391. X#include <Xm/Xm.h>
  1392. X#include <Xm/Form.h>
  1393. X#include <Xm/Frame.h>
  1394. X#include <Xm/Label.h>
  1395. X#include <Xm/PushB.h>
  1396. X#include <Xm/Scale.h>
  1397. X#include <Xm/RowColumn.h>
  1398. X#include <Xm/DrawingA.h>
  1399. X#include <Xm/ToggleB.h>
  1400. X#include "astro.h"
  1401. X#include "circum.h"
  1402. X
  1403. X#if defined(__STDC__) || defined(__cplusplus)
  1404. X#define P_(s) s
  1405. X#else
  1406. X#define P_(s) ()
  1407. X#endif
  1408. X
  1409. Xextern Now *mm_get_now P_((void));
  1410. Xextern int any_ison P_((void));
  1411. Xextern void f_double P_((Widget w, char *fmt, double f));
  1412. Xextern void get_something P_((Widget w, char *resource, char *value));
  1413. Xextern void register_selection P_((char *name));
  1414. Xextern void set_xmstring P_((Widget w, char *resource, char *txt));
  1415. Xextern void timestamp P_((Now *np, Widget w));
  1416. X
  1417. Xvoid sm_manage P_((void));
  1418. Xint sm_ison P_((void));
  1419. Xvoid sm_selection_mode P_((int whether));
  1420. Xvoid sm_cursor P_((Cursor c));
  1421. Xstatic void sm_create_form_w P_((void));
  1422. Xstatic void sm_set_buttons P_((int whether));
  1423. Xstatic void sm_set_a_button P_((Widget pbw, int whether));
  1424. Xstatic void sm_bigd_cb P_((Widget w, XtPointer client, XtPointer call));
  1425. Xstatic void sm_tags_cb P_((Widget w, XtPointer client, XtPointer call));
  1426. Xstatic void sm_scale_cb P_((Widget w, XtPointer client, XtPointer call));
  1427. Xstatic void sm_activate_cb P_((Widget w, XtPointer client, XtPointer call));
  1428. Xstatic void sm_close_cb P_((Widget w, XtPointer client, XtPointer call));
  1429. Xstatic void sm_da_exp_cb P_((Widget w, XtPointer client, XtPointer call));
  1430. Xvoid sm_update P_((Now *np, int how_much));
  1431. Xstatic double polynom P_((double jd, double a[4]));
  1432. Xstatic void saturn P_((double jd, double L_, double a_, double e_, double i_, double omega_, double Omega_, double M_, double *r_p, double *l_p, double *b_p, double *C_p));
  1433. Xstatic void anom_calc P_((double M, double e, double *E_p, double *nu_p));
  1434. Xstatic double obl_jd P_((double jd));
  1435. X
  1436. X#undef P_
  1437. X
  1438. Xextern Widget toplevel_w;
  1439. X#define    XtD    XtDisplay(toplevel_w)
  1440. X
  1441. Xstatic Widget satform_w;    /* main form */
  1442. Xstatic Widget sda_w;        /* drawing area */
  1443. Xstatic Widget ringt_w;        /* widget containing ring tilt */
  1444. Xstatic Widget scale_w;        /* size scale */
  1445. Xstatic Widget dt_w;        /* date/time stamp widget */
  1446. X#define    NM    8        /* number of moons */
  1447. Xstatic Widget    s_w[NM][4];    /* the data display widgets */
  1448. Xenum {X, Y, Z, MAG};        /* s_w column index */
  1449. Xstatic int sm_selecting;    /* set while our fields are being selected */
  1450. Xstatic int bigdots;        /* whether we want big dots */
  1451. Xstatic int s_tags;        /* whether we want tags on the drawing */
  1452. X
  1453. X#define    MAXSCALE    20.0    /* max sclae mag factor */
  1454. X
  1455. Xstatic struct MoonNames {
  1456. X    char *full;
  1457. X    char *tag;
  1458. X} mnames[NM] = {
  1459. X    {"Mimas",    "I"},
  1460. X    {"Enceladus","II"},
  1461. X    {"Tethys",    "III"},
  1462. X    {"Dione",    "IV"},
  1463. X    {"Rhea",    "V"},
  1464. X    {"Titan",    "VI"},
  1465. X    {"Hyperion","VII"},
  1466. X    {"Iapetus",    "VIII"},
  1467. X};
  1468. X
  1469. X/* called when the saturn menu is activated via the main menu pulldown.
  1470. X * if never called before, create and manage all the widgets as a child of a
  1471. X * form. otherwise, just toggle whether the form is managed.
  1472. X */
  1473. Xvoid
  1474. Xsm_manage ()
  1475. X{
  1476. X    if (!satform_w)
  1477. X        sm_create_form_w();
  1478. X    
  1479. X    if (XtIsManaged(satform_w))
  1480. X        XtUnmanageChild (satform_w);
  1481. X    else {
  1482. X        XtManageChild (satform_w);
  1483. X        sm_set_buttons(sm_selecting);
  1484. X        /* rely on expose to do the first draw */
  1485. X    }
  1486. X}
  1487. X
  1488. Xsm_ison()
  1489. X{
  1490. X    return (satform_w && XtIsManaged(satform_w));
  1491. X}
  1492. X
  1493. X/* called by other menus as they want to hear from our buttons or not.
  1494. X * the "on"s and "off"s stack - only really redo the buttons if it's the
  1495. X * first on or the last off.
  1496. X */
  1497. Xvoid
  1498. Xsm_selection_mode (whether)
  1499. Xint whether;    /* whether setting up for plotting or for not plotting */
  1500. X{
  1501. X    sm_selecting += whether ? 1 : -1;
  1502. X
  1503. X    if (satform_w && XtIsManaged(satform_w))
  1504. X        if (whether && sm_selecting == 1     /* first one to want on */
  1505. X        || !whether && sm_selecting == 0 /* last one to want off */)
  1506. X        sm_set_buttons (whether);
  1507. X}
  1508. X
  1509. X/* called to put up or remove the watch cursor.  */
  1510. Xvoid
  1511. Xsm_cursor (c)
  1512. XCursor c;
  1513. X{
  1514. X    Window win;
  1515. X
  1516. X    if (satform_w && (win = XtWindow(satform_w))) {
  1517. X        Display *dsp = XtDisplay(satform_w);
  1518. X        if (c)
  1519. X        XDefineCursor (dsp, win, c);
  1520. X        else
  1521. X        XUndefineCursor (dsp, win);
  1522. X    }
  1523. X}
  1524. X
  1525. Xstatic void
  1526. Xsm_create_form_w()
  1527. X{
  1528. X    Widget w;
  1529. X    Widget f_w, fr_w, frame_w, r_w, title_w, col_w;
  1530. X    XmString str;
  1531. X    Arg args[20];
  1532. X    int n;
  1533. X    int i;
  1534. X
  1535. X    /* create form */
  1536. X    n = 0;
  1537. X    XtSetArg (args[n], XmNautoUnmanage, False); n++;
  1538. X    XtSetArg (args[n], XmNdefaultPosition, False); n++;
  1539. X    XtSetArg (args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
  1540. X    satform_w = XmCreateFormDialog (toplevel_w, "Saturn", args, n);
  1541. X
  1542. X    /* set some stuff in the parent DialogShell.
  1543. X     * setting XmNdialogTitle in the Form didn't work..
  1544. X     */
  1545. X    n = 0;
  1546. X    XtSetArg (args[n], XmNtitle, "xephem Saturn Table"); n++;
  1547. X    XtSetValues (XtParent(satform_w), args, n);
  1548. X
  1549. X    /* make top row for ring tilt info */
  1550. X
  1551. X    n = 0;
  1552. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1553. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1554. X    XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  1555. X    XtSetArg (args[n], XmNrightPosition, 50); n++;
  1556. X    r_w = XmCreatePushButton (satform_w, "SatTiltMsg", args, n);
  1557. X    XtManageChild (r_w);
  1558. X    set_xmstring (r_w, XmNlabelString, "Ring tilt (degs):");
  1559. X    sm_set_a_button (r_w, False);
  1560. X
  1561. X    n = 0;
  1562. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1563. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1564. X    XtSetArg (args[n], XmNleftPosition, 50); n++;
  1565. X    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1566. X    XtSetArg (args[n], XmNuserData, "Saturn.Tilt"); n++;
  1567. X    w = ringt_w = XmCreatePushButton(satform_w, "SatTilt", args, n);
  1568. X    XtAddCallback(w, XmNactivateCallback, sm_activate_cb, 0);
  1569. X    XtManageChild (w);
  1570. X
  1571. X    /* make table title label */
  1572. X
  1573. X    n = 0;
  1574. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1575. X    XtSetArg (args[n], XmNtopWidget, r_w); n++;
  1576. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1577. X    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1578. X    title_w = XmCreateLabel (satform_w, "SatLab", args, n);
  1579. X    XtManageChild (title_w);
  1580. X    set_xmstring (title_w, XmNlabelString,
  1581. X                " \nMoon positions -- in Saturn Radii");
  1582. X
  1583. X    /* make the moon table, one column at a time */
  1584. X
  1585. X    /* moon designator column */
  1586. X
  1587. X    n = 0;
  1588. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1589. X    XtSetArg (args[n], XmNtopWidget, title_w); n++;
  1590. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1591. X    XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_BEGINNING); n++;
  1592. X    XtSetArg (args[n], XmNisAligned, True); n++;
  1593. X    col_w = XmCreateRowColumn (satform_w, "SatDes", args, n);
  1594. X    XtManageChild (col_w);
  1595. X
  1596. X        n = 0;
  1597. X        w = XmCreatePushButton (col_w, " ", args, n);
  1598. X        XtManageChild (w);
  1599. X        sm_set_a_button (w, False);
  1600. X
  1601. X        for (i = 0; i < NM; i++) {
  1602. X        n = 0;
  1603. X        w = XmCreatePushButton (col_w, mnames[i].tag, args, n);
  1604. X        XtManageChild (w);
  1605. X        sm_set_a_button (w, False);
  1606. X        }
  1607. X
  1608. X    /* moon name column */
  1609. X
  1610. X    n = 0;
  1611. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1612. X    XtSetArg (args[n], XmNtopWidget, title_w); n++;
  1613. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1614. X    XtSetArg (args[n], XmNleftPosition, 8); n++;
  1615. X    XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_BEGINNING); n++;
  1616. X    XtSetArg (args[n], XmNisAligned, True); n++;
  1617. X    col_w = XmCreateRowColumn (satform_w, "SatName", args, n);
  1618. X    XtManageChild (col_w);
  1619. X
  1620. X        n = 0;
  1621. X        w = XmCreatePushButton (col_w, " ", args, n);
  1622. X        XtManageChild (w);
  1623. X        sm_set_a_button (w, False);
  1624. X
  1625. X        for (i = 0; i < NM; i++) {
  1626. X        n = 0;
  1627. X        w = XmCreatePushButton (col_w, mnames[i].full, args, n);
  1628. X        XtManageChild (w);
  1629. X        sm_set_a_button (w, False);
  1630. X        }
  1631. X
  1632. X    /* moon X column */
  1633. X
  1634. X    n = 0;
  1635. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1636. X    XtSetArg (args[n], XmNtopWidget, title_w); n++;
  1637. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1638. X    XtSetArg (args[n], XmNleftPosition, 30); n++;
  1639. X    XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  1640. X    XtSetArg (args[n], XmNisAligned, True); n++;
  1641. X    col_w = XmCreateRowColumn (satform_w, "SatX", args, n);
  1642. X    XtManageChild (col_w);
  1643. X
  1644. X        n = 0;
  1645. X        w = XmCreatePushButton (col_w, "SatLab", args, n);
  1646. X        XtManageChild (w);
  1647. X        sm_set_a_button (w, False);
  1648. X        set_xmstring (w, XmNlabelString, "X (+E)");
  1649. X
  1650. X        for (i = 0; i < NM; i++) {
  1651. X        char *sel;
  1652. X        sel = XtMalloc (strlen(mnames[i].full) + 3); /* '.X\0' */
  1653. X        (void) sprintf (sel, "%s.X", mnames[i].full);
  1654. X        n = 0;
  1655. X        XtSetArg (args[n], XmNuserData, sel); n++;
  1656. X        w = s_w[i][X] = XmCreatePushButton(col_w, "SatPB", args, n);
  1657. X        XtAddCallback(w, XmNactivateCallback, sm_activate_cb, 0);
  1658. X        XtManageChild (w);
  1659. X        }
  1660. X
  1661. X    /* moon Y column */
  1662. X
  1663. X    n = 0;
  1664. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1665. X    XtSetArg (args[n], XmNtopWidget, title_w); n++;
  1666. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1667. X    XtSetArg (args[n], XmNleftPosition, 50); n++;
  1668. X    XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  1669. X    XtSetArg (args[n], XmNisAligned, True); n++;
  1670. X    col_w = XmCreateRowColumn (satform_w, "SatY", args, n);
  1671. X    XtManageChild (col_w);
  1672. X
  1673. X        n = 0;
  1674. X        w = XmCreatePushButton (col_w, "SatLab", args, n);
  1675. X        XtManageChild (w);
  1676. X        sm_set_a_button (w, False);
  1677. X        set_xmstring (w, XmNlabelString, "Y (+S)");
  1678. X
  1679. X        for (i = 0; i < NM; i++) {
  1680. X        char *sel;
  1681. X        sel = XtMalloc (strlen(mnames[i].full) + 3); /* '.Y\0' */
  1682. X        (void) sprintf (sel, "%s.Y", mnames[i].full);
  1683. X        n = 0;
  1684. X        XtSetArg (args[n], XmNuserData, sel); n++;
  1685. X        w = s_w[i][Y] = XmCreatePushButton(col_w, "SatPB", args, n);
  1686. X        XtAddCallback(w, XmNactivateCallback, sm_activate_cb, 0);
  1687. X        XtManageChild (w);
  1688. X        }
  1689. X
  1690. X    /* moon Z column */
  1691. X
  1692. X    n = 0;
  1693. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1694. X    XtSetArg (args[n], XmNtopWidget, title_w); n++;
  1695. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1696. X    XtSetArg (args[n], XmNleftPosition, 70); n++;
  1697. X    XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  1698. X    XtSetArg (args[n], XmNisAligned, True); n++;
  1699. X    col_w = XmCreateRowColumn (satform_w, "SatZ", args, n);
  1700. X    XtManageChild (col_w);
  1701. X
  1702. X        n = 0;
  1703. X        w = XmCreatePushButton (col_w, "SatLab", args, n);
  1704. X        XtManageChild (w);
  1705. X        sm_set_a_button (w, False);
  1706. X        set_xmstring (w, XmNlabelString, "Z (+front)");
  1707. X
  1708. X        for (i = 0; i < NM; i++) {
  1709. X        char *sel;
  1710. X        sel = XtMalloc (strlen(mnames[i].full) + 3); /* '.Z\0' */
  1711. X        (void) sprintf (sel, "%s.Z", mnames[i].full);
  1712. X        n = 0;
  1713. X        XtSetArg (args[n], XmNuserData, sel); n++;
  1714. X        w = s_w[i][Z] = XmCreatePushButton(col_w, "SatPB", args, n);
  1715. X        XtAddCallback(w, XmNactivateCallback, sm_activate_cb, 0);
  1716. X        XtManageChild (w);
  1717. X        }
  1718. X
  1719. X    /* moon mag column */
  1720. X
  1721. X    n = 0;
  1722. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1723. X    XtSetArg (args[n], XmNtopWidget, title_w); n++;
  1724. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1725. X    XtSetArg (args[n], XmNleftPosition, 90); n++;
  1726. X    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1727. X    XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  1728. X    XtSetArg (args[n], XmNisAligned, True); n++;
  1729. X    col_w = XmCreateRowColumn (satform_w, "SatMag", args, n);
  1730. X    XtManageChild (col_w);
  1731. X
  1732. X        n = 0;
  1733. X        w = XmCreatePushButton (col_w, "SatLab", args, n);
  1734. X        XtManageChild (w);
  1735. X        sm_set_a_button (w, False);
  1736. X        set_xmstring (w, XmNlabelString, "Mag");
  1737. X
  1738. X        for (i = 0; i < NM; i++) {
  1739. X        char *sel;
  1740. X        sel = XtMalloc (strlen(mnames[i].full) + 5); /* '.Mag\0' */
  1741. X        (void) sprintf (sel, "%s.Mag", mnames[i].full);
  1742. X        n = 0;
  1743. X        XtSetArg (args[n], XmNuserData, sel); n++;
  1744. X        w = s_w[i][MAG] = XmCreatePushButton(col_w, "SatPB",args,n);
  1745. X        XtAddCallback(w, XmNactivateCallback, sm_activate_cb, 0);
  1746. X        XtManageChild (w);
  1747. X        }
  1748. X
  1749. X    /* make a Form to hold the bottom controls */
  1750. X
  1751. X    n = 0;
  1752. X    XtSetArg (args[n], XmNfractionBase, 15); n++;
  1753. X    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1754. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1755. X    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1756. X    f_w = XmCreateForm (satform_w, "CtlForm", args, n);
  1757. X    XtManageChild (f_w);
  1758. X
  1759. X        /* make the close button */
  1760. X
  1761. X        n = 0;
  1762. X        XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1763. X        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1764. X        XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1765. X        XtSetArg (args[n], XmNleftPosition, 1); n++;
  1766. X        XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  1767. X        XtSetArg (args[n], XmNrightPosition, 4); n++;
  1768. X        w = XmCreatePushButton (f_w, "Close", args, n);
  1769. X        XtAddCallback (w, XmNactivateCallback, sm_close_cb, 0);
  1770. X        XtManageChild (w);
  1771. X
  1772. X        /* make the tags button in a frame */
  1773. X
  1774. X        n = 0;
  1775. X        XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1776. X        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1777. X        XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1778. X        XtSetArg (args[n], XmNleftPosition, 6); n++;
  1779. X        XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  1780. X        XtSetArg (args[n], XmNrightPosition, 9); n++;
  1781. X        fr_w = XmCreateFrame (f_w, "TagsFr", args, n);
  1782. X        XtManageChild (fr_w);
  1783. X        w = XmCreateToggleButton (fr_w, "Tags", args, n);
  1784. X        XtAddCallback (w, XmNvalueChangedCallback, sm_tags_cb, 0);
  1785. X        XtManageChild (w);
  1786. X        s_tags = XmToggleButtonGetState(w);
  1787. X
  1788. X        /* "big dots" toggle button in a frame */
  1789. X
  1790. X        n = 0;
  1791. X        XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1792. X        XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1793. X        XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  1794. X        XtSetArg (args[n], XmNleftPosition, 11); n++;
  1795. X        XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  1796. X        XtSetArg (args[n], XmNrightPosition, 14); n++;
  1797. X        fr_w = XmCreateFrame(f_w,"BigDotsFr", args, n);
  1798. X        XtManageChild (fr_w);
  1799. X        str = XmStringCreate("Big dots", XmSTRING_DEFAULT_CHARSET);
  1800. X        n = 0;
  1801. X        XtSetArg (args[n], XmNlabelString, str); n++;
  1802. X        w = XmCreateToggleButton(fr_w,"BigDots",args,n);
  1803. X        XtAddCallback(w, XmNvalueChangedCallback, sm_bigd_cb, 0);
  1804. X        XtManageChild (w);
  1805. X        XmStringFree (str);
  1806. X        bigdots = XmToggleButtonGetState(w);
  1807. X
  1808. X    /* make the date/time stamp label */
  1809. X
  1810. X    n = 0;
  1811. X    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  1812. X    XtSetArg (args[n], XmNbottomWidget, f_w); n++;
  1813. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1814. X    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1815. X    dt_w = XmCreateLabel (satform_w, "DateStamp", args, n);
  1816. X    timestamp (mm_get_now(), dt_w);    /* establishes size */
  1817. X    XtManageChild (dt_w);
  1818. X
  1819. X    /* make the scale widget
  1820. X     * attach both top and bottom so it's the one to follow resizing.
  1821. X     */
  1822. X
  1823. X    n = 0;
  1824. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1825. X    XtSetArg (args[n], XmNtopWidget, col_w); n++;
  1826. X    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  1827. X    XtSetArg (args[n], XmNbottomWidget, dt_w); n++;
  1828. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1829. X    XtSetArg (args[n], XmNmaximum, 100); n++;
  1830. X    XtSetArg (args[n], XmNminimum, 0); n++;
  1831. X    XtSetArg (args[n], XmNscaleMultiple, 10); n++;
  1832. X    XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
  1833. X    XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
  1834. X    scale_w = XmCreateScale (satform_w, "Scale", args, n);
  1835. X    XtAddCallback (scale_w, XmNdragCallback, sm_scale_cb, 0);
  1836. X    XtAddCallback (scale_w, XmNvalueChangedCallback, sm_scale_cb, 0);
  1837. X    XtManageChild (scale_w);
  1838. X
  1839. X    /* make a frame for the drawing area.
  1840. X     * attach both top and bottom so it's the one to follow resizing.
  1841. X     */
  1842. X
  1843. X    n = 0;
  1844. X    XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1845. X    XtSetArg (args[n], XmNtopWidget, col_w); n++;
  1846. X    XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  1847. X    XtSetArg (args[n], XmNbottomWidget, dt_w); n++;
  1848. X    XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  1849. X    XtSetArg (args[n], XmNleftWidget, scale_w); n++;
  1850. X    XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1851. X    XtSetArg (args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
  1852. X    frame_w = XmCreateFrame (satform_w, "SatFrame", args, n);
  1853. X    XtManageChild (frame_w);
  1854. X
  1855. X        /* make a drawing area for drawing the little map */
  1856. X
  1857. X        n = 0;
  1858. X        sda_w = XmCreateDrawingArea (frame_w, "Map", args, n);
  1859. X        XtAddCallback (sda_w, XmNexposeCallback, sm_da_exp_cb, 0);
  1860. X        XtManageChild (sda_w);
  1861. X}
  1862. X
  1863. X/* go through all the buttons pickable for plotting and set whether they
  1864. X * should appear to look like buttons or just flat labels.
  1865. X */
  1866. Xstatic void
  1867. Xsm_set_buttons (whether)
  1868. Xint whether;    /* whether setting up for plotting or for not plotting */
  1869. X{
  1870. X    int i;
  1871. X
  1872. X    for (i = 0; i < NM; i++) {
  1873. X        sm_set_a_button (s_w[i][X], whether);
  1874. X        sm_set_a_button (s_w[i][Y], whether);
  1875. X        sm_set_a_button (s_w[i][Z], whether);
  1876. X        sm_set_a_button (s_w[i][MAG], whether);
  1877. X    }
  1878. X    sm_set_a_button (ringt_w, whether);
  1879. X}
  1880. X
  1881. X/* set whether the given button looks like a label.
  1882. X */
  1883. Xstatic void
  1884. Xsm_set_a_button(pbw, whether)
  1885. XWidget pbw;
  1886. Xint whether;
  1887. X{
  1888. X    static Arg look_like_button[] = {
  1889. X        {XmNtopShadowColor, (XtArgVal) 0},
  1890. X        {XmNbottomShadowColor, (XtArgVal) 0},
  1891. X        {XmNfillOnArm, (XtArgVal) True},
  1892. X    };
  1893. X    static Arg look_like_label[] = {
  1894. X        {XmNtopShadowColor, (XtArgVal) 0},
  1895. X        {XmNbottomShadowColor, (XtArgVal) 0},
  1896. X        {XmNfillOnArm, (XtArgVal) False},
  1897. X    };
  1898. X    static int called;
  1899. X    Arg *ap;
  1900. X    int na;
  1901. X
  1902. X    if (!called) {
  1903. X        /* get baseline label and shadow appearances.
  1904. X         */
  1905. X        Pixel topshad, botshad, bgcol;
  1906. X        Arg args[20];
  1907. X        Widget tmpw;
  1908. X        int n;
  1909. X
  1910. X        n = 0;
  1911. X        tmpw = XmCreatePushButton (satform_w, "tmp", args, n);
  1912. X
  1913. X        n = 0;
  1914. X        XtSetArg (args[n], XmNtopShadowColor, &topshad); n++;
  1915. X        XtSetArg (args[n], XmNbottomShadowColor, &botshad); n++;
  1916. X        XtSetArg (args[n], XmNbackground, &bgcol); n++;
  1917. X        XtGetValues (tmpw, args, n);
  1918. X
  1919. X        look_like_button[0].value = topshad;
  1920. X        look_like_button[1].value = botshad;
  1921. X        look_like_label[0].value = bgcol;
  1922. X        look_like_label[1].value = bgcol;
  1923. X
  1924. X        XtDestroyWidget (tmpw);
  1925. X         
  1926. X        called = 1;
  1927. X    }
  1928. X
  1929. X    if (whether) {
  1930. X        ap = look_like_button;
  1931. X        na = XtNumber(look_like_button);
  1932. X    } else {
  1933. X        ap = look_like_label;
  1934. X        na = XtNumber(look_like_label);
  1935. X    }
  1936. X
  1937. X    XtSetValues (pbw, ap, na);
  1938. X}
  1939. X
  1940. X/* callback from the big dots toggle button
  1941. X * TODO: really shouldn't get present time, just redo dots in same location.
  1942. X */
  1943. X/* ARGSUSED */
  1944. Xstatic void
  1945. Xsm_bigd_cb (w, client, call)
  1946. XWidget w;
  1947. XXtPointer client;
  1948. XXtPointer call;
  1949. X{
  1950. X    bigdots = XmToggleButtonGetState(w);
  1951. X    sm_update (mm_get_now(), 1);
  1952. X}
  1953. X
  1954. X/* callback from the tags toggle button
  1955. X * TODO: really shouldn't get present time, just redo dots in same location.
  1956. X */
  1957. X/* ARGSUSED */
  1958. Xstatic void
  1959. Xsm_tags_cb (w, client, call)
  1960. XWidget w;
  1961. XXtPointer client;
  1962. XXtPointer call;
  1963. X{
  1964. X    s_tags = XmToggleButtonGetState(w);
  1965. X    sm_update (mm_get_now(), 1);
  1966. X}
  1967. X
  1968. X/* callback from the scale.
  1969. X * TODO: really shouldn't get present time, just redo dots in same location.
  1970. X */
  1971. X/* ARGSUSED */
  1972. Xstatic void
  1973. Xsm_scale_cb (w, client, call)
  1974. XWidget w;
  1975. XXtPointer client;
  1976. XXtPointer call;
  1977. X{
  1978. X    sm_update (mm_get_now(), 1);
  1979. X}
  1980. X
  1981. X/* callback from any of the data menu buttons being activated.
  1982. X */
  1983. X/* ARGSUSED */
  1984. Xstatic void
  1985. Xsm_activate_cb (w, client, call)
  1986. XWidget w;
  1987. XXtPointer client;
  1988. XXtPointer call;
  1989. X{
  1990. X    if (sm_selecting) {
  1991. X        char *name;
  1992. X        get_something (w, XmNuserData, (char *)&name);
  1993. X        register_selection (name);
  1994. X    }
  1995. X}
  1996. X
  1997. X/* callback from the Close button
  1998. X */
  1999. X/* ARGSUSED */
  2000. Xstatic void
  2001. Xsm_close_cb (w, client, call)
  2002. XWidget w;
  2003. XXtPointer client;
  2004. XXtPointer call;
  2005. X{
  2006. X    XtUnmanageChild (satform_w);
  2007. X}
  2008. X
  2009. X/* callback from either expose or resize of the drawing area.
  2010. X */
  2011. X/* ARGSUSED */
  2012. Xstatic void
  2013. Xsm_da_exp_cb (w, client, call)
  2014. XWidget w;
  2015. XXtPointer client;
  2016. XXtPointer call;
  2017. X{
  2018. X    XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
  2019. X
  2020. X    /* filter out a few oddball cases */
  2021. X    switch (c->reason) {
  2022. X    case XmCR_EXPOSE: {
  2023. X        /* turn off gravity so we get expose events for either shrink or
  2024. X         * expand.
  2025. X         */
  2026. X        static before;
  2027. X        XExposeEvent *e = &c->event->xexpose;
  2028. X
  2029. X        if (!before) {
  2030. X        XSetWindowAttributes swa;
  2031. X        swa.bit_gravity = ForgetGravity;
  2032. X        XChangeWindowAttributes (e->display, e->window, 
  2033. X                                CWBitGravity, &swa);
  2034. X        before = 1;
  2035. X        }
  2036. X        /* wait for the last in the series */
  2037. X        if (e->count != 0)
  2038. X        return;
  2039. X        break;
  2040. X        }
  2041. X    default:
  2042. X        printf ("Unexpected satform_w event. type=%d\n", c->reason);
  2043. X        exit(1);
  2044. X    }
  2045. X
  2046. X    sm_update (mm_get_now(), 1);
  2047. X}
  2048. X
  2049. X/* computional support for saturn's detail menu.
  2050. X * courtesy Craig Counterman.
  2051. X */
  2052. X
  2053. Xtypedef struct {
  2054. X  double alpha, delta;        /* position in equinox of date */
  2055. X  double l, b;            /* ecliptical longitude and latitude */
  2056. X  double lambda, beta;        /* geocentric longitude and latitude */
  2057. X  double Cen;            /* Center */
  2058. X  double psi;            /* elongation */
  2059. X  double r, Delta;        /* Distance to sun, and earth */
  2060. X  double mag, phase, size;    /* magnitude, phase (degrees) size (arcsec) */
  2061. X  double illum_frac;        /* illuminated fraction of disk */
  2062. X  double beta_e;
  2063. X                /* beta_e, p_n, lambda_e */
  2064. X} planet_data_t;
  2065. X
  2066. X
  2067. Xtypedef struct {
  2068. X  char *name;
  2069. X  double alpha, delta;        /* position in equinox of date */
  2070. X  double R, Theta;        /* Distance to earth, Theta equinox of date */
  2071. X                /* times of these events */
  2072. X} sun_data_t;
  2073. X
  2074. Xtypedef struct {
  2075. X  double dx, dy, dz;        /* relative to planet,
  2076. X                   units of equatorial radius */
  2077. X  double dalpha, ddelta;    /* displacements in RA and dec. */
  2078. X  double mag;
  2079. X  char *name;
  2080. X} sat_t;
  2081. X
  2082. X/* functions */
  2083. Xstatic void anom_calc();
  2084. Xstatic void planet_pos(), sun_pos();
  2085. Xstatic double obl_jd();
  2086. Xstatic void satsat();
  2087. Xstatic void sm_draw_map();
  2088. Xstatic double into_range();
  2089. X
  2090. X
  2091. X/* called to recompute and fill in values for the saturn menu.
  2092. X * don't bother if it doesn't exist or is unmanaged now or no one is logging.
  2093. X */
  2094. Xvoid
  2095. Xsm_update (np, how_much)
  2096. XNow *np;
  2097. Xint how_much;
  2098. X{
  2099. X    static char fmt[] = "%7.3f";
  2100. X        double jd;
  2101. X        sat_t  saturnsats[8];
  2102. X        planet_data_t planets;
  2103. X        sun_data_t sun_data;
  2104. X    int i;
  2105. X
  2106. X    if (!satform_w)
  2107. X        return;
  2108. X    if (!XtIsManaged(satform_w) && !any_ison() && !how_much)
  2109. X        return;
  2110. X
  2111. X        jd = mjd + MJD0;
  2112. X    sun_pos(jd, &sun_data);
  2113. X    planet_pos(jd, sun_data, 4, &planets);
  2114. X        satsat(jd, planets, saturnsats);
  2115. X
  2116. X    for (i = 0; i < NM; i++) {
  2117. X        f_double (s_w[i][X], fmt, -saturnsats[i].dx);
  2118. X        f_double (s_w[i][Y], fmt, -saturnsats[i].dy);
  2119. X        f_double (s_w[i][Z], fmt, saturnsats[i].dz);
  2120. X        f_double (s_w[i][MAG], "%5.1f", saturnsats[i].mag);
  2121. X    }
  2122. X
  2123. X    f_double (ringt_w, fmt, planets.beta_e);
  2124. X
  2125. X    if (XtIsManaged(satform_w)) {
  2126. X        sm_draw_map (sda_w, saturnsats, planets.beta_e);
  2127. X        timestamp (np, dt_w);
  2128. X    }
  2129. X}
  2130. X
  2131. X/* given the loc of the moons, draw a nifty little picture.
  2132. X * scale of the locations is in terms of saturn radii == 1.
  2133. X */
  2134. Xstatic void
  2135. Xsm_draw_map (w, moons, tilt)
  2136. XWidget w;
  2137. Xsat_t moons[NM];
  2138. Xdouble tilt;    /* degrees */
  2139. X{
  2140. X    static GC s_fgc, s_bgc, s_xgc;
  2141. X    static XFontStruct *s_fs;
  2142. X    static last_nx, last_ny;
  2143. X    static int cw, ch;
  2144. X    static Pixmap pm;
  2145. X    Display *dsp = XtDisplay(w);
  2146. X    Window win = XtWindow(w);
  2147. X    Window root;
  2148. X    double scale;
  2149. X    int sv;
  2150. X    char c;
  2151. X    int x, y;
  2152. X    unsigned int nx, ny, bw, d;
  2153. X    int irw, orw, irh, orh, irx, iry, orx, ory;
  2154. X    int i;
  2155. X#define    RLW    3    /* ring line width, pixels */
  2156. X#define    NORM    60.0    /* max Iapetus orbit radius; used to normalize */
  2157. X#define    MAPSCALE(v)    ((v)*((int)nx)/NORM/2*scale)
  2158. X#define    XCORD(x)    ((int)(((int)nx)/2.0 + MAPSCALE(x) + 0.5))
  2159. X#define    YCORD(y)    ((int)(((int)ny)/2.0 - MAPSCALE(y) + 0.5))
  2160. X
  2161. X    if (!s_fgc) {
  2162. X        XGCValues gcv;
  2163. X        unsigned int gcm;
  2164. X        Pixel fg, bg;
  2165. X
  2166. X        gcm = GCForeground;
  2167. X        get_something (w, XmNforeground, (char *)&fg);
  2168. X        gcv.foreground = fg;
  2169. X        s_fgc = XCreateGC (dsp, win, gcm, &gcv);
  2170. X        s_fs = XQueryFont (dsp, XGContextFromGC (s_fgc));
  2171. X        cw = s_fs->max_bounds.width;
  2172. X        ch = s_fs->max_bounds.ascent + s_fs->max_bounds.descent;
  2173. X
  2174. X        gcm = GCForeground;
  2175. X        get_something (w, XmNbackground, (char *)&bg);
  2176. X        gcv.foreground = bg;
  2177. X        s_bgc = XCreateGC (dsp, win, gcm, &gcv);
  2178. X
  2179. X        gcm = GCForeground | GCFunction;
  2180. X        gcv.foreground = fg ^ bg;
  2181. X        gcv.function = GXxor;
  2182. X        s_xgc = XCreateGC (dsp, win, gcm, &gcv);
  2183. X    }
  2184. X
  2185. X    XmScaleGetValue (scale_w, &sv);
  2186. X    scale = pow(MAXSCALE, sv/100.0);
  2187. X
  2188. X    XGetGeometry(dsp, win, &root, &x, &y, &nx, &ny, &bw, &d);
  2189. X    if (!pm || nx != last_nx || ny != last_ny) {
  2190. X        if (pm)
  2191. X        XFreePixmap (dsp, pm);
  2192. X        pm = XCreatePixmap (dsp, win, nx, ny, d);
  2193. X        last_nx = nx;
  2194. X        last_ny = ny;
  2195. X    }
  2196. X
  2197. X    XFillRectangle (dsp, pm, s_bgc, 0, 0, nx, ny);
  2198. X
  2199. X    c = 'E'; XDrawString(dsp, pm, s_fgc, nx-cw-1, ny/2-2, &c, 1);
  2200. X    c = 'S'; XDrawString(dsp, pm, s_fgc, (nx-cw)/2-1, s_fs->ascent, &c, 1);
  2201. X
  2202. X    /* draw Saturn of radius 1 */
  2203. X    XFillArc (dsp, pm, s_fgc, XCORD(-1), YCORD(1), 2*(int)MAPSCALE(1),
  2204. X                        2*(int)MAPSCALE(1), 0, 360*64);
  2205. X    
  2206. X    /* rings of radius IRR and ORR.
  2207. X     * draw rings in front of planet using xor.
  2208. X     * positive tilt means the southern edge of the rings are in front.
  2209. X     * always draw the solid s_fgc last in case we are near the ring plane.
  2210. X     */
  2211. X#define    IRR    1.528    /* inner edge of ring system */
  2212. X#define    ORR    2.267    /* outter edge of A ring */
  2213. X    irh = MAPSCALE(2*IRR*fabs(sin(degrad(tilt))));
  2214. X    irw = (int)MAPSCALE(2*IRR);
  2215. X    orh = MAPSCALE(2*ORR*fabs(sin(degrad(tilt))));
  2216. X    orw = (int)MAPSCALE(2*ORR);
  2217. X    irx = XCORD(-IRR);
  2218. X    iry = YCORD(IRR*fabs(sin(degrad(tilt))));
  2219. X    orx = XCORD(-ORR);
  2220. X    ory = YCORD(ORR*fabs(sin(degrad(tilt))));
  2221. X    if (irh < RLW || orh < RLW) {
  2222. X        /* too near the ring plane to draw a fill ellipse */
  2223. X        XDrawLine (dsp, pm, s_fgc, orx, ny/2, nx-orx, ny/2);
  2224. X    } else {
  2225. X        XDrawArc (dsp, pm, s_xgc, irx, iry, irw, irh,
  2226. X                    tilt > 0.0 ? 0 : 180*64, 180*64-1);
  2227. X        XDrawArc (dsp, pm, s_xgc, orx, ory, orw, orh,
  2228. X                    tilt > 0.0 ? 0 : 180*64, 180*64-1);
  2229. X        XDrawArc (dsp, pm, s_fgc, irx, iry, irw, irh,
  2230. X                    tilt > 0.0 ? 180*64 : 0, 180*64-1);
  2231. X        XDrawArc (dsp, pm, s_fgc, orx, ory, orw, orh,
  2232. X                    tilt > 0.0 ? 180*64 : 0, 180*64-1);
  2233. X    }
  2234. X
  2235. X    /* draw each moon that is visible.
  2236. X     */
  2237. X    for (i = 0; i < NM; i++) {
  2238. X        double mx = -moons[i].dx;
  2239. X        double my = -moons[i].dy;
  2240. X        double mz =  moons[i].dz;
  2241. X        int outside = mx*mx + my*my > 1.0;
  2242. X        int infront = mz > 0.0;
  2243. X
  2244. X        if (!outside && !infront)
  2245. X        continue;    /* behind saturn */
  2246. X
  2247. X        x = XCORD(mx);
  2248. X        y = YCORD(my);
  2249. X        XDrawPoint (dsp, pm, s_xgc, x, y);
  2250. X        if (bigdots) {
  2251. X        XDrawPoint(dsp,pm, s_xgc, x+1, y);
  2252. X        XDrawPoint(dsp,pm, s_xgc, x,   y+1);
  2253. X        XDrawPoint(dsp,pm, s_xgc, x+1, y+1);
  2254. X        }
  2255. X        if (s_tags)
  2256. X        XDrawString(dsp, pm, s_xgc, x-cw/2, y+2*ch,
  2257. X                    mnames[i].tag, strlen(mnames[i].tag));
  2258. X    }
  2259. X
  2260. X    XCopyArea (dsp, pm, win, s_fgc, 0, 0, nx, ny, 0, 0);
  2261. X}
  2262. X
  2263. X
  2264. X/* the following is from starchart */
  2265. X
  2266. X#define DEG_TO_RAD 0.01745329251994329600
  2267. X#define RAD_TO_DEG 57.29577951308232
  2268. X#define DSIN(x) (sin((x)*DEG_TO_RAD))
  2269. X#define DCOS(x) (cos((x)*DEG_TO_RAD))
  2270. X#define DTAN(x) (tan((x)*DEG_TO_RAD))
  2271. X#define DASIN(x) (asin(x)*RAD_TO_DEG)
  2272. X#define DACOS(x) (acos(x)*RAD_TO_DEG)
  2273. X#define DATAN(x) (atan(x)*RAD_TO_DEG)
  2274. X#define DATAN2(x,y) (atan2(x,y)*RAD_TO_DEG)
  2275. X
  2276. X/* siderial Periods of satellites:
  2277. X 0.942421813
  2278. X 1.370217855
  2279. X 1.887802160
  2280. X 2.736914742
  2281. X 4.517500436
  2282. X15.94542068
  2283. X21.2766088
  2284. X79.3301825
  2285. X
  2286. Xsynodic (approx)
  2287. X 0.94250436287643326
  2288. X 1.3703923657888438
  2289. X 1.8881334260185879
  2290. X 2.7376110810451278
  2291. X 4.519397869256954
  2292. X 15.969085530060568
  2293. X 21.318764097751611
  2294. X 79.919403771981642
  2295. X
  2296. Xsemimajor axes
  2297. X185.52
  2298. X238.02
  2299. X294.66
  2300. X377.40
  2301. X527.04
  2302. X1221.83
  2303. X1481.1
  2304. X3561.3
  2305. X*/
  2306. X
  2307. Xstatic struct {
  2308. X  double off; /* angle of satellite at jd 2415020.0 */
  2309. X  double angvel; /* anbular velocity, degrees per day */
  2310. X  double r; /* Distance to saturn in saturn radii */
  2311. X  double mag; /* V(1,0) */
  2312. X  char *name; /* Name */
  2313. X} satsat_data[] = {
  2314. X  {49.0, 381.96109660576467, 3.092, 3.3, "Mimas"},
  2315. X  {98.7, 262.69848620527883, 3.967, 2.1, "Enceladus"},
  2316. X  {263.0, 190.66449173515979, 4.911, 0.6, "Tethys"},
  2317. X  {101.3, 131.50151330574105, 6.290, 0.8, "Dione"},
  2318. X  {11.2, 79.656629138338852, 8.784, 0.1, "Rhea"},
  2319. X  {183.7, 22.543557633424146, 20.364, -1.28, "Titan"},
  2320. X  {95.0, 16.886532368823739, 24.685, 4.63, "Hyperion"},
  2321. X  {338.4, 4.5045381097576426, 59.355, 1.5, "Iapetus"}
  2322. X};
  2323. X
  2324. X/* given jd, return sat_t list of major satellites of Saturn */
  2325. X/* Ignore many corrections to Saturn's orbit,
  2326. X   assume moons in circular orbits in Saturn's equatorial plane */
  2327. Xstatic void
  2328. Xsatsat(jd, saturn, sats)
  2329. X     double jd;
  2330. X     planet_data_t saturn;
  2331. X     sat_t sats[8];
  2332. X{
  2333. X  double d;            /* modified julian date */
  2334. X  double B;            /* Center of saturn */
  2335. X  double Delta;            /* Distance from earth to Saturn */
  2336. X  double psi;            /* Phase angle */
  2337. X  double u[8];            /* angle */
  2338. X  double X[8];            /* relative Positions (radii) */
  2339. X  double Y[8];            /* relative Positions (radii) */
  2340. X  double Z[8];            /* relative Positions (radii) */
  2341. X  double dmag;
  2342. X  int i;
  2343. X
  2344. X  d = jd - MJD0;
  2345. X
  2346. X  Delta = saturn.Delta;
  2347. X  psi = saturn.phase;
  2348. X  B = saturn.Cen;
  2349. X
  2350. X
  2351. X  dmag = 5.0 * log10(saturn.r*saturn.Delta)
  2352. X    - 2.5 * log10(saturn.illum_frac);
  2353. X
  2354. X  for (i = 0; i < 8; i++) {
  2355. X    u[i] = satsat_data[i].off
  2356. X      + satsat_data[i].angvel * (d - Delta * 0.00577167643528) + psi - B;
  2357. X    u[i] = into_range(u[i]);
  2358. X
  2359. X    X[i] = satsat_data[i].r * DSIN(u[i]);
  2360. X    Z[i] = satsat_data[i].r * DCOS(u[i]);
  2361. X    Y[i] = - satsat_data[i].r * DCOS(u[i]) * DSIN(saturn.beta_e);
  2362. X
  2363. X    sats[i].dx = X[i];
  2364. X    sats[i].dy = Y[i];
  2365. X    sats[i].dz = Z[i];
  2366. X    sats[i].name = satsat_data[i].name;
  2367. X    sats[i].mag = satsat_data[i].mag + dmag;
  2368. X  };
  2369. X}
  2370. X
  2371. Xtypedef struct {
  2372. X  double L[4];
  2373. X  double a;
  2374. X  double e[4];
  2375. X  double i[4];
  2376. X  double omega[4];
  2377. X  double Omega[4];
  2378. X  double size_1au;
  2379. X  double mag0;
  2380. X} pelements;
  2381. X
  2382. Xstatic pelements peles = {
  2383. X    /* Saturn */
  2384. X    {266.564377, 1223.509884, 0.0003245, -0.0000058},
  2385. X    9.554747,
  2386. X    {0.05589232, -0.00034550, -0.000000728, 0.00000000074},
  2387. X    {2.492519, -0.0039189, -0.00001549, 0.00000004},
  2388. X    {338.307800, 1.0852207, 0.00097854, 0.00000992},
  2389. X    {112.790414, 0.8731951, -0.00015218, -0.00000531},
  2390. X    165.6,
  2391. X    -8.88
  2392. X    
  2393. X};
  2394. X
  2395. Xtypedef struct {
  2396. X  double alpha_1, delta_1;
  2397. X  double W_0, W_dot;
  2398. X} rot_els_t;
  2399. Xstatic rot_els_t rot_els = {
  2400. X    40.09, 83.49,
  2401. X    223.60, 810.79390
  2402. X};
  2403. X
  2404. Xstatic double polynom(jd, a)
  2405. X     double jd;
  2406. X     double a[4];
  2407. X{
  2408. X  double T;
  2409. X
  2410. X  T = (jd - MJD0)/36525.0;
  2411. X
  2412. X  return (a[0] + a[1]*T + a[2]*T*T + a[3]*T*T*T);
  2413. X}
  2414. X
  2415. Xstatic void  saturn();
  2416. X
  2417. X
  2418. X/* Calculate alpha and delta
  2419. X   from lambda and beta (and epsilon)
  2420. X   which are from r, Delta, psi, b, l, and Theta (in sun_data)
  2421. X   which are from u, i (given), and Omega (given)
  2422. X   u is from L (given), nu, and M
  2423. X   nu and M are calculated.
  2424. X   r is from E, a (given) and e (given)
  2425. X   E is calculated
  2426. X
  2427. X   calculate mag from Delta, size form Delta, phase (== beta).
  2428. X */
  2429. X
  2430. X/* ARGSUSED */
  2431. Xstatic void
  2432. Xplanet_pos(jd, sun_data, nplanet, data)
  2433. X     double jd;            /* time, jd */
  2434. X     sun_data_t sun_data;
  2435. X     planet_data_t *data;
  2436. X{
  2437. X  double L_, a_, e_, i_, omega_, Omega_, M_;
  2438. X  double r;            /* radius distance to sun */
  2439. X  double l, b;            /* ecliptical longitude and latitude */
  2440. X  double Delta;            /* Distance to earth */
  2441. X  double lambda, beta;        /* geocentric longitude and latitude */
  2442. X  double alpha, delta;        /* R.A. and dec. both degrees */
  2443. X  double psi;            /* elongation */
  2444. X  double N, D;            /* temporary variables */
  2445. X  double Theta;            /* Theta of the sun */
  2446. X  double epsilon;        /* obliquity */
  2447. X  double Cen;            /* center */
  2448. X
  2449. X  L_ = into_range(polynom(jd, peles.L));
  2450. X  a_ = peles.a;
  2451. X  e_ = polynom(jd, peles.e);
  2452. X  i_ = polynom(jd, peles.i);
  2453. X  omega_ = into_range(polynom(jd, peles.omega));
  2454. X  Omega_ = into_range(polynom(jd, peles.Omega));
  2455. X  M_ = into_range(L_ - omega_ - Omega_);
  2456. X
  2457. X  /* Perturb */
  2458. X    saturn(jd, L_, a_, e_, i_, omega_, Omega_, M_, &r, &l, &b, &Cen);
  2459. X
  2460. X  Theta = sun_data.Theta;
  2461. X  N = r * DCOS(b) * DSIN(l - Theta);
  2462. X  D = r * DCOS(b) * DCOS(l - Theta) + sun_data.R;
  2463. X
  2464. X  epsilon = obl_jd(jd);
  2465. X
  2466. X  lambda = into_range(RAD_TO_DEG * atan2(N, D)) + Theta;
  2467. X  Delta = sqrt(N*N + D*D + (r * DSIN(b))*(r * DSIN(b)));
  2468. X  beta = RAD_TO_DEG * asin(r * DSIN(b) / Delta);
  2469. X  psi = RAD_TO_DEG * acos(DCOS(beta) * DCOS(lambda - Theta));
  2470. X  if (into_range(lambda - Theta) > 180.0)
  2471. X    psi = -psi;
  2472. X  alpha = RAD_TO_DEG * atan2(DSIN(lambda)*DCOS(epsilon)
  2473. X                 - DTAN(beta) * DSIN(epsilon),
  2474. X                 DCOS(lambda));
  2475. X  delta = RAD_TO_DEG * asin(DSIN(beta)*DCOS(epsilon)
  2476. X                + DCOS(beta)*DSIN(epsilon)*DSIN(lambda));
  2477. X  alpha = into_range(alpha);
  2478. X
  2479. X/* should correct for nutation and aberration */
  2480. X  data->alpha = alpha;
  2481. X  data->delta = delta;
  2482. X  data->l = l;
  2483. X  data->b = b;
  2484. X  data->lambda = lambda;
  2485. X  data->beta = beta;
  2486. X  data->psi = psi;
  2487. X  data->phase =
  2488. X    DACOS((r*r + Delta*Delta - sun_data.R*sun_data.R) / (2*r*Delta));
  2489. X  if (psi < 0) data->phase = -data->phase;
  2490. X  data->r = r;
  2491. X  data->Delta = Delta;
  2492. X  data->illum_frac = ((r+Delta)*(r+Delta) - sun_data.R*sun_data.R)/(4*r*Delta);
  2493. X  data->Cen = Cen;
  2494. X
  2495. X  data->mag = 5.0 * log10(r*Delta)
  2496. X    - 2.5 * log10(data->illum_frac)
  2497. X    + peles.mag0;
  2498. X
  2499. X  data->size = peles.size_1au / Delta;
  2500. X
  2501. X  data->beta_e =
  2502. X    DASIN(-DSIN(rot_els.delta_1)*DSIN(delta)
  2503. X      - DCOS(rot_els.delta_1) * DCOS(delta)
  2504. X          * DCOS(rot_els.alpha_1 - alpha));
  2505. X
  2506. X
  2507. X}
  2508. X
  2509. Xstatic void saturn(jd, L_, a_, e_, i_, omega_, Omega_, M_, r_p, l_p, b_p, C_p)
  2510. Xdouble jd, L_, a_, e_, i_, omega_, Omega_, M_;
  2511. Xdouble *r_p, *l_p, *b_p, *C_p;
  2512. X{
  2513. X  double E, nu;
  2514. X  double r, l, b;
  2515. X
  2516. X  double u;            /* argument of latitude */
  2517. X  double T;
  2518. X  double A, B, e_pert, a_pert, b_pert, v, zeta;
  2519. X  double P, Q, V;
  2520. X  double Szeta, S2zeta, Dzeta, D2zeta,
  2521. X                 DQ, SQ, D2Q, S2Q;
  2522. X
  2523. X  /* for perturbations */
  2524. X  T = (jd - MJD0)/36525.0;
  2525. X
  2526. X  v = T/5.0 + 0.1;
  2527. X  P = 237.47555 +3034.9061*T;
  2528. X  Q = 265.91650 + 1222.1139*T;
  2529. X  V = 5.0*Q -2.0*P;
  2530. X  zeta = Q - P;
  2531. X
  2532. X  Szeta = DSIN(zeta);
  2533. X  S2zeta = DSIN(2*zeta);
  2534. X  Dzeta = DCOS(zeta);
  2535. X  D2zeta = DCOS(2*zeta);
  2536. X  DQ = DCOS(Q);
  2537. X  D2Q = DCOS(2*Q);
  2538. X  SQ = DSIN(Q);
  2539. X  S2Q = DSIN(2*Q);
  2540. X  A = (-0.814181 + 0.018150*v + 0.016714*v*v)*DSIN(V)
  2541. X    +(-0.010497 + 0.160906*v - 0.004100*v*v)*DCOS(V);
  2542. X  A +=        -0.040786*S2zeta
  2543. X  + ( (0.008931 + 0.002728*v)*Szeta )*SQ;
  2544. X
  2545. X
  2546. X  A +=      ((0.081344 )*Dzeta+
  2547. X        0.015019*D2zeta)*SQ;
  2548. X  A +=          ((0.085581 + 0.002494*v)*Szeta
  2549. X        +(0.025328 - 0.003117*v)*Dzeta
  2550. X      )*DQ;
  2551. X
  2552. X  e_pert = (-.0007927 + .0002548*v +.0000091*v*v)*DSIN(V)
  2553. X    +(.0013381 + .0001226*v -.0000253*v*v)*DCOS(V)
  2554. X      ;
  2555. X  e_pert +=         .0012415*SQ;
  2556. X  e_pert +=  (
  2557. X              .0026599*Dzeta)*SQ;
  2558. X  e_pert +=         (
  2559. X          -.0012696*Szeta
  2560. X)*DQ;
  2561. X
  2562. X
  2563. X
  2564. X  B = (0.077108 + 0.007186*v - 0.001533*v*v)*DSIN(V)
  2565. X    +(0.045803 - 0.014766*v - 0.000536*v*v)*DCOS(V);
  2566. X  B +=  
  2567. X    (-0.075825*Szeta
  2568. X      -0.024839*S2zeta
  2569. X          )*SQ;
  2570. X  B +=          (-0.072586
  2571. X          -0.150383*Dzeta
  2572. X          +0.026897*D2zeta
  2573. X            )*DQ;
  2574. X  B += (-(0.013597 +0.001719*v)*Szeta
  2575. X )*S2Q;
  2576. X  B +=     ( (-0.013667 + 0.001239*v)*Szeta
  2577. X          +0.011981*S2zeta
  2578. X          +(0.014861 + 0.001136*v)*Dzeta
  2579. X          -(0.013064 + 0.001628*v)*D2zeta)*D2Q;
  2580. X
  2581. X  a_pert =  .033629*Dzeta 
  2582. X    -.003081*D2zeta ;
  2583. X  a_pert += (.001098 
  2584. X      -.002812*Szeta 
  2585. X         +.002138*Dzeta
  2586. X          )*SQ;
  2587. X  a_pert +=    ( -.000890
  2588. X          +.002206*Szeta)*DQ;
  2589. X  L_ += A;
  2590. X  M_ += A - B / e_;
  2591. X  e_ += e_pert;
  2592. X  a_ += a_pert;
  2593. X  omega_ += B;
  2594. X
  2595. X  /* Calculate E and nu */
  2596. X  anom_calc(M_, e_, &E, &nu);
  2597. X  r = a_ * (1 - e_ * DCOS(E));
  2598. X
  2599. X
  2600. X  u = L_ + nu - M_ - Omega_;
  2601. X  *C_p = nu - M_;
  2602. X  l = into_range(RAD_TO_DEG * atan2(DCOS(i_) * DSIN(u), DCOS(u)) + Omega_);
  2603. X  b = RAD_TO_DEG * asin(DSIN(u)*DSIN(i_));
  2604. X
  2605. X  b_pert = 0.000747*Dzeta*SQ
  2606. X      +0.001069*Dzeta*DQ
  2607. X    +0.002108*S2zeta*S2Q;
  2608. X  b_pert += 0.001261*D2zeta*S2Q
  2609. X        +0.001236*S2zeta*D2Q
  2610. X          -0.002075*D2zeta*D2Q;
  2611. X
  2612. X  *r_p = r;
  2613. X  *l_p = l;
  2614. X  *b_p = b + b_pert;
  2615. X}
  2616. X
  2617. Xstatic void anom_calc(M, e, E_p, nu_p)
  2618. X     double M, e, *E_p, *nu_p;
  2619. X{
  2620. X  double corr, e_0, E_0, E_1;
  2621. X
  2622. X  e_0 = e * RAD_TO_DEG;
  2623. X
  2624. X  corr = 1;
  2625. X  E_0 = M;
  2626. X  while (corr > 0.00001) {
  2627. X    corr = (M + e_0 * DSIN(E_0) - E_0)/(1 - e * DCOS(E_0));
  2628. X    E_1 = E_0 + corr;
  2629. X    if (corr < 0) corr *= -1.0;
  2630. X    E_0 = E_1;
  2631. X  };
  2632. X    
  2633. X  *E_p = E_1;
  2634. X
  2635. X  *nu_p = 2.0 * RAD_TO_DEG * atan(sqrt((1+e)/(1-e))*DTAN(E_1/2));
  2636. X}
  2637. X
  2638. X
  2639. X
  2640. X
  2641. X/* Obliquity epsilon 
  2642. Xepsilon = 23.439291 - 0.0130042* T - 0.00000016* T*T - 0.000000504* T*T*T;
  2643. X*/
  2644. Xstatic double
  2645. Xobl_jd(jd)
  2646. Xdouble jd;
  2647. X{
  2648. X  double T = (jd - 2451545.0)/36525.0;
  2649. X
  2650. X  return (23.439291 - 0.0130042* T - 0.00000016* T*T - 0.000000504* T*T*T);
  2651. X}
  2652. X
  2653. X
  2654. X
  2655. Xstatic double
  2656. Xinto_range(ang)
  2657. Xdouble ang;
  2658. X{
  2659. X  long i;
  2660. X
  2661. X  i = (long)floor(ang/360.0);
  2662. X
  2663. X  ang = ang - i * 360;
  2664. X
  2665. X  return(ang);
  2666. X}  
  2667. X  
  2668. Xstatic void
  2669. Xsun_pos(jd, sun_data)
  2670. X     double jd;
  2671. X     sun_data_t *sun_data;
  2672. X{
  2673. X  double L, M, Theta, R;
  2674. X  double e, nu, E;
  2675. X  double T;
  2676. X  double epsilon;
  2677. X
  2678. X  T =  (jd - MJD0)/36525.0;
  2679. X
  2680. X  M = into_range(358.47583 + 35999.04975*T - 0.000150*T*T - 0.0000033*T*T*T);
  2681. X  e = 0.01675104 - 0.0000418*T - 0.000000126*T*T;
  2682. X  L = into_range(279.69668 + 36000.76892*T + 0.0003025*T*T);
  2683. X  anom_calc(M, e, &E, &nu);
  2684. X  Theta = into_range(L + nu - M);
  2685. X  R = 1.0000002*(1.0 - e * DCOS(E));
  2686. X
  2687. X
  2688. X  sun_data->R = R;
  2689. X  sun_data->Theta = Theta;
  2690. X  epsilon = 23.439291 - 0.0130042* T - 0.00000016* T*T - 0.000000504* T*T*T;
  2691. X  sun_data->alpha
  2692. X    = into_range(RAD_TO_DEG * atan2(DCOS(epsilon)*DSIN(Theta), DCOS(Theta)));
  2693. X  sun_data->delta = 
  2694. X    RAD_TO_DEG * asin(DSIN(epsilon)*DSIN(Theta));
  2695. X}
  2696. END_OF_FILE
  2697.   if test 36774 -ne `wc -c <'satmenu.c'`; then
  2698.     echo shar: \"'satmenu.c'\" unpacked with wrong size!
  2699.   fi
  2700.   # end of 'satmenu.c'
  2701. fi
  2702. echo shar: End of archive 13 \(of 21\).
  2703. cp /dev/null ark13isdone
  2704. MISSING=""
  2705. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  2706.     if test ! -f ark${I}isdone ; then
  2707.     MISSING="${MISSING} ${I}"
  2708.     fi
  2709. done
  2710. if test "${MISSING}" = "" ; then
  2711.     echo You have unpacked all 21 archives.
  2712.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2713.     echo Building ephem.db
  2714.     cat > ephem.db.Z.uu ephem.db.Z.uu.?
  2715.     uudecode ephem.db.Z.uu
  2716.     rm ephem.db.Z.uu ephem.db.Z.uu.?
  2717.     uncompress ephem.db.Z
  2718.     echo Building skyviewmenu.c
  2719.     cat > skyviewmenu.c skyviewmenu.c.?
  2720.     rm skyviewmenu.c.?
  2721.     echo Building smallfm.xbm
  2722.     cat > smallfm.xbm smallfm.xbm.?
  2723.     rm smallfm.xbm.?
  2724. else
  2725.     echo You still must unpack the following archives:
  2726.     echo "        " ${MISSING}
  2727. fi
  2728. exit 0
  2729. exit 0 # Just in case...
  2730. -- 
  2731.   // chris@IMD.Sterling.COM            | Send comp.sources.x submissions to:
  2732. \X/  Amiga - The only way to fly!      |
  2733.  "It's intuitively obvious to the most |    sources-x@imd.sterling.com
  2734.   casual observer..."                  |
  2735.