home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part14 / objmenu.c < prev   
C/C++ Source or Header  |  1993-05-15  |  35KB  |  1,315 lines

  1. /* code to manage the stuff on the "objx/y" menu.
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <math.h>
  7. #if defined(__STDC__)
  8. #include <stdlib.h>
  9. #endif
  10. #include <X11/Xlib.h>
  11. #include <Xm/Xm.h>
  12. #include <Xm/Form.h>
  13. #include <Xm/Frame.h>
  14. #include <Xm/Label.h>
  15. #include <Xm/PushB.h>
  16. #include <Xm/ToggleB.h>
  17. #include <Xm/RowColumn.h>
  18. #include <Xm/ScrollBar.h>
  19. #include <Xm/SelectioB.h>
  20. #include "astro.h"
  21. #include "circum.h"
  22. #include "preferences.h"
  23.  
  24. extern Widget toplevel_w;
  25.  
  26. /* info about each field for a given type of object.
  27.  * N.B. the prompt field is used to decide whether a button should be created
  28.  *   to let this field be changed. Some prompts are determined at runtime
  29.  *   though based on preference. For these, we need at least a dummy.
  30.  *   the runtime setting is done in obj_change_cb().
  31.  * N.B. the altp entries must match the values of the PREF_XX enums.
  32.  */
  33. typedef struct {
  34.     int id;        /* field id */
  35.     char *label;    /* label */
  36.     char *prompt;    /* prompt if changeable, or 0 if it can't be */
  37.     char *altp[3];    /* alternate prompts for fields effected by prefs */
  38.     Widget pb_w;    /* PushButton if it can be changed, else Label */
  39. } Field;
  40.  
  41. #if defined(__STDC__) || defined(__cplusplus)
  42. #define P_(s) s
  43. #define    Const const
  44. #else
  45. #define P_(s) ()
  46. #define    Const
  47. #endif
  48.  
  49. extern Now *mm_get_now P_((void));
  50. extern Obj *db_basic P_((int id));
  51. extern Obj *db_next P_((Obj *op, HowNext how));
  52. extern char *obj_description P_((Obj *op));
  53. extern int db_n P_((void));
  54. extern int db_set_field P_((char bp[], int id, PrefDateFormat pref, Obj *op));
  55. extern int obj_cir P_((Now *np, Obj *op));
  56. extern int sv_id P_((Obj *op));
  57. extern void all_newobj P_((int dbidx));
  58. extern void db_setuserobj P_((int id, Obj *op));
  59. extern void f_double P_((Widget w, char *fmt, double f));
  60. extern void f_gangle P_((Widget w, double a));
  61. extern void f_ra P_((Widget w, double ra));
  62. extern void f_string P_((Widget w, char *s));
  63. extern void fs_date P_((char out[], double jd));
  64. extern void get_something P_((Widget w, char *resource, char *value));
  65. extern void get_xmstring P_((Widget w, char *resource, char **txtp));
  66. extern void hlp_dialog P_((char *tag, char *deflt[], int ndeflt));
  67. extern void mjd_year P_((double Mjd, double *yr));
  68. extern void prompt_map_cb P_((Widget w, XtPointer client, XtPointer call));
  69. extern void sv_point P_((Obj *op));
  70. extern void watch_cursor P_((int want));
  71. extern void xe_msg P_((char *msg, int app_modal));
  72. extern void zero_mem P_((char *loc, unsigned len));
  73.  
  74. void obj_manage P_((void));
  75. void obj_update P_((Now *np, int howmuch));
  76. void obj_set P_((Obj *op));
  77. void obj_newdb P_((int appended));
  78. void obj_cursor P_((Cursor c));
  79. static void init_working_obj P_((void));
  80. static void obj_unsetmenu P_((void));
  81. static void obj_set_from_db P_((Obj *op));
  82. static void obj_set_db P_((void));
  83. static void obj_setmenu P_((void));
  84. static void obj_setobjinfo P_((Field *fp, int nf));
  85. static void obj_create_form P_((void));
  86. static void obj_create_type_rc_form P_((Widget fw, Field *fp));
  87. static void obj_change_cb P_((Widget w, XtPointer client, XtPointer call));
  88. static void obj_ctl_cb P_((Widget w, XtPointer client, XtPointer call));
  89. static void do_help P_((void));
  90. static void obj_xy_cb P_((Widget w, XtPointer client, XtPointer call));
  91. static void obj_type_cb P_((Widget w, XtPointer client, XtPointer call));
  92. static void obj_select_cb P_((Widget w, XtPointer client, XtPointer call));
  93. static void obj_scroll_cb P_((Widget w, XtPointer client, XtPointer call));
  94. static int nl_cmp P_((Const void *nl1, Const void *nl2));
  95. static void new_namelist P_((void));
  96. static void load_namelist P_((void));
  97. static void obj_setnames P_((int nli));
  98. static void obj_set_a_button P_((Widget pbw, int whether));
  99. static void prompt_ok_cb P_((Widget w, XtPointer client, XtPointer call));
  100. static void prompt P_((Field *fp));
  101. static void obj_set_button P_((Widget w, int id));
  102. static void epoch_as_decimal P_((Widget w, double e));
  103. static void epoch_as_mdy P_((Widget w, double e));
  104.  
  105. #undef P_
  106.  
  107. static Widget objform_w;    /* overall form Dialog */
  108. static Widget fldrc_w;        /* overall field info rc */
  109. static Widget scroll_w;        /* name scroll widget */
  110.  
  111. static Field fixed_fields[] = {
  112.     {O_NAME,  "Name:",  "Object name:"},
  113.     {F_CLASS, "Class:",    NULL},
  114.     {F_RA,    "RA:",    "RA (h:m:s):"},
  115.     {F_DEC,   "Dec:",    "Dec (d:m:s):"},
  116.     {F_MAG,   "Mag:",    "Magnitude:"},
  117.     {F_EPOCH, "Epoch:", "dummy", {
  118.     "Reference epoch (UT Date as m/d.d/y or year.d):",
  119.     "Reference epoch (UT Date as y/m/d.d or year.d):",
  120.     "Reference epoch (UT Date as d.d/m/y or year.d):"
  121.     }
  122.     },
  123.     {F_SIZE,  "Size:",  "Angular Size (arc secs):"},
  124. };
  125.  
  126. static Field ellip_fields[] = {
  127.     {O_NAME, "Name:", "Object name:"},
  128.     {E_INC, "Inclination:", "Inclination (degs):"},
  129.     {E_LAN, "Long of Asc Nod:", "Longitude of ascending node (degs):"},
  130.     {E_AOP, "Arg of Peri:", "Argument of Perihelion (degs):"},
  131.     {E_A, "Mean Dist:", "Mean distance (AU):"},
  132.     {E_N, "Daily Motion:", "Daily motion (degs/day):"},
  133.     {E_E, "Eccentricity:", "Eccentricty (<1):"},
  134.     {E_M, "Mean Anomaly:", "Mean Anomaly (degs):"},
  135.     {E_CEPOCH, "C Epoch:", "dummy", {
  136.     "Epoch date (UT Date as m/d.d/y or year.d):",
  137.     "Epoch date (UT Date as y/m/d.d or year.d):",
  138.     "Epoch date (UT Date as d.d/m/y or year.d):"
  139.     }
  140.     },
  141.     {E_EPOCH, "Epoch:", "dummy", {
  142.     "Equinox year (UT Date as m/d.d/y or year.d):",
  143.     "Equinox year (UT Date as y/m/d.d or year.d):",
  144.     "Equinox year (UT Date as d.d/m/y or year.d):"
  145.     }
  146.     },
  147.     {E_M1, "Mag coeff 1:", "Magnitude coefficient 1 (g#, H# or just #):"},
  148.     {E_M2, "Mag coeff 2:", "Magnitude coefficient 2 (k#, G# or just #):"},
  149.     {E_SIZE, "Size:", "Angular Size @ 1 AU (arc secs):"},
  150. };
  151.  
  152. static Field hyper_fields[] = {
  153.     {O_NAME, "Name:", "Object name:"},
  154.     {H_EP, "Ep of Peri:", "dummy", {
  155.     "Epoch of perihelion (UT Date as m/d.d/y or year.d):",
  156.     "Epoch of perihelion (UT Date as y/m/d.d or year.d):",
  157.     "Epoch of perihelion (UT Date as d.d/m/y or year.d):"
  158.     }
  159.     },
  160.     {H_INC, "Inclination:", "Inclination (degs):"},
  161.     {H_LAN, "Long of Asc Nod:", "Longitude of ascending node (degs):"},
  162.     {H_AOP, "Arg of Peri:", "Argument of perihelion (degs):"},
  163.     {H_E, "Eccentricity:", "Eccentricity (>1):"},
  164.     {H_QP, "Peri Dist:", "Perihelion distance (AU):"},
  165.     {H_EPOCH, "Epoch:", "dummy", {
  166.     "Reference epoch (UT Date as m/d.d/y or year.d):",
  167.     "Reference epoch (UT Date as y/m/d.d or year.d):",
  168.     "Reference epoch (UT Date as d.d/m/y or year.d):"
  169.     }
  170.     },
  171.     {H_G, "g:", "g, as in m = g + 5*log(delta) + 2.5*k*log(r):"},
  172.     {H_K, "k:", "k, as in m = g + 5*log(delta) + 2.5*k*log(r):"},
  173.     {H_SIZE, "Size:", "Angular Size @ 1 AU (arc secs):"},
  174. };
  175.  
  176. static Field para_fields[] = {
  177.     {O_NAME, "Name:", "Object name:"},
  178.     {P_EP, "Ep of Peri:", "dummy", {
  179.     "Epoch of perihelion (UT Date as m/d.d/y or year.d):",
  180.     "Epoch of perihelion (UT Date as y/m/d.d or year.d):",
  181.     "Epoch of perihelion (UT Date as d.d/m/y or year.d):"
  182.     }
  183.     },
  184.     {P_INC, "Inclination:", "Inclination (degs):"},
  185.     {P_AOP, "Arg of Peri:", "Argument of perihelion (degs):"},
  186.     {P_QP, "Peri Dist:", "Perihelion distance (AU):"},
  187.     {P_LAN, "Long of Asc Nod:", "Longitude of ascending node (degs):"},
  188.     {P_EPOCH, "Epoch:", "dummy", {
  189.     "Reference epoch (UT Date as m/d.d/y or year.d):",
  190.     "Reference epoch (UT Date as y/m/d.d or year.d):",
  191.     "Reference epoch (UT Date as d.d/m/y or year.d):"
  192.     }
  193.     },
  194.     {P_G, "g:", "g, as in m = g + 5*log(delta) + 2.5*k*log(r):"},
  195.     {P_K, "k:", "k, as in m = g + 5*log(delta) + 2.5*k*log(r):"},
  196.     {P_SIZE, "Size:", "Angular Size @ 1 AU (arc secs):"},
  197. };
  198.  
  199. typedef struct {
  200.     char *name;        /* name of type toggle button */
  201.     Field *fp;        /* ptr to Fields array defining the info, if any */
  202.     int nfields;    /* number of Fields in fp[] */
  203.     Widget tb_w;    /* type toggle button widget */
  204.     Widget frc_w;    /* Field rc widget */
  205. } TypeInfo;
  206. /* names of each type.
  207.  * N.B. must match order of enum in circum.h.
  208.  */
  209. static TypeInfo typeinfo[NOBJTYPES-1 /*No PLANET*/] = {
  210.     {"Undefined",  NULL,       0},
  211.     {"Fixed",       fixed_fields,  XtNumber(fixed_fields)},
  212.     {"Elliptical", ellip_fields,  XtNumber(ellip_fields)},
  213.     {"Hyperbolic", hyper_fields,  XtNumber(hyper_fields)},
  214.     {"Parabolic",  para_fields,   XtNumber(para_fields)},
  215. };
  216.  
  217. /* working storage - set when Reset, made permanent in database with Apply
  218.  */
  219. static Obj objx;
  220. static Obj objy;
  221. static int objidx = OBJX;        /* which one is on-screen now */
  222. #define    objp    (objidx == OBJY ? &objy : &objx)
  223.  
  224. /* used to maintain mapping between object selection buttons and database
  225.  * objects. the userData of each object selection button is set to the index of
  226.  * a namelist[].
  227.  */
  228. typedef struct {
  229.     char *name;
  230.     Obj *op;
  231. } NameList;
  232.  
  233. #define    NBTNS    20        /* number of buttons in name list */
  234. static NameList *namelist;    /* malloced array of (db_n()-NOBJ) NameLists*/
  235. static int nnamelist;        /* number of entries in namelist actually used*/
  236. static Widget namepb_w[NBTNS];    /* each name selection button */
  237.  
  238. #define    SCROLLBAR_WIDTH        20
  239.  
  240. /* bottom control panel buttons */
  241. enum {
  242.     OK, APPLY, RESET, POINT, IDENT, CANCEL, HELP
  243. };
  244.  
  245. /* called by the main menu pick.
  246.  * create the main form, if this is the first time we've been called.
  247.  * then we toggle each time.
  248.  */
  249. void
  250. obj_manage()
  251. {
  252.     if (!objform_w) {
  253.         obj_create_form();
  254.         init_working_obj();
  255.         new_namelist();
  256.         obj_setmenu();
  257.     }
  258.     
  259.     if (XtIsManaged(objform_w))
  260.         XtUnmanageChild (objform_w);
  261.     else
  262.         XtManageChild (objform_w);
  263. }
  264.  
  265. /* all this is really good for is if the date format changes.
  266.  */
  267. /* ARGSUSED */
  268. void
  269. obj_update (np, howmuch)
  270. Now *np;
  271. int howmuch;
  272. {
  273.     obj_setmenu();
  274. }
  275.  
  276. /* make the given arbitrary db object the current objectX/Y:
  277.  * update our working copy, the real db object, all the stuff in the menu (if
  278.  * we've been managed!) and inform all others.
  279.  */
  280. void
  281. obj_set (op)
  282. Obj *op;
  283. {
  284.     static char me[] = "obj_set()";
  285.  
  286.     /* TODO: we don't support planets */
  287.     if (op->type == PLANET) {
  288.         printf ("%s: planets not supported\n", me);
  289.         exit (1);
  290.     }
  291.  
  292.     obj_unsetmenu();
  293.     obj_set_from_db(op);    /* *objp <- *op */
  294.     obj_setmenu();
  295.     obj_set_db();        /* db_setuserobj(objp) */
  296.     all_newobj (objidx);
  297. }
  298.  
  299. /* called when the db has changed (beyond NOBJ that is).
  300.  * we don't care if it was appended or replaced because we need to resort and
  301.  * rebuild the whole list either way.
  302.  */
  303. /* ARGSUSED */
  304. void
  305. obj_newdb(appended)
  306. int appended;
  307. {
  308.     if (!objform_w)
  309.         return;
  310.     new_namelist();
  311. }
  312.  
  313. /* called to put up or remove the watch cursor.  */
  314. void
  315. obj_cursor (c)
  316. Cursor c;
  317. {
  318.     Window win;
  319.  
  320.     if (objform_w && (win = XtWindow(objform_w))) {
  321.         Display *dsp = XtDisplay(objform_w);
  322.         if (c)
  323.         XDefineCursor (dsp, win, c);
  324.         else
  325.         XUndefineCursor (dsp, win);
  326.     }
  327. }
  328.  
  329. /* this was added to support backward compatability with the ability to
  330.  * set OBJX and OBJY from the ephem.cfg file.
  331.  */
  332. static void
  333. init_working_obj()
  334. {
  335.     Obj *op;
  336.  
  337.     op = db_basic(OBJX);
  338.     objx = *op;
  339.     op = db_basic(OBJY);
  340.     objy = *op;
  341. }
  342.  
  343. /* turn off menu info about the current object.
  344.  */
  345. static void
  346. obj_unsetmenu()
  347. {
  348.     if (!objform_w)
  349.         return;
  350.  
  351.     XtUnmanageChild (typeinfo[objp->type].frc_w);
  352.     XmToggleButtonSetState (typeinfo[objp->type].tb_w, False, False);
  353. }
  354.  
  355. /* copy the arbitrary database object, op, into the working copy of the
  356.  * current object.
  357.  * TODO: N.B. don't allow planets -- YET!
  358.  */
  359. static void
  360. obj_set_from_db (op)
  361. Obj *op;
  362. {
  363.     static char me[] = "obj_set_from_db()";
  364.  
  365.     if (op->type == PLANET) {
  366.         printf ("%s: PLANET not supported\n", me);
  367.         exit (1);
  368.     }
  369.  
  370.     /* *objp = *op; */
  371.     (void) memcpy ((char *)objp, (char *)op, sizeof(Obj));
  372. }
  373.  
  374. /* make the current working object officially in the database.
  375.  */
  376. static void
  377. obj_set_db ()
  378. {
  379.     db_setuserobj(objidx, objp);
  380. }
  381.  
  382. /* set up the menu according to the current working object
  383.  */
  384. static void
  385. obj_setmenu()
  386. {
  387.     TypeInfo *tp;
  388.     int type;
  389.  
  390.     if (!objform_w)
  391.         return;
  392.  
  393.     type = objp->type;
  394.     tp = &typeinfo[type];
  395.     XmToggleButtonSetState (tp->tb_w, True, False);
  396.     obj_setobjinfo(tp->fp, tp->nfields);
  397.     XtManageChild (tp->frc_w);
  398. }
  399.  
  400. /* set each field in the rc for the current object.
  401.  */
  402. static void
  403. obj_setobjinfo(fp, nf)
  404. Field *fp;
  405. int nf;
  406. {
  407.     while (--nf >= 0) {
  408.         obj_set_button (fp->pb_w, fp->id);
  409.         fp++;
  410.     }
  411. }
  412.  
  413. /* called once to build the basic form.
  414.  * N.B. we could not manage to connect the right side of NameF to the left
  415.  * side of ScrollB without complaints from the Obj form. So, to make it look
  416.  * attached, both NameF and ScrollB are attach to the right side of the form
  417.  * but the NameF has an offset equal to the width of ScrollB. hey -- it works!
  418.  */
  419. static void
  420. obj_create_form ()
  421. {
  422.     struct Btns {    /* to streamline creation of control buttons */
  423.         int id;
  424.         char *name;
  425.     };
  426.     static struct Btns ctlbtns[] = {
  427.         {OK, "Ok"},
  428.         {APPLY, "Apply"},
  429.         {RESET, "Reset"},
  430.         {CANCEL, "Close"},
  431.         {HELP, "Help"}
  432.     };
  433.     static struct Btns skybtns[] = {
  434.         {POINT, "Sky Point"},
  435.         {IDENT, "Sky Mark"},
  436.     };
  437.     Widget typrbf_w, typrb_w;
  438.     Widget fldrcf_w;
  439.     Widget xyrbf_w, xyrb_w;
  440.     Widget namerc_w, namercf_w;
  441.     Widget ctlfr_w, ctlf_w;
  442.     Widget skyfr_w, skyf_w;
  443.     Widget w;
  444.     Arg args[20];
  445.     int n;
  446.     int i;
  447.  
  448.     /* create form */
  449.     n = 0;
  450.     XtSetArg (args[n], XmNautoUnmanage, False); n++;
  451.     XtSetArg (args[n], XmNdefaultPosition, False); n++;
  452.     XtSetArg (args[n], XmNallowOverlap, False); n++;
  453.     XtSetArg (args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
  454.     objform_w = XmCreateFormDialog (toplevel_w, "Obj", args, n);
  455.  
  456.     /* set some stuff in the parent DialogShell.
  457.      * setting XmNdialogTitle in the Form didn't work..
  458.      */
  459.     n = 0;
  460.     XtSetArg (args[n], XmNtitle, "xephem ObjX/Y Menu"); n++;
  461.     XtSetValues (XtParent(objform_w), args, n);
  462.  
  463.     /* make the type control radio box in a frame.
  464.      * we save the widget ids so we can force the type to be what
  465.      * was selected from the database.
  466.      */
  467.  
  468.     n = 0;
  469.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  470.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  471.     typrbf_w = XmCreateFrame (objform_w, "TypeRBFrame", args, n);
  472.     XtManageChild (typrbf_w);
  473.  
  474.     n = 0;
  475.     XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
  476.     XtSetArg (args[n], XmNnumColumns, 2); n++;
  477.     typrb_w = XmCreateRadioBox (typrbf_w, "TypeRB", args, n);
  478.     XtManageChild (typrb_w);
  479.  
  480.         /* N.B. we assume the enum ObjType form indeces into typeinfo[] */
  481.         for (i = UNDEFOBJ; i < PLANET; i++) {
  482.         TypeInfo *tp = &typeinfo[i];
  483.         n = 0;
  484.         w= tp->tb_w = XmCreateToggleButton (typrb_w, tp->name, args, n);
  485.         XtAddCallback (w, XmNvalueChangedCallback, obj_type_cb,
  486.                                 (XtPointer)i);
  487.         XtManageChild (w);
  488.         }
  489.  
  490.     /* make the overall field id rc in a frame.
  491.      * the field id rc is just used as a manager to hold the several
  492.      *   various type rcs; only one is ever on at once.
  493.      */
  494.     n = 0;
  495.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  496.     XtSetArg (args[n], XmNtopWidget, typrbf_w); n++;
  497.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  498.     fldrcf_w = XmCreateFrame (objform_w, "FldFrame", args, n);
  499.     XtManageChild (fldrcf_w);
  500.  
  501.     n = 0;
  502.     fldrc_w = XmCreateRowColumn (fldrcf_w, "FldInfoRC", args, n);
  503.     XtManageChild (fldrc_w);
  504.  
  505.         /* make one row/col for each possible Obj type.
  506.          * they are managed later according to which type is displayed.
  507.          * N.B. we assume the enum ObjType form indeces into typeinfo[]
  508.          */
  509.         for (i = UNDEFOBJ; i < PLANET; i++) {
  510.         TypeInfo *tp = &typeinfo[i];
  511.         Field *fp;
  512.  
  513.         n = 0;
  514.         tp->frc_w = XmCreateRowColumn (fldrc_w, "TypeRC", args, n);
  515.  
  516.         for (fp = tp->fp; fp < tp->fp + tp->nfields; fp++) {
  517.             Widget fw;
  518.             n = 0;
  519.             fw = XmCreateForm (tp->frc_w, "ObjFldForm", args, n);
  520.             obj_create_type_rc_form (fw, fp);
  521.             XtManageChild (fw);
  522.         }
  523.         }
  524.  
  525.     /* make the x/y selection radio box in a frame */
  526.  
  527.     n = 0;
  528.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  529.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  530.     XtSetArg (args[n], XmNleftWidget, typrbf_w); n++;
  531.     XtSetArg (args[n], XmNorientation, XmVERTICAL); n++;
  532.     xyrbf_w = XmCreateFrame (objform_w, "XYRBF", args, n);
  533.     XtManageChild (xyrbf_w);
  534.  
  535.     n = 0;
  536.     xyrb_w = XmCreateRadioBox (xyrbf_w, "XYRBox", args, n);
  537.     XtManageChild (xyrb_w);
  538.  
  539.         n = 0;
  540.         XtSetArg (args[n], XmNset, True); n++; /* must match objidx init */
  541.         w = XmCreateToggleButton (xyrb_w, "ObjX", args, n);
  542.         XtAddCallback (w, XmNvalueChangedCallback, obj_xy_cb,
  543.                                 (XtPointer)OBJX);
  544.         XtManageChild (w);
  545.  
  546.         n = 0;
  547.         w = XmCreateToggleButton (xyrb_w, "ObjY", args, n);
  548.         XtAddCallback (w, XmNvalueChangedCallback, obj_xy_cb,
  549.                                 (XtPointer)OBJY);
  550.         XtManageChild (w);
  551.  
  552.     /* make a rc in a frame to hold the name buttons */
  553.  
  554.     n = 0;
  555.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  556.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  557.     XtSetArg (args[n], XmNleftWidget, xyrbf_w); n++;
  558.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  559.     XtSetArg (args[n], XmNrightOffset, SCROLLBAR_WIDTH); n++;
  560.     namercf_w = XmCreateFrame (objform_w, "NameF", args, n);
  561.     XtManageChild (namercf_w);
  562.  
  563.     n = 0;
  564.     namerc_w = XmCreateRowColumn (namercf_w, "NameRC", args, n);
  565.     XtManageChild (namerc_w);
  566.  
  567.         for (i = 0; i < NBTNS; i++) {
  568.         n = 0;
  569.         w = XmCreatePushButton (namerc_w, "NamePB", args, n);
  570.         XtAddCallback (w, XmNactivateCallback, obj_select_cb,
  571.                                 (XtPointer)i);
  572.         XtManageChild (w);
  573.         namepb_w[i] = w;
  574.         }
  575.  
  576.     /* make the scrollbar attached to the right edge */
  577.  
  578.     n = 0;
  579.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  580.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  581.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  582.     XtSetArg (args[n], XmNbottomWidget, namercf_w); n++;
  583.     XtSetArg (args[n], XmNpageIncrement, NBTNS-1); n++;
  584.     XtSetArg (args[n], XmNwidth, SCROLLBAR_WIDTH); n++;
  585.     scroll_w = XmCreateScrollBar (objform_w, "ScrollB", args, n);
  586.     XtAddCallback (scroll_w, XmNdragCallback, obj_scroll_cb, 0);
  587.     XtAddCallback (scroll_w, XmNvalueChangedCallback, obj_scroll_cb, 0);
  588.     XtManageChild (scroll_w);
  589.  
  590.     /* make a form in a frame to hold the bottom control buttons */
  591.  
  592.     n = 0;
  593.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  594.     XtSetArg (args[n], XmNtopWidget, namercf_w); n++;
  595.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  596.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  597.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  598.     ctlfr_w = XmCreateFrame (objform_w, "CtlFrame", args, n);
  599.     XtManageChild (ctlfr_w);
  600.  
  601.     n = 0;
  602.     XtSetArg (args[n], XmNfractionBase, 21); n++;
  603.     ctlf_w = XmCreateForm (ctlfr_w, "CtlForm", args, n);
  604.     XtManageChild (ctlf_w);
  605.  
  606.         /* make the control buttons */
  607.  
  608.         for (i = 0; i < XtNumber(ctlbtns); i++) {
  609.         n = 0;
  610.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  611.         XtSetArg (args[n], XmNtopOffset, 10); n++;
  612.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  613.         XtSetArg (args[n], XmNbottomOffset, 10); n++;
  614.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  615.         XtSetArg (args[n], XmNleftPosition, 1 + i*4); n++;
  616.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  617.         XtSetArg (args[n], XmNrightPosition, 4 + i*4); n++;
  618.         w = XmCreatePushButton (ctlf_w, ctlbtns[i].name, args, n);
  619.         XtAddCallback (w, XmNactivateCallback, obj_ctl_cb,
  620.                             (XtPointer)ctlbtns[i].id);
  621.         XtManageChild (w);
  622.         }
  623.  
  624.     /* make a form in a frame for the sky point/id buttons */
  625.  
  626.     n = 0;
  627.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  628.     XtSetArg (args[n], XmNbottomWidget, namercf_w); n++;
  629.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  630.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  631.     XtSetArg (args[n], XmNrightWidget, xyrbf_w); n++;
  632.     skyfr_w = XmCreateFrame (objform_w, "SkyFr", args, n);
  633.     XtManageChild (skyfr_w);
  634.  
  635.     n = 0;
  636.     XtSetArg (args[n], XmNfractionBase, 14); n++;
  637.     skyf_w = XmCreateForm (skyfr_w, "SkyF", args, n);
  638.     XtManageChild (skyf_w);
  639.  
  640.         for (i = 0; i < XtNumber(skybtns); i++) {
  641.         n = 0;
  642.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  643.         XtSetArg (args[n], XmNtopOffset, 10); n++;
  644.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  645.         XtSetArg (args[n], XmNbottomOffset, 10); n++;
  646.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  647.         XtSetArg (args[n], XmNleftPosition, 2 + i*6); n++;
  648.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  649.         XtSetArg (args[n], XmNrightPosition, 6 + i*6); n++;
  650.         w = XmCreatePushButton (skyf_w, skybtns[i].name, args, n);
  651.         XtAddCallback (w, XmNactivateCallback, obj_ctl_cb,
  652.                             (XtPointer)skybtns[i].id);
  653.         XtManageChild (w);
  654.         }
  655. }
  656.  
  657. /* given a Form widget and a Field, fill in the widgets in the Form.
  658.  */
  659. static void
  660. obj_create_type_rc_form (fw, fp)
  661. Widget fw;
  662. Field *fp;
  663. {
  664.     XmString str;
  665.     Widget w;
  666.     Arg args[20];
  667.     int n;
  668.  
  669.     /* create a pushbutton if this field can be changed, else a label */
  670.  
  671.     n = 0;
  672.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  673.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  674.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  675.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  676.     if (fp->prompt) {
  677.         w = XmCreatePushButton (fw, "ObjFldPB", args, n);
  678.         XtAddCallback (w, XmNactivateCallback, obj_change_cb,
  679.                                 (XtPointer)fp);
  680.     } else
  681.         w = XmCreateLabel (fw, "ObjFldInfo", args, n);
  682.     XtManageChild (w);
  683.     fp->pb_w = w;
  684.  
  685.     /* make the label to the left of w */
  686.  
  687.     str = XmStringCreate (fp->label, XmSTRING_DEFAULT_CHARSET);
  688.     n = 0;
  689.     XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
  690.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  691.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  692.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  693.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  694.     XtSetArg (args[n], XmNrightWidget, w); n++;
  695.     XtSetArg (args[n], XmNlabelString, str); n++;
  696.     w = XmCreateLabel (fw, "ObjFldLabel", args, n);
  697.     XtManageChild (w);
  698.     XmStringFree(str);
  699. }
  700.  
  701. /* callback from any of the obj field info buttons being activated.
  702.  * client is the Field pointer for this item.
  703.  * N.B. some fields' prompts are set from preferences.
  704.  */
  705. /* ARGSUSED */
  706. static void
  707. obj_change_cb (w, client, call)
  708. Widget w;
  709. XtPointer client;
  710. XtPointer call;
  711. {
  712.     Field *fp = (Field *)client;
  713.  
  714.     switch (fp->id) {
  715.     case F_EPOCH: 
  716.     case E_CEPOCH:
  717.     case E_EPOCH:
  718.     case H_EP:
  719.     case H_EPOCH:
  720.     case P_EP:
  721.     case P_EPOCH:
  722.         fp->prompt = fp->altp[pref_get(PREF_DATE_FORMAT)];
  723.         break;
  724.     }
  725.  
  726.     prompt (fp);
  727. }
  728.  
  729. /* callback from any of the botton control buttons.
  730.  * id is in client.
  731.  */
  732. /* ARGSUSED */
  733. static void
  734. obj_ctl_cb (w, client, call)
  735. Widget w;
  736. XtPointer client;
  737. XtPointer call;
  738. {
  739.     int id = (int) client;
  740.  
  741.     switch (id) {
  742.     case OK:
  743.         obj_set_db();
  744.         all_newobj(objidx);
  745.         XtUnmanageChild (objform_w);
  746.         break;
  747.     case APPLY:
  748.         obj_set_db();
  749.         all_newobj(objidx);
  750.         break;
  751.     case RESET:
  752.         obj_unsetmenu();
  753.         obj_set_from_db(db_basic(objidx));
  754.         obj_setmenu();
  755.         break;
  756.     case POINT:
  757.         if (objp->type != UNDEFOBJ) {
  758.         if (obj_cir (mm_get_now(), objp) < 0) {
  759.             printf ("obj_ctl_cb: can't get obj_cir for POINT\n");
  760.             exit (1);
  761.         }
  762.         sv_point (objp);
  763.         }
  764.         break;
  765.     case IDENT:
  766.         if (objp->type != UNDEFOBJ) {
  767.         if (obj_cir (mm_get_now(), objp) < 0) {
  768.             printf ("obj_ctl_cb: can't get obj_cir for IDENT\n");
  769.             exit (1);
  770.         }
  771.         switch (sv_id (objp)) {
  772.         case 0:
  773.             break;
  774.         case -1: xe_msg ("Object is below the horizon", 1);
  775.             break;
  776.         case -2: xe_msg ("Object is outside the fiew of view", 1);
  777.             break;
  778.         default:
  779.             printf ("bogus return from sv_id\n");
  780.             exit(1);
  781.         }
  782.         }
  783.         break;
  784.     case CANCEL:
  785.         XtUnmanageChild (objform_w);
  786.         break;
  787.     case HELP:
  788.         do_help();
  789.         break;
  790.     }
  791. }
  792.  
  793. static void
  794. do_help()
  795. {
  796.     static char *msg[] = {
  797. "Object X and Object Y may be set to any of four types of objects: fixed or in",
  798. "heliocentric elliptical, hyperbolic or parabolic orbits. Give the location or",
  799. "orbital elements as necessary.",
  800. "",
  801. "The object may also be loaded from the in-memory database. This database may",
  802. "be loaded from a file using the Database pulldown on the main menu.",
  803. };
  804.  
  805.     switch (objp->type) {
  806.     case FIXED:
  807.         hlp_dialog ("Fixed Object", msg, sizeof(msg)/sizeof(msg[0]));
  808.         break;
  809.     case ELLIPTICAL:
  810.         hlp_dialog ("Elliptical Object", msg, sizeof(msg)/sizeof(msg[0]));
  811.         break;
  812.     case HYPERBOLIC:
  813.         hlp_dialog ("Hyperbolic Object", msg, sizeof(msg)/sizeof(msg[0]));
  814.         break;
  815.     case PARABOLIC:
  816.         hlp_dialog ("Parabolic Object", msg, sizeof(msg)/sizeof(msg[0]));
  817.         break;
  818.     default:
  819.         hlp_dialog ("Object", msg, sizeof(msg)/sizeof(msg[0]));
  820.         break;
  821.     }
  822. }
  823.  
  824. /* callback for which object (x or y) toggle.
  825.  * client is either OBJX or OBJY.
  826.  */
  827. /* ARGSUSED */
  828. static void
  829. obj_xy_cb (w, client, call)
  830. Widget w;
  831. XtPointer client;
  832. XtPointer call;
  833. {
  834.     XmToggleButtonCallbackStruct *t = (XmToggleButtonCallbackStruct *) call;
  835.     int xy = (int)client;
  836.  
  837.     if (t->set && xy != objidx) {
  838.         obj_unsetmenu();
  839.         objidx = xy;
  840.         obj_setmenu();
  841.     }
  842. }
  843.  
  844. /* callback for what type of object toggles.
  845.  * client data is the Obj.type code.
  846.  */
  847. /* ARGSUSED */
  848. static void
  849. obj_type_cb (w, client, call)
  850. Widget w;
  851. XtPointer client;
  852. XtPointer call;
  853. {
  854.     XmToggleButtonCallbackStruct *t = (XmToggleButtonCallbackStruct *) call;
  855.     int type = (int)client;
  856.  
  857.     if (t->set && objp->type != type) {
  858.         obj_unsetmenu();
  859.         zero_mem ((char *)objp, sizeof(Obj));
  860.         objp->type = (Objtype_t) type;
  861.         obj_setmenu();
  862.     }
  863. }
  864.  
  865. /* callback when an item is selected from the list.
  866.  * client is the button number, userData is the namelist index.
  867.  */
  868. /* ARGSUSED */
  869. static void
  870. obj_select_cb (w, client, call)
  871. Widget w;
  872. XtPointer client;
  873. XtPointer call;
  874. {
  875.     static char me[] = "obj_select_cb()";
  876.     int nameidx;
  877.     Obj *op;
  878.  
  879.     get_something (w, XmNuserData, (char *)&nameidx);
  880.     if (nameidx < 0)
  881.         return;    /* marked as unused */
  882.     if (nameidx >= nnamelist) {
  883.         printf ("%s: nameidx=%d but nnamelist=%d\n", me, nameidx,
  884.                                 nnamelist);
  885.         exit (1);
  886.     }
  887.  
  888.     op = namelist[nameidx].op;
  889.     obj_unsetmenu();
  890.     obj_set_from_db(op);
  891.     obj_setmenu();
  892. }
  893.  
  894. /* callback when the scroll bar is moved.
  895.  * fill name buttons with next NB names starting with namelist[sp->value].
  896.  */
  897. /* ARGSUSED */
  898. static void
  899. obj_scroll_cb (w, client, call)
  900. Widget w;
  901. XtPointer client;
  902. XtPointer call;
  903. {
  904.     XmScrollBarCallbackStruct *sp = (XmScrollBarCallbackStruct *)call;
  905.     obj_setnames (sp->value);
  906. }
  907.  
  908. /* compare two NameList entries as required qsort(3).
  909.  * take care to sort numerics by value.
  910.  */
  911. static int
  912. nl_cmp (nl1, nl2)
  913. Const void *nl1, *nl2;
  914. {
  915.     char *s1 = ((NameList *)nl1)->name;
  916.     char *s2 = ((NameList *)nl2)->name;
  917.     int p;
  918.     int q;
  919.  
  920.     for (;;) {
  921.         p = *s1++;
  922.         q = *s2++;
  923.         if (isdigit(p) && isdigit(q)) {
  924.         int np = 0, nq = 0;
  925.         do {
  926.             np = np*10 + p - '0';
  927.             p = *s1;
  928.         } while (isdigit(p) && s1++);
  929.         do {
  930.             nq = nq*10 + q - '0';
  931.             q = *s2;
  932.         } while (isdigit(q) && s2++);
  933.         if (np != nq)
  934.             return (np - nq);
  935.         }
  936.         if (!p || !q || p != q)
  937.         return (p - q);
  938.     }
  939. }
  940.  
  941. /* set up namelist for a new list of db objects.
  942.  */
  943. static void
  944. new_namelist()
  945. {
  946.     Arg args[20];
  947.     int n;
  948.  
  949.     watch_cursor(1);
  950.  
  951.     load_namelist();
  952.  
  953.     if (nnamelist > 0) {
  954.         int slider = nnamelist < NBTNS ? nnamelist : NBTNS;
  955.         n = 0;
  956.         XtSetArg (args[n], XmNmaximum, nnamelist); n++;
  957.         XtSetArg (args[n], XmNsliderSize, slider); n++;
  958.         XtSetArg (args[n], XmNvalue, 0); n++;
  959.         XtSetValues (scroll_w, args, n);
  960.         XtManageChild(scroll_w);
  961.     } else
  962.         XtUnmanageChild(scroll_w);
  963.  
  964.     obj_setnames(0);
  965.  
  966.     watch_cursor(0);
  967. }
  968.  
  969. /* make the master list of db name objects in sorted order.
  970.  */
  971. static void
  972. load_namelist ()
  973. {
  974.     NameList *nlp;
  975.     Obj *op;
  976.     int nobj;
  977.  
  978.     if (namelist) {
  979.         XtFree ((char *)namelist);
  980.         namelist = NULL;
  981.         nnamelist = 0;
  982.     }
  983.  
  984.     nobj = db_n() - NOBJ;
  985.     if (nobj <= 0)
  986.         return;
  987.  
  988.     nlp = namelist = (NameList *) XtMalloc (nobj*sizeof(NameList));
  989.  
  990.     /* don't put any of the basic objects on the list */
  991.     for (op= db_next(NULL, OBJS_ALLBUT_BASIC); op;
  992.                     op= db_next(op, OBJS_ALLBUT_BASIC)) {
  993.         nlp->name = op->o_name;
  994.         nlp->op = op;
  995.         nlp++;
  996.     }
  997.  
  998.     nnamelist = nlp - namelist;
  999.  
  1000.     qsort ((char *)namelist, nnamelist, sizeof(NameList), nl_cmp);
  1001. }
  1002.  
  1003. /* fill the name buttons with the next NBTNS names starting at index nli 
  1004.  * within namelist[];
  1005.  */
  1006. static void
  1007. obj_setnames(nli)
  1008. int nli;
  1009. {
  1010.     XmString str;
  1011.     Arg args[20];
  1012.     char *namep;
  1013.     int bi;        /* namepb_w[] index */
  1014.     int nb;        /* number of good buttons to set */
  1015.  
  1016.     nb = (nnamelist - nli < NBTNS) ? nnamelist - nli : NBTNS;
  1017.     for (bi = 0; bi < NBTNS; bi++) {
  1018.         int n = 0;
  1019.         if (bi < nb) {
  1020.         namep = namelist[nli].name;
  1021.         XtSetArg (args[n], XmNuserData, nli); n++;
  1022.         obj_set_a_button(namepb_w[bi], 1);
  1023.         nli++;
  1024.         } else {
  1025.         namep = " ";
  1026.         XtSetArg (args[n], XmNuserData, -1); n++;
  1027.         obj_set_a_button(namepb_w[bi], 0);
  1028.         }
  1029.         str = XmStringCreate (namep, XmSTRING_DEFAULT_CHARSET);
  1030.         XtSetArg (args[n], XmNlabelString, str); n++;
  1031.         XtSetValues (namepb_w[bi], args, n);
  1032.         XmStringFree (str);
  1033.     }
  1034. }
  1035.  
  1036. /* set whether the given button looks like a label.
  1037.  */
  1038. static void
  1039. obj_set_a_button(pbw, whether)
  1040. Widget pbw;
  1041. int whether;
  1042. {
  1043.     static Arg look_like_button[] = {
  1044.         {XmNtopShadowColor, (XtArgVal) 0},
  1045.         {XmNbottomShadowColor, (XtArgVal) 0},
  1046.         {XmNfillOnArm, (XtArgVal) True},
  1047.     };
  1048.     static Arg look_like_label[] = {
  1049.         {XmNtopShadowColor, (XtArgVal) 0},
  1050.         {XmNbottomShadowColor, (XtArgVal) 0},
  1051.         {XmNfillOnArm, (XtArgVal) False},
  1052.     };
  1053.     static int called;
  1054.     Arg *ap;
  1055.     int na;
  1056.  
  1057.     if (!called) {
  1058.         /* get baseline label and shadow appearances.
  1059.          */
  1060.         Pixel topshad, botshad, bgcol;
  1061.         Arg args[20];
  1062.         Widget tmpw;
  1063.         int n;
  1064.  
  1065.         n = 0;
  1066.         tmpw = XmCreatePushButton (objform_w, "tmp", args, n);
  1067.  
  1068.         n = 0;
  1069.         XtSetArg (args[n], XmNtopShadowColor, &topshad); n++;
  1070.         XtSetArg (args[n], XmNbottomShadowColor, &botshad); n++;
  1071.         XtSetArg (args[n], XmNbackground, &bgcol); n++;
  1072.         XtGetValues (tmpw, args, n);
  1073.  
  1074.         look_like_button[0].value = topshad;
  1075.         look_like_button[1].value = botshad;
  1076.         look_like_label[0].value = bgcol;
  1077.         look_like_label[1].value = bgcol;
  1078.  
  1079.         XtDestroyWidget (tmpw);
  1080.          
  1081.         called = 1;
  1082.     }
  1083.  
  1084.     if (whether) {
  1085.         ap = look_like_button;
  1086.         na = XtNumber(look_like_button);
  1087.     } else {
  1088.         ap = look_like_label;
  1089.         na = XtNumber(look_like_label);
  1090.     }
  1091.  
  1092.     XtSetValues (pbw, ap, na);
  1093. }
  1094.  
  1095. /* user typed OK to a prompt for fp. get his new value and use it */
  1096. /* ARGSUSED */
  1097. static void
  1098. prompt_ok_cb (w, client, call)
  1099. Widget w;
  1100. XtPointer client;
  1101. XtPointer call;
  1102. {
  1103.     Field *fp = (Field *)client;
  1104.     char *text;
  1105.     
  1106.     get_xmstring(w, XmNtextString, &text);
  1107.     (void) db_set_field (text, fp->id,
  1108.                 (PrefDateFormat) pref_get(PREF_DATE_FORMAT), objp);
  1109.     obj_set_button (fp->pb_w, fp->id);
  1110.     XtDestroyWidget (w);
  1111.     XtFree (text);
  1112. }
  1113.  
  1114. /* put up a prompt dialog near the cursor to ask about fp.
  1115.  * make it app modal since we don't want the object type to change under us.
  1116.  */
  1117. static void
  1118. prompt (fp)
  1119. Field *fp;
  1120. {
  1121.     Widget w, dw;
  1122.     XmString str, title;
  1123.     Arg args[20];
  1124.     int n;
  1125.     
  1126.     str = XmStringCreate (fp->prompt, XmSTRING_DEFAULT_CHARSET);
  1127.     title = XmStringCreate("xephem Object Prompt",XmSTRING_DEFAULT_CHARSET);
  1128.     n = 0;
  1129.     XtSetArg(args[n], XmNselectionLabelString, str);  n++;
  1130.     XtSetArg(args[n], XmNdefaultPosition, False);  n++;
  1131.     XtSetArg(args[n], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL);  n++;
  1132.     XtSetArg(args[n], XmNdialogTitle, title);  n++;
  1133.     dw = XmCreatePromptDialog(toplevel_w, "ObjPrompt", args, n);
  1134.     XtAddCallback (dw, XmNmapCallback, prompt_map_cb, NULL);
  1135.     XmStringFree (str);
  1136.     XmStringFree (title);
  1137.  
  1138.     w = XmSelectionBoxGetChild (dw, XmDIALOG_HELP_BUTTON);
  1139.     XtUnmanageChild (w);
  1140.  
  1141.     XtAddCallback (dw, XmNokCallback, prompt_ok_cb, (XtPointer)fp);
  1142.     XtManageChild (dw);
  1143.  
  1144. #if XmVersion >= 1001
  1145.     w = XmSelectionBoxGetChild (dw, XmDIALOG_TEXT);
  1146.     XmProcessTraversal (w, XmTRAVERSE_CURRENT);
  1147.     XmProcessTraversal (w, XmTRAVERSE_CURRENT); /* yes, twice!! */
  1148. #endif
  1149. }
  1150.  
  1151. /* set the label for the given label widget according to the info in the
  1152.  * given field of the current working object.
  1153.  */
  1154. static void
  1155. obj_set_button (w, id)
  1156. Widget w;
  1157. int id;
  1158. {
  1159.     static char me[] = "obj_set_button";
  1160.  
  1161.     switch (id) {
  1162.     case O_NAME:
  1163.         f_string (w, objp->o_name);
  1164.         break;
  1165.     case F_CLASS:
  1166.         f_string (w, obj_description(objp));
  1167.         break;
  1168.     case F_RA:
  1169.         f_ra (w, objp->f_RA);
  1170.         break;
  1171.     case F_DEC:
  1172.         f_gangle (w, objp->f_dec);
  1173.         break;
  1174.     case F_MAG:
  1175.         f_double (w, "%g", objp->f_mag/MAGSCALE);
  1176.         break;
  1177.     case F_EPOCH:
  1178.         epoch_as_decimal (w, objp->f_epoch);
  1179.         break;
  1180.     case F_SIZE:
  1181.         f_double (w, "%g", (double)objp->f_size);
  1182.         break;
  1183.  
  1184.     case E_INC:
  1185.         f_double (w, "%g", objp->e_inc);
  1186.         break;
  1187.     case E_LAN:
  1188.         f_double (w, "%g", objp->e_Om);
  1189.         break;
  1190.     case E_AOP:
  1191.         f_double (w, "%g", objp->e_om);
  1192.         break;
  1193.     case E_A:
  1194.         f_double (w, "%g", objp->e_a);
  1195.         break;
  1196.     case E_N:
  1197.         f_double (w, "%g", objp->e_n);
  1198.         break;
  1199.     case E_E:
  1200.         f_double (w, "%g", objp->e_e);
  1201.         break;
  1202.     case E_M:
  1203.         f_double (w, "%g", objp->e_M);
  1204.         break;
  1205.     case E_CEPOCH:
  1206.         epoch_as_mdy (w, objp->e_cepoch);
  1207.         break;
  1208.     case E_EPOCH:
  1209.         epoch_as_decimal (w, objp->e_epoch);
  1210.         break;
  1211.     case E_M1: {
  1212.         char buf[64];
  1213.         (void) sprintf (buf, "%c%g",
  1214.                 objp->e_mag.whichm == MAG_HG ? 'H' : 'g',
  1215.                 objp->e_mag.m1);
  1216.         f_string (w, buf);
  1217.         break;
  1218.     }
  1219.     case E_M2: {
  1220.         char buf[64];
  1221.         (void) sprintf (buf, "%c%g",
  1222.                 objp->e_mag.whichm == MAG_HG ? 'G' : 'k',
  1223.                 objp->e_mag.m2);
  1224.         f_string (w, buf);
  1225.         break;
  1226.     }
  1227.     case E_SIZE:
  1228.         f_double (w, "%g", objp->e_size);
  1229.         break;
  1230.  
  1231.     case H_EP:
  1232.         epoch_as_mdy (w, objp->h_ep);
  1233.         break;
  1234.     case H_INC:
  1235.         f_double (w, "%g", objp->h_inc);
  1236.         break;
  1237.     case H_LAN:
  1238.         f_double (w, "%g", objp->h_Om);
  1239.         break;
  1240.     case H_AOP:
  1241.         f_double (w, "%g", objp->h_om);
  1242.         break;
  1243.     case H_E:
  1244.         f_double (w, "%g", objp->h_e);
  1245.         break;
  1246.     case H_QP:
  1247.         f_double (w, "%g", objp->h_qp);
  1248.         break;
  1249.     case H_EPOCH:
  1250.         epoch_as_decimal (w, objp->h_epoch);
  1251.         break;
  1252.     case H_G:
  1253.         f_double (w, "%g", objp->h_g);
  1254.         break;
  1255.     case H_K:
  1256.         f_double (w, "%g", objp->h_k);
  1257.         break;
  1258.     case H_SIZE:
  1259.         f_double (w, "%g", objp->h_size);
  1260.         break;
  1261.  
  1262.     case P_EP:
  1263.         epoch_as_mdy (w, objp->p_ep);
  1264.         break;
  1265.     case P_INC:
  1266.         f_double (w, "%g", objp->p_inc);
  1267.         break;
  1268.     case P_AOP:
  1269.         f_double (w, "%g", objp->p_om);
  1270.         break;
  1271.     case P_QP:
  1272.         f_double (w, "%g", objp->p_qp);
  1273.         break;
  1274.     case P_LAN:
  1275.         f_double (w, "%g", objp->p_Om);
  1276.         break;
  1277.     case P_EPOCH:
  1278.         epoch_as_decimal (w, objp->p_epoch);
  1279.         break;
  1280.     case P_G:
  1281.         f_double (w, "%g", objp->p_g);
  1282.         break;
  1283.     case P_K:
  1284.         f_double (w, "%g", objp->p_k);
  1285.         break;
  1286.     case P_SIZE:
  1287.         f_double (w, "%g", objp->p_size);
  1288.         break;
  1289.     default:
  1290.         printf ("%s: bad parabolic id: %d\n", me, id);
  1291.         exit (1);
  1292.     }
  1293. }
  1294.  
  1295. static void
  1296. epoch_as_decimal (w, e)
  1297. Widget w;
  1298. double e;
  1299. {
  1300.     double y;
  1301.     mjd_year (e, &y);
  1302.     f_double (w, "%g", y);
  1303. }
  1304.  
  1305. static void
  1306. epoch_as_mdy (w, e)
  1307. Widget w;
  1308. double e;
  1309. {
  1310.     char buf[100];
  1311.  
  1312.     fs_date (buf, e);
  1313.     f_string (w, buf);
  1314. }
  1315.