home *** CD-ROM | disk | FTP | other *** search
- /* all the screen oriented printing should go through here.
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <ctype.h>
- #if defined(__STDC__)
- #include <stdlib.h>
- #endif
- #include <X11/Xlib.h>
- #include <Xm/Xm.h>
- #include "astro.h"
- #include "preferences.h"
-
- #if defined(__STDC__) || defined(__cplusplus)
- #define P_(s) s
- #else
- #define P_(s) ()
- #endif
-
- extern void dec_sex P_((double d, int *hd, int *m, int *s, int *isneg));
- extern void f_dec_sexsign P_((double x, int *h, int *m, int *s));
- extern void field_log P_((Widget w, double value, int logv, char *str));
- extern void get_xmstring P_((Widget w, char *resource, char **txtp));
- extern void mjd_cal P_((double Mjd, int *mn, double *dy, int *yr));
- extern void mjd_year P_((double Mjd, double *yr));
- extern void set_xmstring P_((Widget w, char *resource, char *txt));
- extern void year_mjd P_((double y, double *Mjd));
-
- void f_on P_((void));
- void f_off P_((void));
- int f_ison P_((void));
- void f_showit P_((Widget w, char *s));
- void f_sexad P_((Widget w, int a, int p, int mod, double v));
- void fs_sexad P_((char out[], int a, int p, int mod, double v));
- void f_sexag P_((Widget w, int nd, double t));
- void fs_sexag P_((char out[], int nd, double t));
- void f_ra P_((Widget w, double ra));
- void fs_ra P_((char out[], double ra));
- void f_time P_((Widget w, double t));
- void fs_time P_((char out[], double t));
- void f_signtime P_((Widget w, double t));
- void fs_signtime P_((char out[], double t));
- void f_mtime P_((Widget w, double t));
- void fs_mtime P_((char out[], double t));
- void f_angle P_((Widget w, double a));
- void fs_angle P_((char out[], double a));
- void f_gangle P_((Widget w, double a));
- void fs_gangle P_((char out[], double a));
- void f_date P_((Widget w, double jd));
- void fs_date P_((char out[], double jd));
- void f_string P_((Widget w, char *s));
- void f_double P_((Widget w, char *fmt, double f));
- void f_sscansex P_((char *bp, int *d, int *m, int *s));
- void f_sscandate P_((char *bp, int pref, int *m, double *d, int *y));
- void f_dec_sexsign P_((double x, int *h, int *m, int *s));
-
- #undef P_
-
- extern Widget toplevel_w;
-
- /* suppress screen io if this is true, but always log stuff.
- */
- static int f_scrnoff;
- void
- f_on ()
- {
- f_scrnoff = 0;
- }
- void
- f_off ()
- {
- f_scrnoff = 1;
- }
- f_ison()
- {
- return (!f_scrnoff);
- }
-
- /* set the given widget's XmNlabelString to s if it's not already the same
- * and we are indeed displaying stuff at the moment.
- */
- void
- f_showit (w, s)
- Widget w;
- char *s;
- {
- char *txtp;
-
- if (f_scrnoff)
- return;
- get_xmstring (w, XmNlabelString, &txtp);
- if (strcmp (txtp, s))
- set_xmstring (w, XmNlabelString, s);
- XtFree (txtp);
- }
-
- /* print the given value, v, in "sexadecimal" format to widget w.
- */
- void
- f_sexad (w, a, p, mod, v)
- Widget w;
- int a, p; /* left space, min precision */
- int mod; /* don't let whole portion get this big */
- double v;
- {
- char out[32];
-
- fs_sexad (out, a, p, mod, v);
- field_log (w, v, 1, out);
- f_showit (w, out);
- }
-
- /* print the given value, v, in "sexadecimal" format into string out.
- * ie, in the form A:m.P, where A is a digits wide, P is p digits.
- * if p == 0, then no decimal point either.
- */
- void
- fs_sexad (out, a, p, mod, v)
- char out[];
- int a, p; /* left space, min precision */
- int mod; /* don't let whole portion get this big */
- double v;
- {
- char str[32];
- long dec;
- double frac;
- int visneg;
-
- if (v >= 0.0)
- visneg = 0;
- else {
- if (v <= -0.5/60.0*pow(10.0,-1.0*p)) {
- v = -v;
- visneg = 1;
- } else {
- /* don't show as negative if less than the precision showing */
- v = 0.0;
- visneg = 0;
- }
- }
-
- dec = v;
- frac = (v - dec)*60.0;
- (void) sprintf (str, "59.%.*s5", p, "999999999");
- if (frac >= atof (str)) {
- dec += 1;
- frac = 0.0;
- }
- dec %= mod;
- if (dec == 0 && visneg)
- (void) strcpy (str, "-0");
- else
- (void) sprintf (str, "%ld", visneg ? -dec : dec);
-
- /* would just do this if Turbo-C 2.0 %?.0f" worked:
- * sprintf (astr, "%*s:%0*.*f", a, str, p == 0 ? 2 : p+3, p, frac);
- */
- if (p == 0)
- (void) sprintf (out, "%*s:%02d", a, str, (int)(frac+0.5));
- else
- (void) sprintf (out, "%*s:%0*.*f", a, str, p+3, p, frac);
- }
-
- /* print the given value, t, in sexagesimal format to widget w. */
- void
- f_sexag (w, nd, t)
- Widget w;
- int nd;
- double t;
- {
- char out[32];
-
- fs_sexag (out, nd, t);
- field_log (w, t, 1, out);
- f_showit (w, out);
- }
-
- /* print the given value, t, in sexagesimal format to string out[].
- * ie, in the form T:mm:ss, where T is nd digits wide.
- * N.B. we assume nd >= 2.
- */
- void
- fs_sexag (out, nd, t)
- char out[];
- int nd;
- double t;
- {
- int h, m, s;
- int tisneg;
-
- dec_sex (t, &h, &m, &s, &tisneg);
- if (h == 0 && tisneg)
- (void) sprintf (out, "%*s-0:%02d:%02d", nd-2, "", m, s);
- else
- (void) sprintf (out, "%*d:%02d:%02d", nd, tisneg ? -h : h, m, s);
- }
-
- /* print angle ra, in radians, in ra hours as hh:mm.m to widget w */
- void
- f_ra (w, ra)
- Widget w;
- double ra;
- {
- f_sexad (w, 2, 1, 24, radhr(ra));
- }
-
- /* print angle ra, in radians, in ra hours as hh:mm.m into string out[].
- * N.B. we assume ra is >= 0.
- */
- void
- fs_ra (out, ra)
- char out[];
- double ra;
- {
- fs_sexad (out, 2, 1, 24, radhr(ra));
- }
-
- /* print time, t, as hh:mm:ss */
- void
- f_time (w, t)
- Widget w;
- double t;
- {
- f_sexag (w, 2, t);
- }
-
- /* print time, t, as hh:mm:ss */
- void
- fs_time (out, t)
- char out[];
- double t;
- {
- fs_sexag (out, 2, t);
- }
-
- /* print time, t, as +/-hh:mm:ss (don't show leading +) */
- void
- f_signtime (w, t)
- Widget w;
- double t;
- {
- f_sexag (w, 3, t);
- }
-
- /* print time, t, as +/-hh:mm:ss (don't show leading +) */
- void
- fs_signtime (out, t)
- char out[];
- double t;
- {
- fs_sexag (out, 3, t);
- }
-
- /* print time, t, as hh:mm */
- void
- f_mtime (w, t)
- Widget w;
- double t;
- {
- f_sexad (w, 2, 0, 24, t);
- }
-
- /* print time, t, as hh:mm */
- void
- fs_mtime (out, t)
- char out[];
- double t;
- {
- fs_sexad (out, 2, 0, 24, t);
- }
-
- /* print angle, a, in rads, as degrees to widget w in form ddd:mm */
- void
- f_angle(w, a)
- Widget w;
- double a;
- {
- f_sexad (w, 3, 0, 360, raddeg(a));
- }
-
- /* print angle, a, in rads, as degrees into string out[] in form ddd:mm */
- void
- fs_angle(out, a)
- char out[];
- double a;
- {
- fs_sexad (out, 3, 0, 360, raddeg(a));
- }
-
- /* print angle, a, in rads, as degrees to widget w in form dddd:mm:ss */
- void
- f_gangle(w, a)
- Widget w;
- double a;
- {
- f_sexag (w, 4, raddeg(a));
- }
-
- /* print angle, a, in rads, as degrees into string out[] in form dddd:mm:ss */
- void
- fs_gangle(out, a)
- char out[];
- double a;
- {
- fs_sexag (out, 4, raddeg(a));
- }
-
- /* print the given modified Julian date, jd, in the preferred format.
- */
- void
- f_date (w, jd)
- Widget w;
- double jd;
- {
- char out[32];
- double tmp;
-
- fs_date (out, jd);
-
- /* shadow to the plot subsystem as years. */
- mjd_year (jd, &tmp);
- field_log (w, tmp, 1, out);
- f_showit (w, out);
- }
-
- /* put the given modified Julian date, jd, in out[] according to preference
- * format.
- */
- void
- fs_date (out, jd)
- char out[];
- double jd;
- {
- int p = pref_get (PREF_DATE_FORMAT);
- int m, y;
- double d;
-
- mjd_cal (jd, &m, &d, &y);
- switch (p) {
- case PREF_YMD:
- (void) sprintf (out, "%4d/%02d/%02d", y, m, (int)d);
- break;
- case PREF_DMY:
- (void) sprintf (out, "%2d/%02d/%-4d", (int)d, m, y);
- break;
- case PREF_MDY:
- (void) sprintf (out, "%2d/%02d/%-4d", m, (int)d, y);
- break;
- default:
- printf ("fs_date: bad date pref: %d\n", p);
- exit (1);
- }
- }
-
- /* set w's XmNlabelString to s if it's not already the same and we are
- * showing fields now.
- * also, log the string if w is being used for logging now.
- * N.B. do not use this for any widget that has its XmNuserData anything but
- * the default (NULL) or a valid field id string; ie. use only for widgets
- * that are buttons that can be "logged" for plotting etc. In all other cases
- * use f_showit() directly.
- */
- void
- f_string (w, s)
- Widget w;
- char *s;
- {
- field_log (w, 0.0, 0, s);
- f_showit (w, s);
- }
-
- void
- f_double (w, fmt, f)
- Widget w;
- char *fmt;
- double f;
- {
- char str[80];
- (void) sprintf (str, fmt, f);
- field_log (w, f, 1, str);
- f_showit (w, str);
- }
-
- /* crack a line of the form X?X?X into its components,
- * where X is an integer and ? can be any character except '0-9' or '-',
- * such as ':' or '/'.
- * only change those fields that are specified:
- * eg: ::10 only changes *s
- * 10 only changes *d
- * 10:0 changes *d and *m
- * if see '-' anywhere, first non-zero component will be made negative.
- * TODO: s should be a double *.
- */
- void
- f_sscansex (bp, d, m, s)
- char *bp;
- int *d, *m, *s;
- {
- char c;
- int *p = d;
- int *nonzp = 0;
- int sawneg = 0;
- int innum = 0;
-
- while (c = *bp++)
- if (isdigit(c)) {
- if (!innum) {
- *p = 0;
- innum = 1;
- }
- *p = *p*10 + (c - '0');
- if (*p && !nonzp)
- nonzp = p;
- } else if (c == '-') {
- sawneg = 1;
- } else if (p == s && c == '.') {
- c = *bp++;
- if (isdigit(c) && c >= '5') {
- /* round up if see at least .5 */
- if (++(*s) == 60) {
- if (++(*m) == 60) {
- ++(*d);
- *m = 0;
- }
- *s = 0;
- }
- }
- break;
- } else if (c != ' ') {
- /* advance to next component */
- p = (p == d) ? m : s;
- innum = 0;
- }
-
- if (sawneg && nonzp)
- *nonzp = -*nonzp;
- }
-
- /* crack a floating date string, bp, of the form X/Y/Z determined by the
- * PREF_DATE_FORMAT preference into its components. allow the day to be a
- * floating point number,
- * a lone component is always a year if it contains a decimal point or pref
- * is MDY or DMY and it is not a reasonable month or day value, respectively.
- * leave any component unspecified unchanged.
- * actually, the slashes may be anything but digits or a decimal point.
- * this is functionally the same as f_sscansex() exept we allow for
- * the day portion to be real, and we don't handle negative numbers.
- * maybe someday we could make a combined one and use it everywhere.
- */
- void
- f_sscandate (bp, pref, m, d, y)
- char *bp;
- int pref; /* one of PREF_X for PREF_DATE_FORMAT */
- int *m, *y;
- double *d;
- {
- char *bp0, c;
- double comp[3]; /* the three components */
- int set[3]; /* set[i] is 1 if component i is present */
- int in; /* scan state: 1 while we are in a component */
- int ncomp; /* incremented as each component is discovered */
- int ndp; /* number of decimal points in last component */
-
- set[0] = set[1] = set[2] = 0;
- ncomp = 0;
- in = 0;
- ndp = 0;
-
- /* scan the input string.
- * '\0' counts as a component terminator too.
- */
- do {
- /* here, bp is the next character to be investigated */
- c = *bp;
- if (c == '.' || isdigit(c) || (c == '-' && !in)) {
- /* found what passes for a floating point number */
- if (in == 0) {
- /* save the beginning of it in bp0 and init ndp */
- bp0 = bp;
- in = 1;
- ndp = 0;
- }
- if (c == '.')
- ndp++;
- } else if (c != ' ') {
- /* not in a number now ... */
- if (in) {
- /* ... but we *were* in a number, so it counts */
- comp[ncomp] = atof (bp0);
- set[ncomp] = 1;
- in = 0;
- }
-
- /* regardless, a non-blank non-float means another component */
- ncomp++;
- }
- bp++;
- } while (c);
-
- /* it's a decimal year if there is exactly one component and
- * it contains a decimal point
- * or we are in MDY format and it's not in the range 1..12
- * or we are in DMY format and it's not int the rangle 1..31
- */
- if (ncomp == 1 &&
- (ndp > 0
- || (pref == PREF_MDY && !(comp[0] >= 1 && comp[0] <= 12))
- || (pref == PREF_DMY && !(comp[0] >= 1 && comp[0] <= 31)))) {
- double mjd;
- year_mjd (comp[0], &mjd);
- mjd_cal (mjd, m, d, y);
- return;
- }
-
- switch (pref) {
- case PREF_MDY:
- if (set[0]) *m = comp[0];
- if (set[1]) *d = comp[1];
- if (set[2]) *y = comp[2];
- break;
- case PREF_YMD:
- if (set[0]) *y = comp[0];
- if (set[1]) *m = comp[1];
- if (set[2]) *d = comp[2];
- break;
- case PREF_DMY:
- if (set[0]) *d = comp[0];
- if (set[1]) *m = comp[1];
- if (set[2]) *y = comp[2];
- break;
- }
- }
-
- /* just like dec_sex() but makes the first non-zero element negative if
- * x is negative (instead of returning a sign flag).
- */
- void
- f_dec_sexsign (x, h, m, s)
- double x;
- int *h, *m, *s;
- {
- int n;
- dec_sex (x, h, m, s, &n);
- if (n) {
- if (*h)
- *h = -*h;
- else if (*m)
- *m = -*m;
- else
- *s = -*s;
- }
- }
-