home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part05 / formats.c < prev   
Encoding:
C/C++ Source or Header  |  1993-05-15  |  12.0 KB  |  554 lines

  1. /* all the screen oriented printing should go through here.
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include <math.h>
  6. #include <ctype.h>
  7. #if defined(__STDC__)
  8. #include <stdlib.h>
  9. #endif
  10. #include <X11/Xlib.h>
  11. #include <Xm/Xm.h>
  12. #include "astro.h"
  13. #include "preferences.h"
  14.  
  15. #if defined(__STDC__) || defined(__cplusplus)
  16. #define P_(s) s
  17. #else
  18. #define P_(s) ()
  19. #endif
  20.  
  21. extern void dec_sex P_((double d, int *hd, int *m, int *s, int *isneg));
  22. extern void f_dec_sexsign P_((double x, int *h, int *m, int *s));
  23. extern void field_log P_((Widget w, double value, int logv, char *str));
  24. extern void get_xmstring P_((Widget w, char *resource, char **txtp));
  25. extern void mjd_cal P_((double Mjd, int *mn, double *dy, int *yr));
  26. extern void mjd_year P_((double Mjd, double *yr));
  27. extern void set_xmstring P_((Widget w, char *resource, char *txt));
  28. extern void year_mjd P_((double y, double *Mjd));
  29.  
  30. void f_on P_((void));
  31. void f_off P_((void));
  32. int f_ison P_((void));
  33. void f_showit P_((Widget w, char *s));
  34. void f_sexad P_((Widget w, int a, int p, int mod, double v));
  35. void fs_sexad P_((char out[], int a, int p, int mod, double v));
  36. void f_sexag P_((Widget w, int nd, double t));
  37. void fs_sexag P_((char out[], int nd, double t));
  38. void f_ra P_((Widget w, double ra));
  39. void fs_ra P_((char out[], double ra));
  40. void f_time P_((Widget w, double t));
  41. void fs_time P_((char out[], double t));
  42. void f_signtime P_((Widget w, double t));
  43. void fs_signtime P_((char out[], double t));
  44. void f_mtime P_((Widget w, double t));
  45. void fs_mtime P_((char out[], double t));
  46. void f_angle P_((Widget w, double a));
  47. void fs_angle P_((char out[], double a));
  48. void f_gangle P_((Widget w, double a));
  49. void fs_gangle P_((char out[], double a));
  50. void f_date P_((Widget w, double jd));
  51. void fs_date P_((char out[], double jd));
  52. void f_string P_((Widget w, char *s));
  53. void f_double P_((Widget w, char *fmt, double f));
  54. void f_sscansex P_((char *bp, int *d, int *m, int *s));
  55. void f_sscandate P_((char *bp, int pref, int *m, double *d, int *y));
  56. void f_dec_sexsign P_((double x, int *h, int *m, int *s));
  57.  
  58. #undef P_
  59.  
  60. extern Widget toplevel_w;
  61.  
  62. /* suppress screen io if this is true, but always log stuff.
  63.  */
  64. static int f_scrnoff;
  65. void
  66. f_on ()
  67. {
  68.     f_scrnoff = 0;
  69. }
  70. void
  71. f_off ()
  72. {
  73.     f_scrnoff = 1;
  74. }
  75. f_ison()
  76. {
  77.     return (!f_scrnoff);
  78. }
  79.  
  80. /* set the given widget's XmNlabelString to s if it's not already the same
  81.  * and we are indeed displaying stuff at the moment.
  82.  */
  83. void
  84. f_showit (w, s)
  85. Widget w;
  86. char *s;
  87. {
  88.     char *txtp;
  89.  
  90.     if (f_scrnoff)
  91.         return;
  92.     get_xmstring (w, XmNlabelString, &txtp);
  93.     if (strcmp (txtp, s))
  94.         set_xmstring (w, XmNlabelString, s);
  95.     XtFree (txtp);
  96. }
  97.  
  98. /* print the given value, v, in "sexadecimal" format to widget w.
  99.  */
  100. void
  101. f_sexad (w, a, p, mod, v)
  102. Widget w;
  103. int a, p;    /* left space, min precision */
  104. int mod;    /* don't let whole portion get this big */
  105. double v;
  106. {
  107.     char out[32];
  108.  
  109.     fs_sexad (out, a, p, mod, v);
  110.     field_log (w, v, 1, out);
  111.     f_showit (w, out);
  112. }
  113.  
  114. /* print the given value, v, in "sexadecimal" format into string out.
  115.  * ie, in the form A:m.P, where A is a digits wide, P is p digits.
  116.  * if p == 0, then no decimal point either.
  117.  */
  118. void
  119. fs_sexad (out, a, p, mod, v)
  120. char out[];
  121. int a, p;    /* left space, min precision */
  122. int mod;    /* don't let whole portion get this big */
  123. double v;
  124. {
  125.     char str[32];
  126.     long dec;
  127.     double frac;
  128.     int visneg;
  129.  
  130.     if (v >= 0.0)
  131.         visneg = 0;
  132.     else {
  133.         if (v <= -0.5/60.0*pow(10.0,-1.0*p)) {
  134.         v = -v;
  135.         visneg = 1;
  136.         } else {
  137.         /* don't show as negative if less than the precision showing */
  138.         v = 0.0;
  139.         visneg = 0;
  140.         }
  141.     }
  142.  
  143.     dec = v;
  144.     frac = (v - dec)*60.0;
  145.     (void) sprintf (str, "59.%.*s5", p, "999999999");
  146.     if (frac >= atof (str)) {
  147.         dec += 1;
  148.         frac = 0.0;
  149.     }
  150.     dec %= mod;
  151.     if (dec == 0 && visneg)
  152.         (void) strcpy (str, "-0");
  153.     else
  154.         (void) sprintf (str, "%ld", visneg ? -dec : dec);
  155.  
  156.     /* would just do this if Turbo-C 2.0 %?.0f" worked:
  157.      * sprintf (astr, "%*s:%0*.*f", a, str, p == 0 ? 2 : p+3, p, frac);
  158.      */
  159.     if (p == 0)
  160.         (void) sprintf (out, "%*s:%02d", a, str, (int)(frac+0.5));
  161.     else
  162.         (void) sprintf (out, "%*s:%0*.*f", a, str, p+3, p, frac);
  163. }
  164.  
  165. /* print the given value, t, in sexagesimal format to widget w. */
  166. void
  167. f_sexag (w, nd, t)
  168. Widget w;
  169. int nd;
  170. double t;
  171. {
  172.     char out[32];
  173.  
  174.     fs_sexag (out, nd, t);
  175.     field_log (w, t, 1, out);
  176.     f_showit (w, out);
  177. }
  178.  
  179. /* print the given value, t, in sexagesimal format to string out[].
  180.  * ie, in the form T:mm:ss, where T is nd digits wide.
  181.  * N.B. we assume nd >= 2.
  182.  */
  183. void
  184. fs_sexag (out, nd, t)
  185. char out[];
  186. int nd;
  187. double t;
  188. {
  189.     int h, m, s;
  190.     int tisneg;
  191.     
  192.     dec_sex (t, &h, &m, &s, &tisneg);
  193.     if (h == 0 && tisneg)
  194.         (void) sprintf (out, "%*s-0:%02d:%02d", nd-2, "", m, s);
  195.     else
  196.         (void) sprintf (out, "%*d:%02d:%02d", nd, tisneg ? -h : h, m, s);
  197. }
  198.  
  199. /* print angle ra, in radians, in ra hours as hh:mm.m to widget w */
  200. void
  201. f_ra (w, ra)
  202. Widget w;
  203. double ra;
  204. {
  205.     f_sexad (w, 2, 1, 24, radhr(ra));
  206. }
  207.  
  208. /* print angle ra, in radians, in ra hours as hh:mm.m into string out[].
  209.  * N.B. we assume ra is >= 0.
  210.  */
  211. void
  212. fs_ra (out, ra)
  213. char out[];
  214. double ra;
  215. {
  216.     fs_sexad (out, 2, 1, 24, radhr(ra));
  217. }
  218.  
  219. /* print time, t, as hh:mm:ss */
  220. void
  221. f_time (w, t)
  222. Widget w;
  223. double t;
  224. {
  225.     f_sexag (w, 2, t);
  226. }
  227.  
  228. /* print time, t, as hh:mm:ss */
  229. void
  230. fs_time (out, t)
  231. char out[];
  232. double t;
  233. {
  234.     fs_sexag (out, 2, t);
  235. }
  236.  
  237. /* print time, t, as +/-hh:mm:ss (don't show leading +) */
  238. void
  239. f_signtime (w, t)
  240. Widget w;
  241. double t;
  242. {
  243.     f_sexag (w, 3, t);
  244. }
  245.  
  246. /* print time, t, as +/-hh:mm:ss (don't show leading +) */
  247. void
  248. fs_signtime (out, t)
  249. char out[];
  250. double t;
  251. {
  252.     fs_sexag (out, 3, t);
  253. }
  254.  
  255. /* print time, t, as hh:mm */
  256. void
  257. f_mtime (w, t)
  258. Widget w;
  259. double t;
  260. {
  261.     f_sexad (w, 2, 0, 24, t);
  262. }
  263.  
  264. /* print time, t, as hh:mm */
  265. void
  266. fs_mtime (out, t)
  267. char out[];
  268. double t;
  269. {
  270.     fs_sexad (out, 2, 0, 24, t);
  271. }
  272.  
  273. /* print angle, a, in rads, as degrees to widget w in form ddd:mm */
  274. void
  275. f_angle(w, a)
  276. Widget w;
  277. double a;
  278. {
  279.     f_sexad (w, 3, 0, 360, raddeg(a));
  280. }
  281.  
  282. /* print angle, a, in rads, as degrees into string out[] in form ddd:mm */
  283. void
  284. fs_angle(out, a)
  285. char out[];
  286. double a;
  287. {
  288.     fs_sexad (out, 3, 0, 360, raddeg(a));
  289. }
  290.  
  291. /* print angle, a, in rads, as degrees to widget w in form dddd:mm:ss */
  292. void
  293. f_gangle(w, a)
  294. Widget w;
  295. double a;
  296. {
  297.     f_sexag (w, 4, raddeg(a));
  298. }
  299.  
  300. /* print angle, a, in rads, as degrees into string out[] in form dddd:mm:ss */
  301. void
  302. fs_gangle(out, a)
  303. char out[];
  304. double a;
  305. {
  306.     fs_sexag (out, 4, raddeg(a));
  307. }
  308.  
  309. /* print the given modified Julian date, jd, in the preferred format.
  310.  */
  311. void
  312. f_date (w, jd)
  313. Widget w;
  314. double jd;
  315. {
  316.     char out[32];
  317.     double tmp;
  318.  
  319.     fs_date (out, jd);
  320.  
  321.     /* shadow to the plot subsystem as years. */
  322.     mjd_year (jd, &tmp);
  323.     field_log (w, tmp, 1, out);
  324.     f_showit (w, out);
  325. }
  326.  
  327. /* put the given modified Julian date, jd, in out[] according to preference
  328.  * format.
  329.  */
  330. void
  331. fs_date (out, jd)
  332. char out[];
  333. double jd;
  334. {
  335.     int p = pref_get (PREF_DATE_FORMAT);
  336.     int m, y;
  337.     double d;
  338.  
  339.     mjd_cal (jd, &m, &d, &y);
  340.     switch (p) {
  341.     case PREF_YMD:
  342.         (void) sprintf (out, "%4d/%02d/%02d", y, m, (int)d);
  343.         break;
  344.     case PREF_DMY:
  345.         (void) sprintf (out, "%2d/%02d/%-4d", (int)d, m, y);
  346.         break;
  347.     case PREF_MDY:
  348.         (void) sprintf (out, "%2d/%02d/%-4d", m, (int)d, y);
  349.         break;
  350.     default:
  351.         printf ("fs_date: bad date pref: %d\n", p);
  352.         exit (1);
  353.     }
  354. }
  355.  
  356. /* set w's XmNlabelString to s if it's not already the same and we are
  357.  * showing fields now.
  358.  * also, log the string if w is being used for logging now.
  359.  * N.B. do not use this for any widget that has its XmNuserData anything but
  360.  *   the default (NULL) or a valid field id string; ie. use only for widgets
  361.  *   that are buttons that can be "logged" for plotting etc. In all other cases
  362.  *   use f_showit() directly.
  363.  */
  364. void
  365. f_string (w, s)
  366. Widget w;
  367. char *s;
  368. {
  369.     field_log (w, 0.0, 0, s);
  370.     f_showit (w, s);
  371. }
  372.  
  373. void
  374. f_double (w, fmt, f)
  375. Widget w;
  376. char *fmt;
  377. double f;
  378. {
  379.     char str[80];
  380.     (void) sprintf (str, fmt, f);
  381.     field_log (w, f, 1, str);
  382.     f_showit (w, str);
  383. }
  384.  
  385. /* crack a line of the form X?X?X into its components,
  386.  *   where X is an integer and ? can be any character except '0-9' or '-',
  387.  *   such as ':' or '/'.
  388.  * only change those fields that are specified:
  389.  *   eg:  ::10    only changes *s
  390.  *        10    only changes *d
  391.  *        10:0  changes *d and *m
  392.  * if see '-' anywhere, first non-zero component will be made negative.
  393.  * TODO: s should be a double *.
  394.  */
  395. void
  396. f_sscansex (bp, d, m, s)
  397. char *bp;
  398. int *d, *m, *s;
  399. {
  400.     char c;
  401.     int *p = d;
  402.     int *nonzp = 0;
  403.     int sawneg = 0;
  404.     int innum = 0;
  405.  
  406.     while (c = *bp++)
  407.         if (isdigit(c)) {
  408.         if (!innum) {
  409.             *p = 0;
  410.             innum = 1;
  411.         }
  412.         *p = *p*10 + (c - '0');
  413.         if (*p && !nonzp)
  414.             nonzp = p;
  415.         } else if (c == '-') {
  416.         sawneg = 1;
  417.         } else if (p == s && c == '.') {
  418.         c = *bp++;
  419.         if (isdigit(c) && c >= '5') {
  420.             /* round up if see at least .5 */
  421.             if (++(*s) == 60) {
  422.             if (++(*m) == 60) {
  423.                 ++(*d);
  424.                 *m = 0;
  425.             }
  426.             *s = 0;
  427.             }
  428.         }
  429.         break;
  430.         } else if (c != ' ') {
  431.         /* advance to next component */
  432.         p = (p == d) ? m : s;
  433.         innum = 0;
  434.         }
  435.  
  436.     if (sawneg && nonzp)
  437.         *nonzp = -*nonzp;
  438. }
  439.  
  440. /* crack a floating date string, bp, of the form X/Y/Z determined by the
  441.  *   PREF_DATE_FORMAT preference into its components. allow the day to be a
  442.  *   floating point number,
  443.  * a lone component is always a year if it contains a decimal point or pref
  444.  *   is MDY or DMY and it is not a reasonable month or day value, respectively.
  445.  * leave any component unspecified unchanged.
  446.  * actually, the slashes may be anything but digits or a decimal point.
  447.  * this is functionally the same as f_sscansex() exept we allow for
  448.  *   the day portion to be real, and we don't handle negative numbers.
  449.  *   maybe someday we could make a combined one and use it everywhere.
  450.  */
  451. void
  452. f_sscandate (bp, pref, m, d, y)
  453. char *bp;
  454. int pref;       /* one of PREF_X for PREF_DATE_FORMAT */
  455. int *m, *y;
  456. double *d;
  457. {
  458.         char *bp0, c;
  459.         double comp[3]; /* the three components */
  460.         int set[3];     /* set[i] is 1 if component i is present */
  461.     int in;        /* scan state: 1 while we are in a component */
  462.     int ncomp;    /* incremented as each component is discovered */
  463.     int ndp;    /* number of decimal points in last component */
  464.  
  465.     set[0] = set[1] = set[2] = 0;
  466.     ncomp = 0;
  467.     in = 0;
  468.     ndp = 0;
  469.  
  470.     /* scan the input string.
  471.      * '\0' counts as a component terminator too.
  472.      */
  473.     do {
  474.         /* here, bp is the next character to be investigated */
  475.         c = *bp;
  476.         if (c == '.' || isdigit(c) || (c == '-' && !in)) {
  477.         /* found what passes for a floating point number */
  478.         if (in == 0) {
  479.             /* save the beginning of it in bp0 and init ndp */
  480.             bp0 = bp;
  481.             in = 1;
  482.             ndp = 0;
  483.         }
  484.         if (c == '.')
  485.             ndp++;
  486.         } else if (c != ' ') {
  487.         /* not in a number now ... */
  488.         if (in) {
  489.             /* ... but we *were* in a number, so it counts */
  490.             comp[ncomp] = atof (bp0);
  491.             set[ncomp] = 1;
  492.             in = 0;
  493.         }
  494.  
  495.         /* regardless, a non-blank non-float means another component */
  496.         ncomp++;
  497.         }
  498.         bp++;
  499.     } while (c);
  500.  
  501.     /* it's a decimal year if there is exactly one component and
  502.      *   it contains a decimal point
  503.      *   or we are in MDY format and it's not in the range 1..12
  504.      *   or we are in DMY format and it's not int the rangle 1..31
  505.      */
  506.     if (ncomp == 1 &&
  507.         (ndp > 0
  508.          || (pref == PREF_MDY && !(comp[0] >= 1 && comp[0] <= 12))
  509.          || (pref == PREF_DMY && !(comp[0] >= 1 && comp[0] <= 31)))) {
  510.         double mjd;
  511.         year_mjd (comp[0], &mjd);
  512.         mjd_cal (mjd, m, d, y);
  513.         return;
  514.     }
  515.  
  516.         switch (pref) {
  517.         case PREF_MDY:
  518.             if (set[0]) *m = comp[0];
  519.             if (set[1]) *d = comp[1];
  520.             if (set[2]) *y = comp[2];
  521.             break;
  522.         case PREF_YMD:
  523.             if (set[0]) *y = comp[0];
  524.             if (set[1]) *m = comp[1];
  525.             if (set[2]) *d = comp[2];
  526.             break;
  527.         case PREF_DMY:
  528.             if (set[0]) *d = comp[0];
  529.             if (set[1]) *m = comp[1];
  530.             if (set[2]) *y = comp[2];
  531.             break;
  532.     }
  533. }
  534.  
  535. /* just like dec_sex() but makes the first non-zero element negative if
  536.  * x is negative (instead of returning a sign flag).
  537.  */
  538. void
  539. f_dec_sexsign (x, h, m, s)
  540. double x;
  541. int *h, *m, *s;
  542. {
  543.     int n;
  544.     dec_sex (x, h, m, s, &n);
  545.     if (n) {
  546.         if (*h)
  547.         *h = -*h;
  548.         else if (*m)
  549.         *m = -*m;
  550.         else
  551.         *s = -*s;
  552.     }
  553. }
  554.