home *** CD-ROM | disk | FTP | other *** search
- /* code to manage the stuff on the moon display.
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #if defined(__STDC__)
- #include <stdlib.h>
- #endif
- #include <X11/Xlib.h>
- #include <Xm/Xm.h>
- #include <Xm/Form.h>
- #include <Xm/Frame.h>
- #include <Xm/DrawingA.h>
- #include <Xm/Label.h>
- #include <Xm/PushB.h>
- #include <Xm/ToggleB.h>
- #include <Xm/Text.h>
- #include "astro.h"
- #include "circum.h"
-
-
- extern Widget toplevel_w;
-
- #if defined(__STDC__) || defined(__cplusplus)
- #define P_(s) s
- #else
- #define P_(s) ()
- #endif
-
- extern Now *mm_get_now P_((void));
- extern Obj *db_basic P_((int id));
- extern void db_update P_((Obj *op));
- extern void get_something P_((Widget w, char *resource, char *value));
- extern void timestamp P_((Now *np, Widget w));
-
- void m_manage P_((void));
- int m_ison P_((void));
- void m_update P_((Now *np, int how_much));
- void m_cursor P_((Cursor c));
- static void m_create_form P_((void));
- static void m_close_cb P_((Widget w, XtPointer client, XtPointer call));
- static void m_mapvw_cb P_((Widget w, XtPointer client, XtPointer call));
- static void m_eshine_cb P_((Widget w, XtPointer client, XtPointer call));
- static void m_da_exp_cb P_((Widget w, XtPointer client, XtPointer call));
- static void m_draw P_((int force));
- static void m_draw_mapview P_((double el));
- static void m_draw_grview P_((double el));
-
- #undef P_
-
- /* get the small moonbit map and its dimension defines.
- * moon is roughly centered within the map, with a radius of some 200 pixels.
- * exact values set by trial and error.
- */
- #include "smallfm.xbm"
- #define MRAD 191 /* radius of moon image */
- #define TOPMAR (smallfm_height/2 - MRAD + 2) /* top margin */
- #define LEFTMAR (smallfm_width/2 - MRAD) /* left margin */
-
- #define NSTARS 300 /* number of fake background stars in graphical view */
-
- static Widget mform_w; /* main moon form dialog */
- static Widget mda_w; /* moon drawring area */
- static Widget eshine_w; /* whether we want to show earthshine */
- static Widget mapvw_w; /* toggle button that selects which view */
- static Widget dt_w; /* date/time stamp widget */
-
- #define MAPVW_W (smallfm_width+20)
- #define MAPVW_H (smallfm_height+40)
-
- /* called when the moon view is activated via the main menu pulldown.
- * if never called before, create and manage all the widgets as a child of a
- * form. otherwise, just toggle whether the form is managed.
- */
- void
- m_manage ()
- {
- if (!mform_w)
- m_create_form();
-
- if (XtIsManaged(mform_w))
- XtUnmanageChild (mform_w);
- else {
- XtManageChild (mform_w);
- /* let the initial expose do the drawing */
- }
- }
-
- m_ison()
- {
- return (mform_w && XtIsManaged(mform_w));
- }
-
- void
- m_update (np, how_much)
- Now *np;
- int how_much;
- {
- if (!mform_w || !XtIsManaged(mform_w))
- return;
-
- m_draw (how_much);
- timestamp (np, dt_w);
- }
-
- /* called to put up or remove the watch cursor. */
- void
- m_cursor (c)
- Cursor c;
- {
- Window win;
-
- if (mform_w && (win = XtWindow(mform_w))) {
- Display *dsp = XtDisplay(mform_w);
- if (c)
- XDefineCursor (dsp, win, c);
- else
- XUndefineCursor (dsp, win);
- }
- }
-
- static void
- m_create_form()
- {
- Widget frame_w;
- Widget f_w, fr_w;
- Widget w;
- XmString str;
- Arg args[20];
- int n;
-
- /* create master form */
- n = 0;
- XtSetArg (args[n], XmNautoUnmanage, False); n++;
- XtSetArg (args[n], XmNhorizontalSpacing, 5); n++;
- XtSetArg (args[n], XmNverticalSpacing, 5); n++;
- XtSetArg (args[n], XmNdefaultPosition, False); n++;
- mform_w = XmCreateFormDialog (toplevel_w, "Moon", args, n);
-
- /* set some stuff in the parent DialogShell.
- * setting XmNdialogTitle in the Form didn't work..
- */
- n = 0;
- XtSetArg (args[n], XmNtitle, "xephem Moon View"); n++;
- XtSetValues (XtParent(mform_w), args, n);
-
- /* make a Form to hold the bottom controls */
-
- n = 0;
- XtSetArg (args[n], XmNfractionBase, 13); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
- f_w = XmCreateForm (mform_w, "MoonCtlForm", args, n);
- XtManageChild (f_w);
-
- /* make the close button */
-
- n = 0;
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNleftPosition, 1); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNrightPosition, 4); n++;
- w = XmCreatePushButton (f_w, "Close", args, n);
- XtAddCallback (w, XmNactivateCallback, m_close_cb, 0);
- XtManageChild (w);
-
- /* make the earthshine toggle button in a frame */
-
- n = 0;
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNleftPosition, 5); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNrightPosition, 8); n++;
- fr_w = XmCreateFrame (f_w, "EarthshineFr", args, n);
- XtManageChild (fr_w);
- eshine_w = XmCreateToggleButton (fr_w, "Earthshine", args, n);
- XtAddCallback (eshine_w, XmNvalueChangedCallback, m_eshine_cb, 0);
- XtManageChild (eshine_w);
-
- /* make the view option toggle button in a frame */
-
- n = 0;
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNleftPosition, 9); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNrightPosition, 12); n++;
- fr_w = XmCreateFrame(f_w,"MMapViewFr", args, n);
- XtManageChild (fr_w);
- str = XmStringCreate("Bitmap View", XmSTRING_DEFAULT_CHARSET);
- n = 0;
- XtSetArg (args[n], XmNlabelString, str); n++;
- mapvw_w = XmCreateToggleButton(fr_w, "BitmapView", args, n);
- XtAddCallback(mapvw_w, XmNvalueChangedCallback, m_mapvw_cb, 0);
- XtManageChild (mapvw_w);
- XmStringFree (str);
-
- /* make a label for the date stamp */
-
- n = 0;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
- XtSetArg (args[n], XmNbottomWidget, f_w); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNrecomputeSize, False); n++;
- dt_w = XmCreateLabel (mform_w, "DateStamp", args, n);
- timestamp (mm_get_now(), dt_w); /* sets initial size */
- XtManageChild (dt_w);
-
- /* make a frame for the drawing area */
-
- n = 0;
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
- XtSetArg (args[n], XmNbottomWidget, dt_w); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
- frame_w = XmCreateFrame (mform_w, "MoonFrame", args, n);
- XtManageChild (frame_w);
-
- /* make a drawing area in the frame for the sky */
- n = 0;
- XtSetArg (args[n], XmNwidth, MAPVW_W); n++;
- XtSetArg (args[n], XmNheight, MAPVW_H); n++;
- XtSetArg (args[n], XmNmarginWidth, 0); n++;
- XtSetArg (args[n], XmNmarginHeight, 0); n++;
- mda_w = XmCreateDrawingArea (frame_w, "MoonDA", args, n);
- XtManageChild (mda_w);
- XtAddCallback (mda_w, XmNexposeCallback, m_da_exp_cb, 0);
- }
-
- /* callback from the Close button.
- */
- /* ARGSUSED */
- static void
- m_close_cb (w, client, call)
- Widget w;
- XtPointer client;
- XtPointer call;
- {
- XtUnmanageChild (mform_w);
- }
-
- /* callback from the Map view toggle button.
- */
- /* ARGSUSED */
- static void
- m_mapvw_cb (w, client, call)
- Widget w;
- XtPointer client;
- XtPointer call;
- {
- m_update (mm_get_now(), 1);
- }
-
- /* callback from the earthshine toggle button.
- */
- /* ARGSUSED */
- static void
- m_eshine_cb (w, client, call)
- Widget w;
- XtPointer client;
- XtPointer call;
- {
- m_update (mm_get_now(), 1);
- }
-
- /* expose (or reconfig) of moon drawing area.
- * just redraw the scene to the current window size.
- */
- /* ARGSUSED */
- static void
- m_da_exp_cb (w, client, call)
- Widget w;
- XtPointer client;
- XtPointer call;
- {
- XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
-
- switch (c->reason) {
- case XmCR_EXPOSE: {
- /* turn off gravity so we get expose events for either shrink or
- * expand.
- */
- static before;
- XExposeEvent *e = &c->event->xexpose;
-
- if (!before) {
- XSetWindowAttributes swa;
- swa.bit_gravity = ForgetGravity;
- XChangeWindowAttributes (e->display, e->window,
- CWBitGravity, &swa);
- before = 1;
- }
- /* wait for the last in the series */
- if (e->count != 0)
- return;
- break;
- }
- default:
- printf ("Unexpected mda_w event. type=%d\n", c->reason);
- exit(1);
- }
-
- m_update (mm_get_now(), 1);
- }
-
- /* draw moon, always if force or scene has changed.
- */
- static void
- m_draw (force)
- int force;
- {
- static double last_el;
- Obj *op;
- double el;
-
- /* get new elongation */
- op = db_basic (MOON);
- db_update (op);
- el = degrad(op->s_elong);
-
- /* don't bother if not forcing and hasn't changed 1 degree */
- if (!force && fabs (el - last_el) < degrad(1.0))
- return;
- last_el = el;
-
- if (XmToggleButtonGetState(mapvw_w)) {
- /* drawing pixmap view so insure a good initial size at least
- */
- Arg args[20];
- int n;
-
- n = 0;
- XtSetArg (args[n], XmNwidth, MAPVW_W); n++;
- XtSetArg (args[n], XmNheight, MAPVW_H); n++;
- XtSetValues (mda_w, args, n);
- XtManageChild (XtParent(eshine_w));
- XtManageChild (eshine_w);
- m_draw_mapview (el);
- } else {
- /* want graphical view */
- XtUnmanageChild (eshine_w);
- XtUnmanageChild (XtParent(eshine_w));
- m_draw_grview (el);
- }
- }
-
- /* version that draws moon using genuine bitmap image. */
- static void
- m_draw_mapview (el)
- double el;
- {
- static GC m_fgc;
- Display *dsp = XtDisplay (mda_w);
- Window win = XtWindow (mda_w);
- double cosel;
- XImage *xim;
- unsigned char *m;
- int y; /* y coord: 0 is center, up is + */
- int earthshine = XmToggleButtonGetState(eshine_w);
-
- if (!m_fgc) {
- /* make gc from MoonDA colors
- */
- XGCValues gcv;
- unsigned int gcm;
-
- gcm = GCForeground | GCBackground;
- get_something (mda_w, XmNforeground, (char *)&gcv.background);
- get_something (mda_w, XmNbackground, (char *)&gcv.foreground);
-
- m_fgc = XCreateGC (dsp, win, gcm, &gcv);
- }
-
- /* make a copy so we can darken some of it */
- m = (unsigned char *)XtMalloc(smallfm_width*smallfm_height/8);
- (void) memcpy (m, smallfm_bits, smallfm_width*smallfm_height/8);
-
- cosel = cos(el);
- for (y = MRAD; y > -MRAD; y--) {
- int lx, rx; /* left and right edge of scan line to darken */
- int r, c; /* X row/col coords */
- lx = -sqrt((double)(MRAD*MRAD - y*y));
- rx = -lx * cosel;
- if (el < 0) {
- int tmp = rx;
- rx = -lx;
- lx = -tmp;
- }
- r = TOPMAR + MRAD - y;
- for (c = LEFTMAR + MRAD + lx; c < LEFTMAR + MRAD + rx; c++)
- if (!earthshine || (c & 3) != 3 || (y & 3) != 3)
- m[r*smallfm_width/8 + c/8] |= (1 << (c%8)); /* 1 is bkgnd */
- }
-
- xim = XCreateImage (dsp, XDefaultVisual (dsp, 0),
- /* depth */ 1,
- /* format */ XYBitmap,
- /* offset */ 0,
- /* data */ (char *)m,
- /* width */ smallfm_width,
- /* height */ smallfm_height,
- /* pad */ 8,
- /* bpl */ 0);
- xim->bitmap_bit_order = LSBFirst;
- xim->byte_order = LSBFirst;
-
- XPutImage (dsp, win, m_fgc, xim, 0, 0, 0, 0,
- smallfm_width, smallfm_height);
- XDestroyImage (xim); /* also frees m */
- }
-
- /* version that draws moon using just simple graphics */
- static void
- m_draw_grview (el)
- double el;
- {
- static GC m_fgc, m_bgc;
- static XPoint *stars;
- static int last_w, last_h;
- Display *dsp = XtDisplay (mda_w);
- Window win = XtWindow (mda_w);
- Window root;
- int x, y;
- unsigned int bw, d;
- unsigned w, h; /* actual size of drawing area window */
- unsigned md; /* moon circle diameter */
- int la1, la2, ta1, ta2; /* limb and terminator start and extent */
- int wid; /* distance from meridian to terminator */
- int xb, yb; /* x and y borders, eg, (w-nx)/2 */
- Pixmap pm;
-
- if (!m_fgc) {
- /* make gcs from MoonDA colors
- */
- XGCValues gcv;
- unsigned int gcm;
-
- gcm = GCForeground | GCBackground;
- get_something (mda_w, XmNforeground, (char *)&gcv.foreground);
- get_something (mda_w, XmNbackground, (char *)&gcv.background);
- m_fgc = XCreateGC (dsp, win, gcm, &gcv);
-
- get_something (mda_w, XmNbackground, (char *)&gcv.foreground);
- get_something (mda_w, XmNforeground, (char *)&gcv.background);
- m_bgc = XCreateGC (dsp, win, gcm, &gcv);
- }
-
-
- /* get size of window now and make a fresh pixmap to match.
- * we draw the scene in the pixmap then copy it to the window.
- * otherwise, you can see it drawing and it flashes and looks ugly.
- */
- XGetGeometry (dsp, win, &root, &x, &y, &w, &h, &bw, &d);
- pm = XCreatePixmap (dsp, win, w, h, d);
- XFillRectangle (dsp, pm, m_bgc, 0, 0, w, h);
-
- /* set moon diameter so it is centered within the bounding rectangle
- * of the window.
- * this code sets it to match the borders of the map view and makes
- * the diameter even so it divides evenly.
- */
- md = ((w > h) ? MRAD*h/(MRAD+TOPMAR) : MRAD*w/(MRAD+LEFTMAR)) & (~1);
- xb = (w - md)/2;
- yb = (h - md)/2;
-
- la1 = el >= 0.0 ? -90*64 : 90*64;
- la2 = 180*64;
- wid = fabs(md/2*cos(el))+0.5;
- ta1 = el >= PI/2 || (el <= 0 && el >= -PI/2) ? 90*64 : -90*64;
- ta2 = 180*64;
-
- /* dsp, win, gc, x, y, w, h, start_ang, ang_extent */
- /* draw the lit hemisphere to the limb */
- XFillArc (dsp, pm, m_fgc, xb, yb, md, md, la1, la2);
-
- /* draw the portion from the terminator to the meridian */
- if (la1 < 0 && ta1 < 0 || la1 > 0 && ta1 > 0) {
- /* crescent, so draw in background color */
- XFillArc (dsp, pm, m_bgc, md/2-wid+xb, yb, 2*wid, md, ta1, ta2);
- } else {
- /* gibbous, so draw in foreground color */
- XFillArc (dsp, pm, m_fgc, md/2-wid+xb, yb, 2*wid, md, ta1, ta2);
- }
-
- /* add in the background stars */
- if (!stars || last_w != w || last_h != h) {
- /* sprinkle NSTARS stars outside the moon's circle of radius r.
- */
- double rr = 0.25*md*md; /* = (md/2)*(md/2); */
- int i;
- if (stars)
- XtFree ((char *)stars);
- stars = (XPoint *) XtMalloc (NSTARS * sizeof(XPoint));
- for (i = 0; i < NSTARS; ) {
- x = ((rand() >> 2) & 0xfff) * (w-1) / 0xfff;
- y = ((rand() >> 2) & 0xfff) * (h-1) / 0xfff;
- /* compare the candidate y with the y on the ellipse at the
- * candidate x to decide whether to draw the point.
- */
- #define SQR(x) ((x)*(x))
- if (SQR(y-h/2) > rr - SQR(x-w/2)) {
- stars[i].x = (short)x;
- stars[i].y = (short)y;
- i++;
- }
- }
- }
- XDrawPoints (dsp, pm, m_fgc, stars, NSTARS, CoordModeOrigin);
-
- XCopyArea (dsp, pm, win, m_fgc, 0, 0, w, h, 0, 0);
- XFreePixmap (dsp, pm);
-
- last_w = w;
- last_h = h;
- }
-