home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part18 / misc.c < prev    next >
C/C++ Source or Header  |  1993-05-15  |  20KB  |  813 lines

  1. /* misc handy functions.
  2.  * every system has such, no?
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <math.h>
  8. #if defined(__STDC__)
  9. #include <stdlib.h>
  10. #endif
  11. #include <X11/Xlib.h>
  12. #include <X11/cursorfont.h>
  13. #include <Xm/Xm.h>
  14. #include <Xm/PushB.h>
  15. #include "astro.h"
  16. #include "circum.h"
  17.  
  18. #if defined(__STDC__) || defined(__cplusplus)
  19. #define P_(s) s
  20. #else
  21. #define P_(s) ()
  22. #endif
  23.  
  24. extern Now *mm_get_now P_((void));
  25. extern int listing_ison P_((void));
  26. extern int plot_ison P_((void));
  27. extern int srch_ison P_((void));
  28. extern void dm_newobj P_((int dbidx));
  29. extern void dm_selection_mode P_((int whether));
  30. extern void dm_update P_((Now *np, int how_much));
  31. extern void e_cursor P_((Cursor c));
  32. extern void e_selection_mode P_((int whether));
  33. extern void e_update P_((Now *np, int force));
  34. extern void f_showit P_((Widget w, char *s));
  35. extern void fs_date P_((char out[], double jd));
  36. extern void fs_time P_((char out[], double t));
  37. extern void jm_selection_mode P_((int whether));
  38. extern void jm_update P_((Now *np, int how_much));
  39. extern void lst_log P_((char *name, char *str));
  40. extern void lst_selection P_((char *name));
  41. extern void m_update P_((Now *np, int how_much));
  42. extern void mars_cursor P_((Cursor c));
  43. extern void mars_selection_mode P_((int whether));
  44. extern void mars_update P_((Now *np, int force));
  45. extern void mm_selection_mode P_((int whether));
  46. extern void obj_newdb P_((int appended));
  47. extern void obj_update P_((Now *np, int howmuch));
  48. extern void plt_log P_((char *name, double value));
  49. extern void plt_selection P_((char *name));
  50. extern void sm_selection_mode P_((int whether));
  51. extern void sm_update P_((Now *np, int how_much));
  52. extern void srch_log P_((char *name, double value));
  53. extern void srch_selection P_((char *name));
  54. extern void srch_selection_mode P_((int whether));
  55. extern void ss_newobj P_((int dbidx));
  56. extern void ss_update P_((Now *np, int how_much));
  57. extern void sv_newdb P_((int appended));
  58. extern void sv_newobj P_((int dbidx));
  59. extern void sv_update P_((Now *np, int how_much));
  60. extern void utc_gst P_((double Mjd, double utc, double *gst));
  61. extern void xe_msg P_((char *msg, int app_modal));
  62.  
  63. void set_something P_((Widget w, char *resource, char *value));
  64. void get_something P_((Widget w, char *resource, char *value));
  65. void get_xmstring P_((Widget w, char *resource, char **txtp));
  66. void set_xmstring P_((Widget w, char *resource, char *txt));
  67. void range P_((double *v, double r));
  68. void now_lst P_((Now *np, double *lst));
  69. void rnd_second P_((double *t));
  70. double mjd_day P_((double jd));
  71. double mjd_hr P_((double jd));
  72. void zero_mem P_((char *loc, unsigned len));
  73. void watch_cursor P_((int want));
  74. void all_update P_((Now *np, int how_much));
  75. void all_newobj P_((int dbidx));
  76. void all_newdb P_((int appended));
  77. void all_selection_mode P_((int whether));
  78. void register_selection P_((char *name));
  79. void field_log P_((Widget w, double value, int logv, char *str));
  80. void prompt_map_cb P_((Widget w, XtPointer client, XtPointer call));
  81. static void get_color_resource P_((Widget w, char *cname, Pixel *p));
  82. static get_views_font P_((Display *dsp, Font *fp));
  83. void obj_pickgc P_((Obj *op, Widget w, GC *gcp));
  84. int tickmarks P_((double min, double max, int numdiv, double ticks[]));
  85. char *obj_description P_((Obj *op));
  86. void timestamp P_((Now *np, Widget w));
  87. int any_ison P_((void));
  88. int lc P_((int cx, int cy, int cw, int x1, int y1, int x2, int y2, int *sx1, int *sy1, int *sx2, int *sy2));
  89. void hg_mag P_((double h, double g, double rp, double rho, double rsn, double *mp));
  90. void gk_mag P_((double g, double k, double rp, double rho, double *mp));
  91.  
  92. #undef P_
  93.  
  94. extern Widget toplevel_w;
  95. extern char *myclass;
  96. #define    XtD    XtDisplay(toplevel_w)
  97.  
  98. /* handy way to set one resource for a widget.
  99.  * shouldn't use this if you have several things to set for the same widget.
  100.  */
  101. void
  102. set_something (w, resource, value)
  103. Widget w;
  104. char *resource;
  105. char *value;
  106. {
  107.     Arg a[1];
  108.  
  109.     if (!w) {
  110.         printf ("set_something (%s) called with w==0\n", resource);
  111.         exit(1);
  112.     }
  113.  
  114.     XtSetArg (a[0], resource, value);
  115.     XtSetValues (w, a, 1);
  116. }
  117.  
  118. /* handy way to get one resource for a widget.
  119.  * shouldn't use this if you have several things to get for the same widget.
  120.  */
  121. void
  122. get_something (w, resource, value)
  123. Widget w;
  124. char *resource;
  125. char *value;
  126. {
  127.     Arg a[1];
  128.  
  129.     if (!w) {
  130.         printf ("get_something (%s) called with w==0\n", resource);
  131.         exit(1);
  132.     }
  133.  
  134.     XtSetArg (a[0], resource, value);
  135.     XtGetValues (w, a, 1);
  136. }
  137.  
  138. /* return the given XmString resource from the given widget as a char *.
  139.  * N.B. based on a sample in Heller, pg 178, the string back from
  140.  *   XmStringGetLtoR should be XtFree'd. Therefore, OUR caller should always
  141.  *   XtFree (*txtp).
  142.  */
  143. void
  144. get_xmstring (w, resource, txtp)
  145. Widget w;
  146. char *resource;
  147. char **txtp;
  148. {
  149.     static char me[] = "get_xmstring()";
  150.     static char hah[] = "??";
  151.  
  152.     if (!w) {
  153.         printf ("%s: called for %s with w==0\n", me, resource);
  154.         exit(1);
  155.     } else {
  156.         XmString str;
  157.         get_something(w, resource, (char *)&str); 
  158.         if (!XmStringGetLtoR (str, XmSTRING_DEFAULT_CHARSET, txtp)) {
  159.         /*
  160.         fprintf (stderr, "%s: can't get string resource %s\n", me,
  161.                                 resource);
  162.         exit (1);
  163.         */
  164.         (void) strcpy (*txtp = XtMalloc(sizeof(hah)), hah);
  165.         }
  166.         XmStringFree (str);
  167.     }
  168. }
  169.  
  170. void
  171. set_xmstring (w, resource, txt)
  172. Widget w;
  173. char *resource;
  174. char *txt;
  175. {
  176.     XmString str;
  177.  
  178.     if (!w) {
  179.         printf ("set_xmstring called for %s with w==0\n", resource);
  180.         return;
  181.     }
  182.  
  183.     str = XmStringCreateLtoR (txt, XmSTRING_DEFAULT_CHARSET);
  184.     set_something (w, resource, (char *)str);
  185.     XmStringFree (str);
  186. }
  187.  
  188. /* insure 0 <= *v < r.
  189.  */
  190. void
  191. range (v, r)
  192. double *v, r;
  193. {
  194.     *v -= r*floor(*v/r);
  195. }
  196.  
  197. void
  198. now_lst (np, lst)
  199. Now *np;
  200. double *lst;
  201. {
  202.     utc_gst (mjd_day(mjd), mjd_hr(mjd), lst);
  203.     *lst += radhr(lng);
  204.     range (lst, 24.0);
  205. }
  206.  
  207. /* round a time in days, *t, to the nearest second, IN PLACE. */
  208. void
  209. rnd_second (t)
  210. double *t;
  211. {
  212.     *t = floor(*t*SPD+0.5)/SPD;
  213. }
  214.     
  215. double
  216. mjd_day(jd)
  217. double jd;
  218. {
  219.     return (floor(jd-0.5)+0.5);
  220. }
  221.  
  222. double
  223. mjd_hr(jd)
  224. double jd;
  225. {
  226.     return ((jd-mjd_day(jd))*24.0);
  227. }
  228.  
  229. /* zero from loc for len bytes */
  230. void
  231. zero_mem (loc, len)
  232. char *loc;
  233. unsigned len;
  234. {
  235.     (void) memset (loc, 0, len);
  236. }
  237.  
  238. /* called to set or unset the watch cursor on all menus.
  239.  * allow for nested requests.
  240.  */
  241. void
  242. watch_cursor(want)
  243. int want;
  244. {
  245.     extern void dm_cursor();
  246.     extern void db_cursor();
  247.     extern void jm_cursor();
  248.     extern void lst_cursor();
  249.     extern void main_cursor();
  250.     extern void m_cursor();
  251.     extern void msg_cursor();
  252.     extern void obj_cursor();
  253.     extern void plt_cursor();
  254.     extern void sm_cursor();
  255.     extern void sv_cursor();
  256.     extern void svf_cursor();
  257.     extern void ss_cursor();
  258.     extern void srch_cursor();
  259.     extern void v_cursor();
  260.     static Cursor wc;
  261.     static nreqs;
  262.     Cursor c;
  263.  
  264.     if (!wc)
  265.         wc = XCreateFontCursor (XtD, XC_watch);
  266.  
  267.     if (want) {
  268.         if (nreqs++ > 0)
  269.         return;
  270.         c = wc;
  271.     } else {
  272.         if (--nreqs > 0)
  273.         return;
  274.         c = (Cursor)0;
  275.     }
  276.  
  277.     dm_cursor(c);
  278.     db_cursor(c);
  279.     jm_cursor(c);
  280.     mars_cursor(c);
  281.     e_cursor(c);
  282.     lst_cursor(c);
  283.     main_cursor(c);
  284.     m_cursor(c);
  285.     msg_cursor(c);
  286.     obj_cursor(c);
  287.     plt_cursor(c);
  288.     sm_cursor(c);
  289.     sv_cursor(c);
  290.     svf_cursor(c);
  291.     ss_cursor(c);
  292.     srch_cursor(c);
  293.     v_cursor(c);
  294.  
  295.     XSync (XtD, 0);
  296. }
  297.  
  298. /* print stuff on other menus */
  299. void
  300. all_update(np, how_much)
  301. Now *np;
  302. int how_much;
  303. {
  304.     dm_update (np, how_much);
  305.     mars_update (np, how_much);
  306.     e_update (np, how_much);
  307.     jm_update (np, how_much);
  308.     sm_update (np, how_much);
  309.     ss_update (np, how_much);
  310.     sv_update (np, how_much);
  311.     m_update  (np, how_much);
  312.     obj_update (np, how_much);
  313. }
  314.  
  315. /* tell everyone who might care that a user-defined object has changed
  316.  * then recompute and redisplay new values.
  317.  */
  318. void
  319. all_newobj(dbidx)
  320. int dbidx;
  321. {
  322.     watch_cursor (1);
  323.  
  324.     dm_newobj(dbidx);
  325.     ss_newobj(dbidx);
  326.     sv_newobj(dbidx);
  327.     all_update (mm_get_now(), 1);
  328.  
  329.     watch_cursor (0);
  330. }
  331.  
  332. /* tell everyone who might care that the db (beyond NOBJ) has changed.
  333.  * appended is true if it grew; else it was replaced.
  334.  */
  335. void
  336. all_newdb(appended)
  337. int appended;
  338. {
  339.     watch_cursor (1);
  340.  
  341.     obj_newdb(appended);
  342.     sv_newdb(appended);
  343.  
  344.     watch_cursor (0);
  345. }
  346.  
  347. /* inform all menus that have something selectable for plotting/listing/srching
  348.  * wether we are now in a mode that they should report when those fields are
  349.  * selected.
  350.  */
  351. void
  352. all_selection_mode(whether)
  353. int whether;
  354. {
  355.     dm_selection_mode(whether);
  356.     mm_selection_mode(whether);
  357.     jm_selection_mode(whether);
  358.     mars_selection_mode(whether);
  359.     e_selection_mode(whether);
  360.     sm_selection_mode(whether);
  361.     srch_selection_mode(whether);
  362. }
  363.  
  364. /* inform all potentially interested parties of the name of a field that
  365.  * it might want to use for latter.
  366.  * this is just to collect in one place all the modules that gather care.
  367.  */
  368. void
  369. register_selection (name)
  370. char *name;
  371. {
  372.     plt_selection (name);
  373.     lst_selection (name);
  374.     srch_selection (name);
  375. }
  376.  
  377. /* if we are plotting/listing/searching, send the current field info to them.
  378.  * N.B. only send `value' to plot and search if logv is not 0.
  379.  */
  380. void
  381. field_log (w, value, logv, str)
  382. Widget w;
  383. double value;
  384. int logv;
  385. char *str;
  386. {
  387.     char *name;
  388.  
  389.     if (!any_ison())
  390.         return;
  391.  
  392.     get_something (w, XmNuserData, (char *)&name);
  393.     if (name) {
  394.         if (logv) {
  395.         plt_log (name, value);
  396.         srch_log (name, value);
  397.         }
  398.         lst_log (name, str);
  399.     }
  400. }
  401.  
  402. /* may be connected as the mapCallback to any convenience Dialog to
  403.  * position it centered the cursor (allowing for the screen edges).
  404.  */
  405. /* ARGSUSED */
  406. void
  407. prompt_map_cb (w, client, call)
  408. Widget w;
  409. XtPointer client;
  410. XtPointer call;
  411. {
  412.     Window root, child;
  413.     int rx, ry, wx, wy;    /* rx/y: cursor loc on root window */
  414.     unsigned sw, sh;    /* screen width/height */
  415.     Dimension ww, wh;    /* this widget's width/height */
  416.     Position x, y;        /* final location */
  417.     unsigned mask;
  418.     Arg args[20];
  419.     int n;
  420.  
  421.     XQueryPointer (XtDisplay(w), XtWindow(w),
  422.                 &root, &child, &rx, &ry, &wx, &wy, &mask);
  423.     sw = WidthOfScreen (XtScreen(w));
  424.     sh = HeightOfScreen(XtScreen(w));
  425.     n = 0;
  426.     XtSetArg (args[n], XmNwidth, &ww); n++;
  427.     XtSetArg (args[n], XmNheight, &wh); n++;
  428.     XtGetValues (w, args, n);
  429.  
  430.     x = rx - ww/2;
  431.     if (x < 0)
  432.         x = 0;
  433.     else if (x + ww >= sw)
  434.         x = sw - ww;
  435.     y = ry - wh/2;
  436.     if (y < 0)
  437.         y = 0;
  438.     else if (y + wh >= sh)
  439.         y = sh - wh;
  440.  
  441.     n = 0;
  442.     XtSetArg (args[n], XmNx, x); n++;
  443.     XtSetArg (args[n], XmNy, y); n++;
  444.     XtSetValues (w, args, n);
  445. }
  446.  
  447. /* get the named color in *p, else set to w's XmNforeground.
  448.  */
  449. static void
  450. get_color_resource (w, cname, p)
  451. Widget w;
  452. char *cname;
  453. Pixel *p;
  454. {
  455.     Display *dsp = XtDisplay(w);
  456.     Colormap def_cm = DefaultColormap (dsp, 0);
  457.     XColor defxc, dbxc;
  458.     char *cval;
  459.  
  460.     cval = XGetDefault (dsp, myclass, cname);
  461.  
  462.     if (!cval || !XAllocNamedColor (dsp, def_cm, cval, &defxc, &dbxc)) {
  463.         char msg[128];
  464.         if (!cval)
  465.         (void) sprintf (msg, "Can't find resource `%.80s'", cname);
  466.         else
  467.         (void) sprintf (msg, "Can't Alloc color `%.80s'", cval);
  468.         (void) strcat (msg, "... so using *foreground.\n");
  469.         xe_msg(msg, 0);
  470.         get_something (w, XmNforeground, (char *)p);
  471.     } else
  472.         *p = defxc.pixel;
  473. }
  474.  
  475. /* get the Font we want to use when drawing text for the display views.
  476.  * return 0 if ok, else -1.
  477.  */
  478. static
  479. get_views_font (dsp, fp)
  480. Display *dsp;
  481. Font *fp;
  482. {
  483.     static char resname[] = "viewsFont";
  484.     char *fname;
  485.     XFontStruct *fsp;
  486.  
  487.     fname = XGetDefault (dsp, myclass, resname);
  488.  
  489.     /* use XLoadQueryFont because it returns gracefully if font is not
  490.      * found; XloadFont calls the default X error handler.
  491.      */
  492.     if (!fname || !(fsp = XLoadQueryFont (dsp, fname))) {
  493.         char msg[256];
  494.  
  495.         if (!fname)
  496.         (void) sprintf (msg, "Can't find resource `%.180s'", resname);
  497.         else
  498.         (void) sprintf (msg, "Can't load font `%.180s'", fname);
  499.         (void) strcat (msg, "... using default server font");
  500.         xe_msg(msg, 0);
  501.         return (-1);
  502.     }
  503.     
  504.     *fp = fsp->fid;
  505.     return (0);
  506. }
  507.  
  508. /* given an object, return a GC for it.
  509.  * Use the colors defined in the X resoucres, else use the foreground of the
  510.  * given widget.
  511.  */
  512. void
  513. obj_pickgc(op, w, gcp)
  514. Obj *op;
  515. Widget w;
  516. GC *gcp;
  517. {
  518.     /* names of resource colors for the planets.
  519.      * N.B. should be in the same order as the defines in astro.h
  520.      */
  521.     static char *objcolnames[NOBJ-2] = {
  522.         "mercuryColor", "venusColor", "marsColor", "jupiterColor",
  523.         "saturnColor", "uranusColor", "neptuneColor", "plutoColor",
  524.         "sunColor", "moonColor"
  525.     };
  526.     /* names of resource colors for stellar types.
  527.      */
  528.     static char *starcolnames[] = {
  529.         "hotStarColor", "mediumStarColor", "coolStarColor"
  530.     };
  531.     static GC objgcs[XtNumber(objcolnames)];
  532.     static GC stargcs[XtNumber(starcolnames)];
  533.     static GC other_gc;
  534.  
  535.     /* make all the gcs the first time through */
  536.     if (!other_gc) {
  537.         Display *dsp = XtDisplay(w);
  538.         Window win = XtWindow(w);
  539.         unsigned gcm = GCForeground;
  540.         Font f;
  541.         XGCValues gcv;
  542.         Pixel p;
  543.         int i;
  544.  
  545.         if (get_views_font (dsp, &f) == 0) {
  546.         gcm |= GCFont;
  547.         gcv.font = f;
  548.         }
  549.  
  550.         /* make the planet gcs */
  551.         for (i = 0; i < XtNumber(objgcs); i++) {
  552.         get_color_resource (w, objcolnames[i], &p);
  553.         gcv.foreground = p;
  554.         objgcs[i] = XCreateGC (dsp, win, gcm, &gcv);
  555.         }
  556.  
  557.         /* make the star color gcs */
  558.         for (i = 0; i < XtNumber(stargcs); i++) {
  559.         get_color_resource (w, starcolnames[i], &p);
  560.         gcv.foreground = p;
  561.         stargcs[i] = XCreateGC (dsp, win, gcm, &gcv);
  562.         }
  563.  
  564.         /* make the gc for everything else */
  565.         get_something (w, XmNforeground, (char *)&p);
  566.         gcv.foreground = p;
  567.         other_gc = XCreateGC (dsp, win, gcm, &gcv);
  568.     }
  569.  
  570.     if (op->type == PLANET && op->pl.code < XtNumber(objgcs))
  571.         *gcp = objgcs[op->pl.code];
  572.     else if (op->type == FIXED && op->f_spect[0])
  573.         switch (op->f_spect[0]) {
  574.         case 'O': case 'B': case 'A': case 'W':
  575.         *gcp = stargcs[0];
  576.         break;
  577.         case 'F': case 'G':
  578.         *gcp = stargcs[1];
  579.         break;
  580.         case 'K': case 'M': case 'N': case 'R': case 'S':
  581.         *gcp = stargcs[2];
  582.         break;
  583.         default:
  584.         *gcp = other_gc;
  585.         break;
  586.         }
  587.     else
  588.         *gcp = other_gc;
  589. }
  590.  
  591. /* given min and max and an approximate number of divisions desired,
  592.  * fill in ticks[] with nicely spaced values and return how many.
  593.  * N.B. return value, and hence number of entries to ticks[], might be as
  594.  *   much as 2 more than numdiv.
  595.  */
  596. int
  597. tickmarks (min, max, numdiv, ticks)
  598. double min, max;
  599. int numdiv;
  600. double ticks[];
  601. {
  602.         static int factor[] = { 1, 2, 5 };
  603.         double minscale;
  604.         double delta;
  605.     double lo;
  606.         double v;
  607.         int n;
  608.  
  609.         minscale = fabs(max - min);
  610.         delta = minscale/numdiv;
  611.         for (n=0; n < sizeof(factor)/sizeof(factor[0]); n++) {
  612.         double scale;
  613.         double x = delta/factor[n];
  614.             if ((scale = (pow(10.0, ceil(log10(x)))*factor[n])) < minscale)
  615.         minscale = scale;
  616.     }
  617.         delta = minscale;
  618.  
  619.         lo = floor(min/delta);
  620.         for (n = 0; (v = delta*(lo+n)) < max+delta; )
  621.         ticks[n++] = v;
  622.  
  623.     return (n);
  624. }
  625.  
  626. /* given an Obj *, return its type as a descriptive string.
  627.  * if it's of type fixed then return its class description.
  628.  * N.B. we return the address of static storage -- do not free or change.
  629.  */
  630. char *
  631. obj_description (op)
  632. Obj *op;
  633. {
  634.     static struct {
  635.         char class;
  636.         char *desc;
  637.     } fixed_class_map[] = {
  638.         {'C', "Globular Cluster"},
  639.         {'U', "Cluster, with nebulosity"},
  640.         {'O', "Open Cluster"},
  641.         {'G', "Spiral Galaxy"},
  642.         {'H', "Spherical Galaxy"},
  643.         {'A', "Cluster of Galaxies"},
  644.         {'N', "Bright Nebula"},
  645.         {'F', "Diffuse Nebula"},
  646.         {'K', "Dark Nebula"},
  647.         {'P', "Planetary Nebula"},
  648.         {'Q', "Quasar"},
  649.         {'T', "Stellar Object"},
  650.         {'B', "Binary Star"},
  651.         {'D', "Double Star"},
  652.         {'M', "Multiple Star"},
  653.         {'S', "Star"},
  654.         {'V', "Variable Star"},
  655.     };
  656.  
  657.     switch (op->type) {
  658.     case FIXED:
  659.         if (op->f_class) {
  660.         int i;
  661.         for (i = 0; i < XtNumber(fixed_class_map); i++)
  662.             if (fixed_class_map[i].class == op->f_class)
  663.             return (fixed_class_map[i].desc);
  664.         }
  665.         return ("Fixed");
  666.     case PARABOLIC:
  667.         return ("Solar - Parabolic");
  668.     case HYPERBOLIC:
  669.         return ("Solar - Hyperbolic");
  670.     case ELLIPTICAL:
  671.         return ("Solar - Elliptical");
  672.     case PLANET:
  673.         return ("Planet");
  674.     default:
  675.         printf ("obj_description: unknown type: 0x%x\n", op->type);
  676.         exit (1);
  677.         return (NULL);    /* for lint */
  678.     }
  679. }
  680.  
  681. /* set the XmNlabelString resource of the given widget to the date and time 
  682.  * as given in the Now struct at *np.
  683.  * avoid unnecessary blinking by using f_showit().
  684.  */
  685. void
  686. timestamp (np, w)
  687. Now *np;
  688. Widget w;
  689. {
  690.     char d[32], t[32], out[64];
  691.     double lmjd = mjd - tz/24.0;
  692.     char timezonename[32];
  693.  
  694.     fs_date (d, mjd_day(lmjd));
  695.     fs_time (t, mjd_hr(lmjd));
  696.     if (tznm[0] == '\0') {
  697.         if (tz == 0)
  698.         (void) strcpy(timezonename, "UTC");
  699.         else
  700.         (void) sprintf(timezonename, "UTC%c%g", tz<0?'+':'-', fabs(tz));
  701.     } else
  702.         (void) strcpy (timezonename, tznm);
  703.     (void) sprintf (out, "%s %s %s", d, t, timezonename);
  704.     f_showit (w, out);
  705. }
  706.  
  707. /* return !0 if any of the button/data capture tools are active, else 0.
  708.  */
  709. any_ison()
  710. {
  711.     return (srch_ison() || plot_ison() || listing_ison());
  712. }
  713.  
  714. /* given a circle and a line segment, find a segment of the line inside the 
  715.  *   circle.
  716.  * return 0 and the segment end points if one exists, else 0.
  717.  * We use a parametric representation of the line:
  718.  *   x = x1 + (x2-x1)*t and y = y1 + (y2-y1)*t, 0 < t < 1
  719.  * and a centered representation of the circle:
  720.  *   (x - xc)**2 + (y - yc)**2 = r**2
  721.  * and solve for the t's that work, checking for usual conditions.
  722.  */
  723. lc (cx, cy, cw, x1, y1, x2, y2, sx1, sy1, sx2, sy2)
  724. int cx, cy, cw;            /* circle bounding box corner and width */
  725. int x1, y1, x2, y2;        /* line segment endpoints */
  726. int *sx1, *sy1, *sx2, *sy2;    /* segment inside the circle */
  727. {
  728.     int dx = x2 - x1;
  729.     int dy = y2 - y1;
  730.     int r = cw/2;
  731.     int xc = cx + r;
  732.     int yc = cy + r;
  733.     int A = x1 - xc;
  734.     int B = y1 - yc;
  735.     double a = dx*dx + dy*dy;    /* O(2 * 2**16 * 2**16) */
  736.     double b = 2*(dx*A + dy*B);    /* O(4 * 2**16 * 2**16) */
  737.     double c = A*A + B*B - r*r;    /* O(2 * 2**16 * 2**16) */
  738.     double d = b*b - 4*a*c;        /* O(2**32 * 2**32) */
  739.     double sqrtd;
  740.     double t1, t2;
  741.  
  742.     if (d <= 0)
  743.         return (-1);    /* containing line is purely outside circle */
  744.  
  745.     sqrtd = sqrt(d);
  746.     t1 = (-b - sqrtd)/(2.0*a);
  747.     t2 = (-b + sqrtd)/(2.0*a);
  748.  
  749.     if (t1 >= 1.0 || t2 <= 0.0)
  750.         return (-1);    /* segment is purely outside circle */
  751.  
  752.     /* we know now that some part of the segment is inside,
  753.      * ie, t1 < 1 && t2 > 0
  754.      */
  755.  
  756.     if (t1 <= 0.0) {
  757.         /* (x1,y1) is inside circle */
  758.         *sx1 = x1;
  759.         *sy1 = y1;
  760.     } else {
  761.         *sx1 = x1 + dx*t1;
  762.         *sy1 = y1 + dy*t1;
  763.     }
  764.  
  765.     if (t2 >= 1.0) {
  766.         /* (x2,y2) is inside circle */
  767.         *sx2 = x2;
  768.         *sy2 = y2;
  769.     } else {
  770.         *sx2 = x1 + dx*t2;
  771.         *sy2 = y1 + dy*t2;
  772.     }
  773.  
  774.     return (0);
  775. }
  776.  
  777. /* compute visual magnitude using the H/G parameters used in the Astro Almanac.
  778.  * these are commonly used for asteroids.
  779.  */
  780. void
  781. hg_mag (h, g, rp, rho, rsn, mp)
  782. double h, g;
  783. double rp;    /* sun-obj dist, AU */
  784. double rho;    /* earth-obj dist, AU */
  785. double rsn;    /* sun-earth dist, AU */
  786. double *mp;
  787. {
  788.     double psi_t, Psi_1, Psi_2, beta;
  789.     double tb2;
  790.  
  791.     beta = acos((rp*rp + rho*rho - rsn*rsn)/ (2*rp*rho));
  792.     tb2 = tan(beta/2.0);
  793.     /* psi_t = exp(log(tan(beta/2.0))*0.63); */
  794.     psi_t = pow (tb2, 0.63);
  795.     Psi_1 = exp(-3.33*psi_t);
  796.     /* psi_t = exp(log(tan(beta/2.0))*1.22); */
  797.     psi_t = pow (tb2, 1.22);
  798.     Psi_2 = exp(-1.87*psi_t);
  799.     *mp = h + 5.0*log10(rp*rho) - 2.5*log10((1-g)*Psi_1 + g*Psi_2);
  800. }
  801.  
  802. /* computer visual magnitude using the g/k parameters commonly used for comets.
  803.  */
  804. void
  805. gk_mag (g, k, rp, rho, mp)
  806. double g, k;
  807. double rp;    /* sun-obj dist, AU */
  808. double rho;    /* earth-obj dist, AU */
  809. double *mp;
  810. {
  811.     *mp = g + 5.0*log10(rho) + 2.5*k*log10(rp);
  812. }
  813.