home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part17 / skyviewmenu.c.2 < prev   
Encoding:
Text File  |  1993-05-15  |  25.5 KB  |  1,001 lines

  1.     XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
  2.     XtSetArg (args[n], XmNscaleMultiple, 1); n++;
  3.     XtSetArg (args[n], XmNshowValue, True); n++;
  4.     azra_w = XmCreateScale (svform_w, "AzRAScale", args, n);
  5.     XtAddCallback (azra_w, XmNvalueChangedCallback, sv_changed_cb, NULL);
  6.     XtManageChild (azra_w);
  7.  
  8.     /* make the left scale */
  9.  
  10.     str = XmStringCreate ("FOV", XmSTRING_DEFAULT_CHARSET);
  11.     n = 0;
  12.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  13.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  14.     XtSetArg (args[n], XmNleftWidget, sep_w); n++;
  15.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  16.     XtSetArg (args[n], XmNbottomWidget, azra_w); n++;
  17.     XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
  18.     XtSetArg (args[n], XmNminimum, 1); n++;
  19.     XtSetArg (args[n], XmNmaximum, 180); n++;
  20.     XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_BOTTOM); n++;
  21.     XtSetArg (args[n], XmNscaleMultiple, 1); n++;
  22.     XtSetArg (args[n], XmNshowValue, True); n++;
  23.     XtSetArg (args[n], XmNtitleString, str); n++;
  24.     fov_w = XmCreateScale (svform_w, "FOVScale", args, n);
  25.     XtAddCallback (fov_w, XmNvalueChangedCallback, sv_changed_cb, NULL);
  26.     XtManageChild (fov_w);
  27.     XmStringFree (str);
  28.  
  29.     /* make the right scale */
  30.  
  31.     n = 0;
  32.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  33.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  34.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  35.     XtSetArg (args[n], XmNbottomWidget, azra_w); n++;
  36.     XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
  37.     XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
  38.     XtSetArg (args[n], XmNscaleMultiple, 1); n++;
  39.     XtSetArg (args[n], XmNshowValue, True); n++;
  40.     altdec_w = XmCreateScale (svform_w, "AltDecScale", args, n);
  41.     XtAddCallback (altdec_w, XmNvalueChangedCallback, sv_changed_cb, NULL);
  42.     XtManageChild (altdec_w);
  43.  
  44.     /* make ra/dec tracking labels just above the bottom scale on either
  45.      * side.
  46.      */
  47.  
  48.     n = 0;
  49.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  50.     XtSetArg (args[n], XmNleftWidget, fov_w); n++;
  51.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  52.     XtSetArg (args[n], XmNbottomWidget, azra_w); n++;
  53.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  54.     tra_w = XmCreateLabel (svform_w, "TRA", args, n);
  55.     set_xmstring (tra_w, XmNlabelString, " ");
  56.     XtManageChild(tra_w);
  57.  
  58.     n = 0;
  59.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  60.     XtSetArg (args[n], XmNrightWidget, altdec_w); n++;
  61.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  62.     XtSetArg (args[n], XmNbottomWidget, azra_w); n++;
  63.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  64.     tdec_w = XmCreateLabel (svform_w, "TDec", args, n);
  65.     set_xmstring (tdec_w, XmNlabelString, " ");
  66.     XtManageChild(tdec_w);
  67.  
  68.     /* make alt/az tracking labels on top on either side */
  69.  
  70.     n = 0;
  71.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  72.     XtSetArg (args[n], XmNleftWidget, fov_w); n++;
  73.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  74.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  75.     talt_w = XmCreateLabel (svform_w, "TAlt", args, n);
  76.     set_xmstring (talt_w, XmNlabelString, " ");
  77.     XtManageChild(talt_w);
  78.  
  79.     n = 0;
  80.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  81.     XtSetArg (args[n], XmNrightWidget, altdec_w); n++;
  82.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  83.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  84.     taz_w = XmCreateLabel (svform_w, "TAz", args, n);
  85.     set_xmstring (taz_w, XmNlabelString, " ");
  86.     XtManageChild(taz_w);
  87.  
  88.     /* make a drawing area inside the sliders for drawing the sky */
  89.  
  90.     n = 0;
  91.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  92.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  93.     XtSetArg (args[n], XmNbottomWidget, azra_w); n++;
  94.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  95.     XtSetArg (args[n], XmNleftWidget, fov_w); n++;
  96.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  97.     XtSetArg (args[n], XmNrightWidget, altdec_w); n++;
  98.     svda_w = XmCreateDrawingArea (svform_w, "Map", args, n);
  99.     XtAddCallback (svda_w, XmNexposeCallback, sv_da_exp_cb, 0);
  100.     XtAddCallback (svda_w, XmNinputCallback, sv_da_input_cb, 0);
  101.     mask = Button1MotionMask | ButtonPressMask | ButtonReleaseMask
  102.                            | PointerMotionHintMask,
  103.     XtAddEventHandler (svda_w, mask, False, sv_da_motion_cb,0);
  104.     XtManageChild (svda_w);
  105.  
  106.     /* create the filter dialog.
  107.      * it's not managed yet, but its state info is used right off.
  108.      */
  109.     svf_create();
  110.  
  111.     /* create the popup */
  112.     sv_create_popup();
  113.  
  114.     sv_set_view();
  115.     sv_set_scales();
  116. }
  117.  
  118. static void
  119. sv_create_find (parent)
  120. Widget parent;
  121. {
  122.     Arg args[20];
  123.     Widget mb_w, menu_w, p_w;
  124.     Widget w;
  125.     int n;
  126.     int i;
  127.  
  128.     /* create menu bar for the cascade button */
  129.  
  130.     n = 0;
  131.     XtSetArg (args[n], XmNrowColumnType, XmMENU_BAR); n++;
  132.     mb_w = XmCreateRowColumn (parent, "PointMB", args, n);
  133.     XtManageChild (mb_w);
  134.  
  135.     /* create pulldown managed by the cascade button */
  136.     n = 0;
  137.     menu_w = XmCreatePulldownMenu (parent, "PointPD", args, n);
  138.  
  139.         /* create the pushbuttons forming the cascade menu.
  140.          * go ahead and fill in and manage the planet names now.
  141.          * we do the user objects just as we are cascading.
  142.          */
  143.         for (i = 0; i < NOBJ; i++) {
  144.         n = 0;
  145.         w = XmCreatePushButton (menu_w, "PointPB", args, n);
  146.         XtAddCallback (w, XmNactivateCallback, sv_find_cb,
  147.                                 (XtPointer)i);
  148.         if (i >= MERCURY && i <= MOON) {
  149.             Obj *op = db_basic (i);
  150.             set_xmstring (w, XmNlabelString, op->o_name);
  151.             XtManageChild (w);
  152.         } else if (i == OBJX)
  153.             find_w[0] = w;
  154.         else if (i == OBJY)
  155.             find_w[1] = w;
  156.         }
  157.  
  158.     n = 0;
  159.     XtSetArg (args[n], XmNsubMenuId, menu_w); n++;
  160.     XtSetArg (args[n], XmNmarginHeight, 0); n++;
  161.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_CENTER); n++;
  162.     p_w = XmCreateCascadeButton (mb_w, "PointCB", args, n);
  163.     set_xmstring (p_w, XmNlabelString, "Locate...");
  164.     XtAddCallback (p_w, XmNcascadingCallback, sv_finding_cb, 0);
  165.     XtManageChild (p_w);
  166. }
  167.  
  168. /* callback from the main Close button.
  169.  */
  170. /* ARGSUSED */
  171. static void
  172. sv_close_cb (w, client, call)
  173. Widget w;
  174. XtPointer client;
  175. XtPointer call;
  176. {
  177.     XtUnmanageChild (svform_w);
  178.     svf_unmanage ();
  179.     if (sv_pm) {
  180.         XFreePixmap (XtDisplay(svda_w), sv_pm);
  181.         sv_pm = (Pixmap) NULL;
  182.     }
  183. }
  184.  
  185. /* callback from the Help button.
  186.  */
  187. /* ARGSUSED */
  188. static void
  189. sv_help_cb (w, client, call)
  190. Widget w;
  191. XtPointer client;
  192. XtPointer call;
  193. {
  194.     static char *msg[] = {
  195. "This displays all database objects currently in memory onto the sky. The view",
  196. "may be Alt/Az or RA/Dec. The three sliders adjust the field of fov, the",
  197. "azimuth (or RA), and the altitude (or Dec). Objects may be filtered out by",
  198. "type and magnitude."
  199. };
  200.  
  201.     hlp_dialog ("Sky View", msg, sizeof(msg)/sizeof(msg[0]));
  202. }
  203.  
  204. /* callback when the alt/az button changes state.
  205.  */
  206. /* ARGSUSED */
  207. static void
  208. sv_aa_cb (w, client, call)
  209. Widget w;
  210. XtPointer client;
  211. XtPointer call;
  212. {
  213.     double lst;
  214.     Now *np;
  215.  
  216.     np = mm_get_now();
  217.     now_lst (np, &lst);
  218.  
  219.     if (aa_mode) {
  220.         /* change from alt/az to ra/dec mode */
  221.         double ha;
  222.         unrefract (pressure, temp, sv_altdec, &sv_altdec);
  223.         aa_hadec (lat, sv_altdec, sv_azra, &ha, &sv_altdec);
  224.         sv_azra = hrrad(lst) - ha;
  225.         range (&sv_azra, 2*PI);
  226.         if (epoch != EOD)
  227.         precess (mjd, epoch, &sv_azra, &sv_altdec);
  228.     } else {
  229.         /* change from ra/dec to alt/az mode if center is above horizon */
  230.         double ha, ra, dec, alt, az;
  231.         ra = sv_azra;
  232.         dec = sv_altdec;
  233.         if (epoch != EOD)
  234.         precess (epoch, mjd, &ra, &dec);
  235.         ha = hrrad(lst) - ra;
  236.         range (&ha, 2*PI);
  237.         hadec_aa (lat, ha, dec, &alt, &az);
  238.         refract (pressure, temp, alt, &alt);
  239.         if (alt < 0.0) {
  240.         xe_msg ("Center would be below horizon.", 1);
  241.         XmToggleButtonSetState (aa_w, False, False);
  242.         XmToggleButtonSetState (rad_w, True, False);
  243.         return;
  244.         }
  245.         sv_altdec = alt;
  246.         sv_azra = az;
  247.     }
  248.  
  249.     aa_mode ^= 1;
  250.     sv_set_scales();
  251.     sv_all(np, 1);
  252. }
  253.  
  254. /* callback from the filter button.
  255.  * just toggle the filter dialog.
  256.  * always restore it to the real state before bringing it up.
  257.  */
  258. /* ARGSUSED */
  259. static void
  260. sv_filter_cb (w, client, call)
  261. Widget w;
  262. XtPointer client;
  263. XtPointer call;
  264. {
  265.     svf_manage_toggle ();
  266. }
  267.  
  268. /* callback from the grid button.
  269.  * if adding the grid just draw it, but if taking it away copy from pixmap.
  270.  */
  271. /* ARGSUSED */
  272. static void
  273. sv_grid_cb (w, client, call)
  274. Widget w;
  275. XtPointer client;
  276. XtPointer call;
  277. {
  278.     want_grid = XmToggleButtonGetState(w);
  279.  
  280.     sv_all(mm_get_now(), 1);
  281.  
  282.     if (!want_grid) {
  283.         set_xmstring (vgrid_w, XmNlabelString, null_grid_str);
  284.         set_xmstring (hgrid_w, XmNlabelString, null_grid_str);
  285.     }
  286. }
  287.  
  288. /* set the altdec_w and azra_w scale values, depending on aa_mode and sv_altdec
  289.  * and sv_azra.
  290.  */
  291. static void
  292. sv_set_scales()
  293. {
  294.     Arg args[20];
  295.     int n;
  296.  
  297.     if (aa_mode) {
  298.         int altitude, azimuth;
  299.  
  300.         altitude = raddeg(sv_altdec) + 0.5;
  301.         azimuth = raddeg(sv_azra) + 0.5;
  302.         if (azimuth >= 360) azimuth -= 360;
  303.         if (azimuth < 0) azimuth += 360;
  304.  
  305.         n = 0;
  306.         XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_RIGHT); n++;
  307.         XtSetArg (args[n], XmNmaximum, 359); n++;
  308.         XtSetArg (args[n], XmNminimum, 0); n++;
  309.         XtSetArg (args[n], XmNdecimalPoints, 0); n++;
  310.         XtSetArg (args[n], XmNvalue, azimuth); n++;
  311.         XtSetValues (azra_w, args, n);
  312.  
  313.         n = 0;
  314.         XtSetArg (args[n], XmNmaximum, 90); n++;
  315.         XtSetArg (args[n], XmNminimum, 0); n++;
  316.         XtSetArg (args[n], XmNvalue, altitude); n++;
  317.         XtSetValues (altdec_w, args, n);
  318.  
  319.     } else {
  320.         int ra, dec;
  321.  
  322.         ra = radhr(sv_azra)*10.0 + 0.5;
  323.         if (ra >= 240) ra -= 240;
  324.         dec = raddeg(sv_altdec) + (sv_altdec >= 0 ? 0.5 : -0.5);
  325.  
  326.         n = 0;
  327.         XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_LEFT); n++;
  328.         XtSetArg (args[n], XmNmaximum, 239); n++;
  329.         XtSetArg (args[n], XmNminimum, 0); n++;
  330.         XtSetArg (args[n], XmNdecimalPoints, 1); n++;
  331.         XtSetArg (args[n], XmNvalue, ra); n++;
  332.         XtSetValues (azra_w, args, n);
  333.  
  334.         n = 0;
  335.         XtSetArg (args[n], XmNmaximum, 90); n++;
  336.         XtSetArg (args[n], XmNminimum, -90); n++;
  337.         XtSetArg (args[n], XmNvalue, dec); n++;
  338.         XtSetValues (altdec_w, args, n);
  339.     }
  340. }
  341.  
  342. /* expose event of sky view drawing area.
  343.  * if same size just copy from pixmap, else recompute all (it's resized).
  344.  * N.B. we set bit_gravity to ForgetGravity so we can just use Expose events.
  345.  * N.B. we turn off backing store since we effectively do it in the pixmap.
  346.  */
  347. /* ARGSUSED */
  348. static void
  349. sv_da_exp_cb (w, client, call)
  350. Widget w;
  351. XtPointer client;
  352. XtPointer call;
  353. {
  354.     static unsigned int wid_last, hei_last;
  355.     XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
  356.     Display *dsp = XtDisplay(w);
  357.     Window win = XtWindow(w);
  358.     Window root;
  359.     int x, y;
  360.     unsigned int bw, d;
  361.     unsigned wid, hei;
  362.  
  363.  
  364.     switch (c->reason) {
  365.     case XmCR_EXPOSE: {
  366.         static before;
  367.         XExposeEvent *e = &c->event->xexpose;
  368.         if (!before) {
  369.         XSetWindowAttributes swa;
  370.         unsigned long mask = CWBitGravity | CWBackingStore;
  371.         swa.bit_gravity = ForgetGravity;
  372.         swa.backing_store = NotUseful;
  373.         XChangeWindowAttributes (e->display, e->window, mask, &swa);
  374.         before = 1;
  375.         }
  376.         /* wait for the last in the series */
  377.         if (e->count != 0)
  378.         return;
  379.         break;
  380.         }
  381.     default:
  382.         printf ("Unexpected svda_w event. type=%d\n", c->reason);
  383.         exit(1);
  384.     }
  385.  
  386.     XGetGeometry (dsp, win, &root, &x, &y, &wid, &hei, &bw, &d);
  387.  
  388.     if (!sv_pm || wid != wid_last || hei != hei_last) {
  389.         if (sv_pm)
  390.         XFreePixmap (dsp, sv_pm);
  391.  
  392.         if (!sv_gc)
  393.         sv_mk_gcs(dsp, win);
  394.  
  395.         sv_pm = XCreatePixmap (dsp, win, wid, hei, d);
  396.         wid_last = wid;
  397.         hei_last = hei;
  398.  
  399.         sv_all(mm_get_now(), 1);
  400.     } else {
  401.         /* same size; just copy from the pixmap */
  402.         sv_copy_sky();
  403.     }
  404. }
  405.  
  406. /* copy the pixmap to the drawing area
  407.  */
  408. static void
  409. sv_copy_sky()
  410. {
  411.     Display *dsp = XtDisplay (svda_w);
  412.     Window win = XtWindow (svda_w);
  413.     unsigned wid, hei;    /* overall width and height */
  414.     unsigned int r;        /* circle radius */
  415.     unsigned int xb, yb;    /* x and y border */
  416.  
  417.     sv_getcircle (&wid, &hei, &r, &xb, &yb);
  418.  
  419.     XCopyArea (dsp, sv_pm, win, sv_gc, 0, 0, wid, hei, 0, 0);
  420. }
  421.  
  422. /* called on receipt of a MotionNotify or ButtonPress or ButtonRelease event
  423.  *   while the cursor is wandering over the sky view and button 1 is down.
  424.  * we report the current location in world coordinates.
  425.  */
  426. /* ARGSUSED */
  427. static void
  428. sv_da_motion_cb (w, client, ev, continue_to_dispatch)
  429. Widget w;
  430. XtPointer client;
  431. XEvent *ev;
  432. Boolean *continue_to_dispatch;
  433. {
  434.     Now *np = mm_get_now();
  435.     unsigned int wide, h, r, xb, yb;
  436.     double altdec, azra;
  437.     Window root, child;
  438.     int rx, ry, wx, wy;
  439.     unsigned mask;
  440.     char alt_buf[64], az_buf[64];
  441.     char ra_buf[64], dec_buf[64];
  442.     int evt = ev->type;
  443.     int okmotion, okbutton;
  444.     double lst;
  445.  
  446.     /* only interested if motion event or button 1 press/release */
  447.     okmotion = evt == MotionNotify && ev->xmotion.state == Button1Mask;
  448.     okbutton = (evt == ButtonPress || evt == ButtonRelease)
  449.                     && ev->xbutton.button == Button1;
  450.     if (!okmotion && !okbutton)
  451.         return;
  452.  
  453.     now_lst (np, &lst);
  454.  
  455.     XQueryPointer (XtDisplay(w), XtWindow(w),
  456.                 &root, &child, &rx, &ry, &wx, &wy, &mask);
  457.  
  458.     sv_getcircle (&wide, &h, &r, &xb, &yb);
  459.  
  460.     if (evt != ButtonRelease && sv_unloc (r, wx-xb, wy-yb, &altdec, &azra)){
  461.         double ha, ra, dec, alt, az;
  462.  
  463.         if (aa_mode) {
  464.         /* need to make the ra/dec entries */
  465.         alt = altdec;
  466.         az = azra;
  467.         unrefract (pressure, temp, altdec, &altdec);
  468.         aa_hadec (lat, altdec, azra, &ha, &dec);
  469.         ra = hrrad(lst) - ha;
  470.         range (&ra, 2*PI);
  471.         if (epoch != EOD)
  472.             precess (mjd, epoch, &ra, &dec);
  473.         } else {
  474.         /* need to make the alt/az entries */
  475.         ra = azra;
  476.         dec = altdec;
  477.         if (epoch != EOD)
  478.             precess (epoch, mjd, &azra, &altdec);
  479.         ha = hrrad(lst) - azra;
  480.         range (&ha, 2*PI);
  481.         hadec_aa (lat, ha, altdec, &alt, &az);
  482.         refract (pressure, temp, alt, &alt);
  483.         }
  484.  
  485.         (void) strcpy (alt_buf, "Alt: ");
  486.         fs_angle (alt_buf+5, alt);
  487.         (void) strcpy (az_buf, "Az: ");
  488.         fs_angle (az_buf+4, az);
  489.         (void) strcpy (ra_buf, "RA: ");
  490.         fs_ra (ra_buf+4, ra);
  491.         (void) strcpy (dec_buf, "Dec: ");
  492.         fs_angle (dec_buf+5, dec);
  493.     } else {
  494.         (void) strcpy (alt_buf, " ");
  495.         (void) strcpy (az_buf, " ");
  496.         (void) strcpy (ra_buf, " ");
  497.         (void) strcpy (dec_buf, " ");
  498.     }
  499.  
  500.     f_showit (talt_w, alt_buf);
  501.     f_showit (taz_w, az_buf);
  502.     f_showit (tra_w, ra_buf);
  503.     f_showit (tdec_w, dec_buf);
  504. }
  505.  
  506. /* a dot has been picked:
  507.  * find what it is and report stuff about it in a popup.
  508.  */
  509. /* ARGSUSED */
  510. static void
  511. sv_da_input_cb (w, client, call)
  512. Widget w;
  513. XtPointer client;
  514. XtPointer call;
  515. {
  516. #define    PICKRANGE    100    /* sqr of dist allowed from pointer */
  517.     XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
  518.     XEvent *ev;
  519.     TrailObj *top;
  520.     unsigned int wide, h, r, xb, yb;
  521.     int x, y;
  522.     int mind = 1000000;    /* min distance to far */
  523.     TSky *mintsp = NULL;    /* set to a TSky if find one close */
  524.     Obj *minop = NULL;    /* set to an Obj if find one closer */
  525.     Obj *op;
  526.     int cx, cy;
  527.     int d;
  528.     int i;
  529.  
  530.     if (c->reason != XmCR_INPUT)
  531.         return;
  532.     ev = c->event;
  533.     if (ev->xany.type != ButtonPress || ev->xbutton.button != 3)
  534.         return;
  535.  
  536.     watch_cursor(1);
  537.  
  538.     sv_getcircle (&wide, &h, &r, &xb, &yb);
  539.  
  540.     /* search everything based on cursor loc within the circle */
  541.     cx = ev->xbutton.x - xb;
  542.     cy = ev->xbutton.y - yb;
  543.  
  544.     /* search the trailed stuff first because
  545.      * the first entry in a trailing list will be both in the db and in
  546.      * the trails list -- we want to find the latter when we can.
  547.      */
  548.     for (top = trailobj; top; top = top->ntop) {
  549.         if (!top->on)
  550.         continue;
  551.         for (i = 0; i < top->nsky; i++) {
  552.         if (!sv_trailobjloc (&top->sky[i], r, &x, &y))
  553.             continue;
  554.         d = (cx - x)*(cx - x) + (cy - y)*(cy - y);
  555.         if (d < mind) {
  556.             mintsp = &top->sky[i];
  557.             mind = d;
  558.         }
  559.         }
  560.     }
  561.  
  562.     /* search the database too -- might be something closer */
  563.     for (op = db_next(NULL, OBJS_ALL); op; op = db_next(op, OBJS_ALL)) {
  564.         if (!(op->o_flags & OBJF_ONSCREEN))
  565.         continue;
  566.         if (!sv_dbobjloc (op, r, &x, &y))
  567.         continue;    /* not in the circle now */
  568.         d = (cx - x)*(cx - x) + (cy - y)*(cy - y);
  569.         if (d < mind) {
  570.         minop = op;
  571.         mind = d;
  572.         }
  573.     }
  574.  
  575.     if (mind <= PICKRANGE)
  576.         sv_popup (ev, minop, minop ? NULL : mintsp);
  577.  
  578.     watch_cursor(0);
  579. }
  580.  
  581. /* callback when any of the scales change value.
  582.  */
  583. /* ARGSUSED */
  584. static void
  585. sv_changed_cb (w, client, call)
  586. Widget w;
  587. XtPointer client;
  588. XtPointer call;
  589. {
  590.     sv_set_view();
  591.     sv_all(mm_get_now(), 1);
  592. }
  593.  
  594. /* callback when the "just dots" toggle button changes state.
  595.  */
  596. /* ARGSUSED */
  597. static void
  598. sv_justdots_cb (w, client, call)
  599. Widget w;
  600. XtPointer client;
  601. XtPointer call;
  602. {
  603.     justdots = XmToggleButtonGetState (w);
  604.     sv_all(mm_get_now(), 1);
  605. }
  606.  
  607. /* callback when the "ecliptic" toggle button changes state.
  608.  */
  609. /* ARGSUSED */
  610. static void
  611. sv_ecliptic_cb (w, client, call)
  612. Widget w;
  613. XtPointer client;
  614. XtPointer call;
  615. {
  616.     want_ecliptic = XmToggleButtonGetState (w);
  617.     sv_all(mm_get_now(), 1);
  618. }
  619.  
  620. /* callback when the "all labels" toggle button changes state.
  621.  */
  622. /* ARGSUSED */
  623. static void
  624. sv_all_labels_cb (w, client, call)
  625. Widget w;
  626. XtPointer client;
  627. XtPointer call;
  628. {
  629.     all_labels = XmToggleButtonGetState (w);
  630.     sv_all(mm_get_now(), 1);
  631. }
  632.  
  633. /* callback when the "Find" cascade button is activated.
  634.  * check the used defined objects and adjust the cascade buttons accordingly.
  635.  */
  636. /* ARGSUSED */
  637. static void
  638. sv_finding_cb (wid, client, call)
  639. Widget wid;
  640. XtPointer client;
  641. XtPointer call;
  642. {
  643.     int i;
  644.  
  645.     for (i = 0; i < 2; i++) {
  646.         Obj *op = db_basic (i == 0 ? OBJX : OBJY);
  647.         Widget w = find_w[i];
  648.         if (op->type == UNDEFOBJ)
  649.         XtUnmanageChild (w);
  650.         else {
  651.         set_xmstring (w, XmNlabelString, op->o_name);
  652.         XtManageChild (w);
  653.         }
  654.     }
  655. }
  656.  
  657. /* callback when one of the "point" cascade buttons changes state.
  658.  * object index is in client.
  659.  */
  660. /* ARGSUSED */
  661. static void
  662. sv_find_cb (w, client, call)
  663. Widget w;
  664. XtPointer client;
  665. XtPointer call;
  666. {
  667.     Obj *op = db_basic((int)client);
  668.  
  669.     switch (sv_id (op)) {
  670.     case 0: 
  671.         break;
  672.     case -1:
  673.         xe_msg ("Object is below the horizon now", 1);
  674.         break;
  675.     case -2:
  676.         sv_point (op);
  677.         break;
  678.     }
  679. }
  680.  
  681. /* callback as either magnitude scale is dragged.
  682.  * enforce at least a 1 mag window.
  683. */
  684. /* ARGSUSED */
  685. static void
  686. sv_magdrag_cb (w, client, call)
  687. Widget w;
  688. XtPointer client;
  689. XtPointer call;
  690. {
  691.     int f, b;
  692.  
  693.     XmScaleGetValue (fmag_w, &f);
  694.     XmScaleGetValue (bmag_w, &b);
  695.     if (f - b < 1)
  696.         XmScaleSetValue (w, w == fmag_w ? b+1 : f-1);
  697. }
  698.  
  699. /* read the scales and alt-az widgets into the global variables that
  700.  * describe our current display conditions.
  701.  */
  702. static void
  703. sv_set_view()
  704. {
  705.     int i;
  706.  
  707.     XmScaleGetValue (fov_w, &i);
  708.     sv_fov = degrad(i);
  709.  
  710.     XmScaleGetValue (bmag_w, &bmag);
  711.     XmScaleGetValue (fmag_w, &fmag);
  712.  
  713.     XmScaleGetValue (altdec_w, &i);
  714.     sv_altdec = degrad(i);
  715.     XmScaleGetValue (azra_w, &i);
  716.     sv_azra = aa_mode ? degrad(i) : hrrad((double)i/10.0);
  717. }
  718.  
  719. /* return the current circle info about svda_w */
  720. static void
  721. sv_getcircle (wp, hp, rp, xbp, ybp)
  722. unsigned int *wp, *hp;        /* overall width and height */
  723. unsigned int *rp;        /* circle radius */
  724. unsigned int *xbp, *ybp;    /* x and y border */
  725. {
  726.     Display *dsp = XtDisplay(svda_w);
  727.     Window win = XtWindow(svda_w);
  728.     Window root;
  729.     int x, y;
  730.     unsigned int w, h;
  731.     unsigned int bw, d;
  732.  
  733.     XGetGeometry (dsp, win, &root, &x, &y, wp, hp, &bw, &d);
  734.     w = *wp/2;
  735.     h = *hp/2;
  736.     *rp = w > h ? h : w;    /* radius */
  737.     *xbp = w - *rp;        /* x border */
  738.     *ybp = h - *rp;        /* y border */
  739.  
  740. }
  741.  
  742. /* fill in the popup with goodies from db object *op or *tsp if it is set:
  743.  *   if tsp is set use it's Obj -- this is a trailed object.
  744.  * position the popup as indicated by ev and display it.
  745.  * it goes down by itself.
  746.  */
  747. static void
  748. sv_popup (ev, op, tsp)
  749. XEvent *ev;
  750. Obj *op;
  751. TSky *tsp;
  752. {
  753.     char buf[32], buf2[64];
  754.     int trail;
  755.     int label;
  756.     double jd;
  757.  
  758.     if (tsp) {
  759.         /* we were given a trailed Obj */
  760.         TrailObj *top;
  761.         op = &tsp->o;
  762.         jd = tsp->ts_mjd;
  763.         top = tobj_find (op);
  764.         trail = top->on;
  765.         label = !!(tsp->flags & OBJF_LABEL);
  766.     } else {
  767.         /* no tsp trail -- just use the db */
  768.         Now *np = mm_get_now();
  769.         jd = mjd;
  770.         trail = 0;
  771.         label = !!(op->o_flags & OBJF_LABEL);
  772.     }
  773.  
  774.     XmToggleButtonSetState (pu.trail_w, trail, False);
  775.     XmToggleButtonSetState (pu.label_w, label, False);
  776.  
  777.     pu.op = op;
  778.     pu.tsp = tsp;
  779.  
  780.     (void) sprintf (buf2, "   Name: %.20s", op->o_name);
  781.     set_xmstring (pu.name_w, XmNlabelString, buf2);
  782.  
  783.     (void) sprintf (buf2, "   Type: %.20s", obj_description(op));
  784.     set_xmstring (pu.desc_w, XmNlabelString, buf2);
  785.  
  786.     if (op->type == FIXED && op->f_spect[0]) {
  787.         (void) sprintf (buf2, "  Spect: %.*s", sizeof(op->f_spect),
  788.                                 op->f_spect);
  789.         set_xmstring (pu.spect_w, XmNlabelString, buf2);
  790.         XtManageChild (pu.spect_w);
  791.     } else
  792.         XtUnmanageChild (pu.spect_w);
  793.  
  794.     fs_date (buf, jd);
  795.     (void) sprintf (buf2, "UT Date: %s", buf);
  796.     set_xmstring (pu.ud_w, XmNlabelString, buf2);
  797.  
  798.     fs_time (buf, mjd_hr(jd));
  799.     (void) sprintf (buf2, "UT Time: %s", buf);
  800.     set_xmstring (pu.ut_w, XmNlabelString, buf2);
  801.  
  802.     fs_ra (buf, op->s_ra);
  803.     (void) sprintf (buf2, "     RA: %s", buf);
  804.     set_xmstring (pu.ra_w, XmNlabelString, buf2);
  805.  
  806.     fs_angle (buf, op->s_dec);
  807.     (void) sprintf (buf2, "    Dec: %s", buf);
  808.     set_xmstring (pu.dec_w, XmNlabelString, buf2);
  809.  
  810.     fs_angle (buf, op->s_alt);
  811.     (void) sprintf (buf2, "    Alt: %s", buf);
  812.     set_xmstring (pu.alt_w, XmNlabelString, buf2);
  813.  
  814.     fs_angle (buf, op->s_az);
  815.     (void) sprintf (buf2, "     Az: %s", buf);
  816.     set_xmstring (pu.az_w, XmNlabelString, buf2);
  817.  
  818.     (void) sprintf (buf2, "    Mag: %.3g", op->s_mag/MAGSCALE);
  819.     set_xmstring (pu.mag_w, XmNlabelString, buf2);
  820.  
  821.     XmMenuPosition (pu.pu_w, (XButtonPressedEvent *)ev);
  822.     XtManageChild (pu.pu_w);
  823. }
  824.  
  825. /* create the id popup */
  826. static void
  827. sv_create_popup()
  828. {
  829.     static Widget *puw[] = {
  830.         &pu.name_w,
  831.         &pu.desc_w,
  832.         &pu.spect_w,
  833.         &pu.ud_w,
  834.         &pu.ut_w,
  835.         &pu.ra_w,
  836.         &pu.dec_w,
  837.         &pu.alt_w,
  838.         &pu.az_w,
  839.         &pu.mag_w,
  840.     };
  841.     Arg args[20];
  842.     XmString str;
  843.     Widget w;
  844.     int i, n;
  845.  
  846.     /* create the outer form */
  847.     n = 0;
  848.     XtSetArg (args[n], XmNisAligned, True); n++;
  849.     XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  850.     pu.pu_w = XmCreatePopupMenu (toplevel_w, "SVPopup", args, n);
  851.  
  852.     /* create the label widgets */
  853.  
  854.     for (i = 0; i < XtNumber(puw); i++) {
  855.         n = 0;
  856.         *puw[i] = XmCreateLabel (pu.pu_w, "SVPopValueL", args, n);
  857.         XtManageChild (*puw[i]);
  858.     }
  859.  
  860.     /* add a nice separator */
  861.     n = 0;
  862.     w = XmCreateSeparator (pu.pu_w, "SVSep", args, n);
  863.     XtManageChild(w);
  864.  
  865.     /* make the "aim", "ObjX" and "trail" command buttons */
  866.  
  867.     str = XmStringCreateLtoR ("Point", XmSTRING_DEFAULT_CHARSET);
  868.     n = 0;
  869.     XtSetArg (args[n], XmNlabelString, str); n++;
  870.     w = XmCreatePushButton (pu.pu_w, "SVPopPoint", args, n);
  871.     XtAddCallback (w, XmNactivateCallback, sv_pu_activate_cb,
  872.                                 (XtPointer)AIM);
  873.     XtManageChild (w);
  874.     XmStringFree (str);
  875.  
  876.     str = XmStringCreateLtoR ("Make ObjX/Y", XmSTRING_DEFAULT_CHARSET);
  877.     n = 0;
  878.     XtSetArg (args[n], XmNlabelString, str); n++;
  879.     w = XmCreatePushButton (pu.pu_w, "SVPopMakeObj", args, n);
  880.     XtAddCallback (w, XmNactivateCallback, sv_pu_activate_cb,
  881.                             (XtPointer)MK_OBJX);
  882.     XtManageChild (w);
  883.     XmStringFree(str);
  884.  
  885.     str = XmStringCreateLtoR ("Leave Trail", XmSTRING_DEFAULT_CHARSET);
  886.     n = 0;
  887.     XtSetArg (args[n], XmNlabelString, str); n++;
  888.     XtSetArg (args[n], XmNvisibleWhenOff, True); n++;
  889.     pu.trail_w = XmCreateToggleButton (pu.pu_w, "SVPopTrail", args, n);
  890.     XtAddCallback(pu.trail_w, XmNvalueChangedCallback, sv_pu_trail_cb,NULL);
  891.     XtManageChild (pu.trail_w);
  892.     XmStringFree(str);
  893.  
  894.     str = XmStringCreateLtoR ("Persistent Label", XmSTRING_DEFAULT_CHARSET);
  895.     n = 0;
  896.     XtSetArg (args[n], XmNlabelString, str); n++;
  897.     XtSetArg (args[n], XmNvisibleWhenOff, True); n++;
  898.     pu.label_w = XmCreateToggleButton (pu.pu_w, "SVPopLabel", args, n);
  899.     XtAddCallback(pu.label_w, XmNvalueChangedCallback, sv_pu_label_cb,NULL);
  900.     XtManageChild (pu.label_w);
  901.     XmStringFree(str);
  902. }
  903.  
  904. /* called when any of the popup's pushbuttons are activated.
  905.  * client is a code to indicate which.
  906.  */
  907. /* ARGSUSED */
  908. static void
  909. sv_pu_activate_cb (w, client, call)
  910. Widget w;
  911. XtPointer client;
  912. XtPointer call;
  913. {
  914.     switch ((int)client) {
  915.     case AIM:
  916.         sv_point (pu.tsp ? &pu.tsp->o : pu.op);
  917.         break;
  918.     case MK_OBJX: {
  919.         switch (pu.op->type) {
  920.         case HYPERBOLIC: case PARABOLIC: case ELLIPTICAL: case FIXED:
  921.         sv_ournewobj = 1;
  922.         obj_set (pu.op);
  923.         sv_ournewobj = 0;
  924.         break;
  925.         default:
  926.         xe_msg ("User objects can not be of that type.", 0);
  927.         break;
  928.         }
  929.         }
  930.         break;
  931.     }
  932. }
  933.  
  934. /* called when the Trail popup toggle button changes.
  935.  * clean up the trailobj stuff.
  936.  */
  937. /* ARGSUSED */
  938. static void
  939. sv_pu_trail_cb (wid, client, call)
  940. Widget wid;
  941. XtPointer client;
  942. XtPointer call;
  943. {
  944.     if (XmToggleButtonGetState(wid)) {
  945.         /* trail is being turned on.
  946.          * if it already has a trail just turn it back on and draw it, else
  947.          *   add a new db obj to trailobj list.
  948.          */
  949.         TrailObj *top = tobj_find (pu.op);
  950.         if (top) {
  951.         unsigned int w, h, r, xb, yb;
  952.         sv_getcircle (&w, &h, &r, &xb, &yb);
  953.         top->on = 1;
  954.         tobj_display_all(r, xb, yb);
  955.         sv_copy_sky();
  956.         } else {
  957.         Now *np = mm_get_now();
  958.         top = tobj_addobj (pu.op);
  959.         (void) tobj_addsky (top, mjd, pu.op);
  960.         /* no need to redraw since a trail of lenth 1 won't *look*
  961.          * any different.
  962.          */
  963.         }
  964.     } else {
  965.         /* trailing is being turned off. mark it as being off.
  966.          * it will get removed at the next update if it's still off.
  967.          * redraw sky so it disappears.
  968.          */
  969.         TrailObj *top = tobj_find (pu.op);
  970.         top->on = 0;
  971.         sv_all (mm_get_now(), 1);
  972.     }
  973. }
  974.  
  975. /* called when the Label popup toggle button changes.
  976.  * we get all context from the pu structure.
  977.  */
  978. /* ARGSUSED */
  979. static void
  980. sv_pu_label_cb (wid, client, call)
  981. Widget wid;
  982. XtPointer client;
  983. XtPointer call;
  984. {
  985.     unsigned int w, h, r, xb, yb;
  986.     int x, y;
  987.     int label;
  988.     char *name;
  989.  
  990.     /* if this is a trailed item then its TSky will be in pu.tsp
  991.      * otherwise it is a plain db object.
  992.      * either way, toggle the corresponding OBJF_LABEL bit too.
  993.      */
  994.     if (pu.tsp) {
  995.         label = (pu.tsp->flags ^= OBJF_LABEL) & OBJF_LABEL;
  996.         if (label) {
  997.         sv_getcircle (&w, &h, &r, &xb, &yb);
  998.         (void) sv_trailobjloc (pu.tsp, r, &x, &y);
  999.         name = pu.tsp->o.o_name;
  1000.         }
  1001.