mirror of https://github.com/XEphem/XEphem.git
1542 lines
42 KiB
C
1542 lines
42 KiB
C
/* handle the list feature of skyview */
|
|
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/Form.h>
|
|
#include <Xm/Frame.h>
|
|
#include <Xm/Label.h>
|
|
#include <Xm/RowColumn.h>
|
|
#include <Xm/Separator.h>
|
|
#include <Xm/Scale.h>
|
|
#include <Xm/SelectioB.h>
|
|
#include <Xm/TextF.h>
|
|
#include <Xm/Text.h>
|
|
#include <Xm/ToggleB.h>
|
|
#include <Xm/PushB.h>
|
|
|
|
#include "xephem.h"
|
|
|
|
static void sl_create_list_w (void);
|
|
static void sl_create_pu (void);
|
|
static void sl_cr_sorttable (Widget f_w);
|
|
static void sl_toggle_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void sl_save_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void sl_clear_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void sl_undo_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void sl_so_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void sl_sort_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void sl_close_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void sl_help_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void slpu_mark_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void slpu_del_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void sl_info_eh (Widget w, XtPointer client, XEvent *ev,
|
|
Boolean *continue_to_dispatch);
|
|
static void sl_append_qcb (void);
|
|
static void sl_write_qcb (void);
|
|
static void sl_sort (void);
|
|
static void sl_colhdr (char *txt);
|
|
static int sort_name (const void *v1, const void *v2);
|
|
static int sort_size (const void *v1, const void *v2);
|
|
static int sort_spect (const void *v1, const void *v2);
|
|
static int sort_ura (const void *v1, const void *v2);
|
|
static int sort_u2k (const void *v1, const void *v2);
|
|
static int sort_msa (const void *v1, const void *v2);
|
|
static int sort_airmass (const void *v1, const void *v2);
|
|
static int sort_desc (const void *v1, const void *v2);
|
|
static int sort_ha (const void *v1, const void *v2);
|
|
static int sort_edist (const void *v1, const void *v2);
|
|
static int sort_sdist (const void *v1, const void *v2);
|
|
static int sort_ra (const void *v1, const void *v2);
|
|
static int sort_dec (const void *v1, const void *v2);
|
|
static int sort_alt (const void *v1, const void *v2);
|
|
static int sort_az (const void *v1, const void *v2);
|
|
static int sort_settm (const void *v1, const void *v2);
|
|
static int sort_setaz (const void *v1, const void *v2);
|
|
static int sort_risetm (const void *v1, const void *v2);
|
|
static int sort_riseaz (const void *v1, const void *v2);
|
|
static int sort_trantm (const void *v1, const void *v2);
|
|
static int sort_tranalt (const void *v1, const void *v2);
|
|
static int sort_elong (const void *v1, const void *v2);
|
|
static int sort_mag (const void *v1, const void *v2);
|
|
static int sort_cns (const void *v1, const void *v2);
|
|
static int sort_glat (const void *v1, const void *v2);
|
|
static int sort_glng (const void *v1, const void *v2);
|
|
static int sort_hlat (const void *v1, const void *v2);
|
|
static int sort_hlng (const void *v1, const void *v2);
|
|
static int sort_eclat (const void *v1, const void *v2);
|
|
static int sort_eclng (const void *v1, const void *v2);
|
|
static int sort_z (const void *v1, const void *v2);
|
|
static int sort_sep (const void *v1, const void *v2);
|
|
|
|
static Widget list_w; /* object list dialog */
|
|
static Widget txttb_w; /* text-format TB */
|
|
static Widget txtfn_w; /* text-format file name */
|
|
static Widget edbtb_w; /* edb-format TB */
|
|
static Widget edbfn_w; /* edb-format file name */
|
|
static Widget nl_w; /* count label */
|
|
static Widget clpb_w; /* Clear PB */
|
|
static Widget undo_w; /* Undo PB */
|
|
static Widget listt_w; /* text for showing list */
|
|
static Widget hdrtf_w; /* text field for showing column headings */
|
|
|
|
#define LSTINDENT 20 /* list item indent, pixels */
|
|
#define ATLASLEN 30 /* room for atlas info */
|
|
|
|
/* all info about one object, including some things not in an Obj */
|
|
typedef struct {
|
|
Obj *op; /* Obj */
|
|
RiseSet rs; /* rise/set info */
|
|
double glat, glng; /* galactic lat/long */
|
|
double eclat, eclng; /* ecliptic lat/long */
|
|
double ha; /* hour angle */
|
|
double Z; /* airmass */
|
|
char *cns; /* constellation name */
|
|
char *desc; /* description */
|
|
char ura[ATLASLEN]; /* Uranometria page number */
|
|
char u2k[ATLASLEN]; /* Uranometria 200 page number */
|
|
char msa[ATLASLEN]; /* Millenium Star Atlas page number */
|
|
} ObjInfo;
|
|
|
|
/* handy "no rise/set" test */
|
|
#define NORS (RS_ERROR|RS_CIRCUMPOLAR|RS_NEVERUP)
|
|
|
|
/* info about each sort field */
|
|
typedef struct {
|
|
char *lname; /* label widget instance name */
|
|
char *title; /* sort description */
|
|
int (*cmp_f)(); /* qsort-style compare function */
|
|
Widget lw; /* sort-order label widget */
|
|
Widget pw; /* sort-order pushb widget */
|
|
} SortInfo;
|
|
static SortInfo sinfo[] = {
|
|
{"Name", "Name", sort_name},
|
|
{"Type", "Type", sort_desc},
|
|
{"Cns", "Constellation", sort_cns},
|
|
{"RA", "Right Asc", sort_ra},
|
|
{"HA", "Hour angle", sort_ha},
|
|
{"Dec", "Declination", sort_dec},
|
|
{"Az", "Azimuth", sort_az},
|
|
{"Alt", "Altitude", sort_alt},
|
|
{"Zenith", "Zenith", sort_z},
|
|
{"Air", "Air mass", sort_airmass},
|
|
{"Spect", "Spect class", sort_spect},
|
|
|
|
{"Size", "Size", sort_size},
|
|
{"Mag", "Magnitude", sort_mag},
|
|
{"Elong", "Elongation", sort_elong},
|
|
{"HLat", "Helio lat", sort_hlat},
|
|
{"HLong", "Helio long", sort_hlng},
|
|
{"GLat", "Galactic lat", sort_glat},
|
|
{"GLong", "Galactic long", sort_glng},
|
|
{"EcLat", "Ecliptic lat", sort_eclat},
|
|
{"EcLong", "Ecliptic long", sort_eclng},
|
|
{"EaDst", "Earth dist", sort_edist},
|
|
{"SnDst", "Sun dist", sort_sdist},
|
|
|
|
{"Urano", "Uranometria", sort_ura},
|
|
{"Uran2k", "Uranom 2000", sort_u2k},
|
|
{"MillSA", "Millenium", sort_msa},
|
|
{"RisTm", "Rise time", sort_risetm},
|
|
{"RisAz", "Rise azimuth", sort_riseaz},
|
|
{"TrnTm", "Transit time", sort_trantm},
|
|
{"TrnAlt", "Transit alt", sort_tranalt},
|
|
{"SetTm", "Set time", sort_settm},
|
|
{"SetAz", "Set azimuth", sort_setaz},
|
|
{"Sep", "Separation", sort_sep},
|
|
};
|
|
#define NSINFO XtNumber(sinfo)
|
|
#define NTCOLS 4 /* desired number of columns for table */
|
|
#define NTROWS ((NSINFO-1)/NTCOLS+1)
|
|
#define LBLPC 25 /* % of each cell for sort-order label */
|
|
|
|
/* popup for more info on a given line */
|
|
typedef struct {
|
|
Widget pu_w; /* popup */
|
|
Widget name_w; /* name label */
|
|
int linepos; /* index into listt_w text at BOL */
|
|
Obj *op; /* named object */
|
|
} PopupInfo;
|
|
static PopupInfo pu;
|
|
|
|
/* pointers into sinfo[] in order of sort */
|
|
static SortInfo *sortorder[NSINFO];
|
|
static int nsortorder; /* number in use */
|
|
|
|
static char skylcategory[] = "Sky View -- List";
|
|
|
|
void
|
|
sl_manage()
|
|
{
|
|
if (!list_w) {
|
|
sl_create_list_w();
|
|
sl_create_pu();
|
|
}
|
|
XtManageChild (list_w);
|
|
}
|
|
|
|
void
|
|
sl_unmanage()
|
|
{
|
|
if (list_w)
|
|
XtUnmanageChild (list_w);
|
|
}
|
|
|
|
/* called to put up or remove the watch cursor. */
|
|
void
|
|
sl_cursor (c)
|
|
Cursor c;
|
|
{
|
|
Window win;
|
|
|
|
if (list_w && (win = XtWindow(list_w)) != 0) {
|
|
Display *dsp = XtDisplay(list_w);
|
|
if (c)
|
|
XDefineCursor (dsp, win, c);
|
|
else
|
|
XUndefineCursor (dsp, win);
|
|
}
|
|
}
|
|
|
|
/* create the list filename prompt */
|
|
static void
|
|
sl_create_list_w()
|
|
{
|
|
Widget dspb_w, lbl_w, tbl_w;
|
|
Widget w;
|
|
Arg args[20];
|
|
int n;
|
|
|
|
/* create form */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNallowShellResize, False); n++;
|
|
XtSetArg (args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
|
|
XtSetArg (args[n], XmNautoUnmanage, False); n++;
|
|
XtSetArg (args[n], XmNcolormap, xe_cm); n++;
|
|
XtSetArg (args[n], XmNhorizontalSpacing, 10); n++;
|
|
XtSetArg (args[n], XmNverticalSpacing, 10); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 10); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 10); n++;
|
|
XtSetArg (args[n], XmNfractionBase, 13); n++;
|
|
XtSetArg (args[n], XmNdefaultPosition, False); n++;
|
|
list_w = XmCreateFormDialog (svshell_w, "SkyList", args, n);
|
|
set_something (list_w, XmNcolormap, (XtArgVal)xe_cm);
|
|
XtAddCallback (list_w, XmNhelpCallback, sl_help_cb, 0);
|
|
sr_reg (XtParent(list_w), "XEphem*SkyList.x", skylcategory, 0);
|
|
sr_reg (XtParent(list_w), "XEphem*SkyList.y", skylcategory, 0);
|
|
|
|
/* set some stuff in the parent DialogShell.
|
|
* setting XmNdialogTitle in the Form didn't work..
|
|
*/
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtitle, "Sky list"); n++;
|
|
XtSetValues (XtParent(list_w), args, n);
|
|
|
|
/* title */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNalignment, XmALIGNMENT_CENTER); n++;
|
|
lbl_w = XmCreateLabel (list_w, "TTB", args, n);
|
|
set_xmstring (lbl_w, XmNlabelString,
|
|
"List, Sort and Save current Sky View objects");
|
|
XtManageChild (lbl_w);
|
|
|
|
/* format options */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, lbl_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
|
|
lbl_w = XmCreateLabel (list_w, "FFL", args, n);
|
|
set_xmstring (lbl_w, XmNlabelString,
|
|
"Choose format and set file name for Save:");
|
|
XtManageChild (lbl_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, lbl_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftOffset, LSTINDENT); n++;
|
|
XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 4); n++;
|
|
XtSetArg (args[n], XmNspacing, 4); n++;
|
|
edbtb_w = XmCreateToggleButton (list_w, "EDB", args, n);
|
|
set_xmstring (edbtb_w, XmNlabelString, ".edb:");
|
|
XtManageChild (edbtb_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, lbl_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, edbtb_w); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
edbfn_w = XmCreateTextField (list_w, "EdbFilename", args, n);
|
|
defaultTextFN (edbfn_w, 1, "skylist.edb", NULL);
|
|
wtip (edbfn_w, "Name of .edb file to create");
|
|
XtManageChild (edbfn_w);
|
|
sr_reg (edbfn_w, NULL, skylcategory, 1);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, edbfn_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftOffset, LSTINDENT); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 4); n++;
|
|
XtSetArg (args[n], XmNspacing, 4); n++;
|
|
XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
|
|
txttb_w = XmCreateToggleButton (list_w, "Text", args, n);
|
|
set_xmstring (txttb_w, XmNlabelString, "Text:");
|
|
XtManageChild (txttb_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, edbfn_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, txttb_w); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
txtfn_w = XmCreateTextField (list_w, "TextFilename", args, n);
|
|
defaultTextFN (txtfn_w, 1, "skylist.txt", NULL);
|
|
wtip (txtfn_w, "Name of text file to create");
|
|
XtManageChild (txtfn_w);
|
|
sr_reg (txtfn_w, NULL, skylcategory, 1);
|
|
|
|
/* implement txt/edb as a radio pair */
|
|
if (XmToggleButtonGetState(txttb_w) == XmToggleButtonGetState(edbtb_w)){
|
|
XmToggleButtonSetState(txttb_w, True, 0);
|
|
XmToggleButtonSetState(edbtb_w, False, 0);
|
|
}
|
|
XtAddCallback (txttb_w, XmNvalueChangedCallback, sl_toggle_cb,
|
|
(XtPointer)edbtb_w);
|
|
XtAddCallback (edbtb_w, XmNvalueChangedCallback, sl_toggle_cb,
|
|
(XtPointer)txttb_w);
|
|
|
|
sr_reg (txttb_w, NULL, skylcategory, 1);
|
|
|
|
/* sort options heading */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, txtfn_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
lbl_w = XmCreateLabel (list_w, "STB", args, n);
|
|
set_xmstring (lbl_w, XmNlabelString,
|
|
"Pick sort keys in desired order:");
|
|
XtManageChild (lbl_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, txtfn_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, lbl_w); n++;
|
|
XtSetArg (args[n], XmNleftOffset, 10); n++;
|
|
XtSetArg (args[n], XmNsensitive, False); n++;
|
|
clpb_w = XmCreatePushButton (list_w, "Clear", args, n);
|
|
XtAddCallback (clpb_w, XmNactivateCallback, sl_clear_cb, NULL);
|
|
wtip (clpb_w, "Start key selection over");
|
|
XtManageChild (clpb_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, txtfn_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, clpb_w); n++;
|
|
XtSetArg (args[n], XmNleftOffset, 10); n++;
|
|
XtSetArg (args[n], XmNsensitive, False); n++;
|
|
undo_w = XmCreatePushButton (list_w, "Undo", args, n);
|
|
XtAddCallback (undo_w, XmNactivateCallback, sl_undo_cb, NULL);
|
|
wtip (undo_w, "Undo last key pick");
|
|
XtManageChild (undo_w);
|
|
|
|
/* sort option table */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, undo_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
tbl_w = XmCreateForm (list_w, "SortTable", args, n);
|
|
XtManageChild (tbl_w);
|
|
|
|
sl_cr_sorttable(tbl_w);
|
|
|
|
/* bottom controls */
|
|
|
|
n = 0;
|
|
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, 3); n++;
|
|
w = XmCreatePushButton (list_w, "Save", args, n);
|
|
XtAddCallback (w, XmNactivateCallback, sl_save_cb, NULL);
|
|
wtip (w, "Write the file chosen above");
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 4); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 6); n++;
|
|
w = XmCreatePushButton (list_w, "Sort", args, n);
|
|
XtAddCallback (w, XmNactivateCallback, sl_sort_cb, NULL);
|
|
wtip (w, "Rebuild the list with new settings");
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 7); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 9); n++;
|
|
w = XmCreatePushButton (list_w, "Close", args, n);
|
|
XtAddCallback (w, XmNactivateCallback, sl_close_cb, NULL);
|
|
wtip (w, "Close this window");
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 10); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 12); n++;
|
|
w = XmCreatePushButton (list_w, "Help", args, n);
|
|
XtAddCallback (w, XmNactivateCallback, sl_help_cb, NULL);
|
|
wtip (w, "Get more info");
|
|
XtManageChild (w);
|
|
|
|
/* scrolled text in between, beneath title and column headings */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, tbl_w); n++;
|
|
XtSetArg (args[n], XmNtopOffset, 12); n++; /* lazy: nudge for PB */
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
nl_w = XmCreateLabel (list_w, "STB", args, n);
|
|
set_xmstring (nl_w, XmNlabelString,
|
|
"List: 0 objects. Set columns with");
|
|
XtManageChild (nl_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, tbl_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, nl_w); n++;
|
|
XtSetArg (args[n], XmNleftOffset, 4); n++;
|
|
dspb_w = XmCreatePushButton (list_w, "STB", args, n);
|
|
XtAddCallback (dspb_w, XmNactivateCallback, dm_setup_cb, NULL);
|
|
wtip (dspb_w,"Bring up Data Table setup window to change list columns");
|
|
set_xmstring (dspb_w, XmNlabelString, "Data Table setup...");
|
|
XtManageChild (dspb_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, dspb_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftOffset, 12); n++; /* lazy: margin + shadow */
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNshadowThickness, 0); n++;
|
|
XtSetArg (args[n], XmNeditable, False); n++;
|
|
XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 0); n++;
|
|
hdrtf_w = XmCreateTextField (list_w, "HdrTF", args, n);
|
|
XtManageChild (hdrtf_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, hdrtf_w); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNbottomWidget, w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
|
|
XtSetArg (args[n], XmNeditable, True); n++;
|
|
listt_w = XmCreateScrolledText (list_w, "List", args, n);
|
|
XtAddEventHandler (listt_w, ButtonPressMask, False, sl_info_eh, 0);
|
|
sr_reg (listt_w, "XEphem*SkyList*List.rows", skylcategory, 0);
|
|
XtManageChild (listt_w);
|
|
}
|
|
|
|
/* create the popup skeleton */
|
|
static void
|
|
sl_create_pu()
|
|
{
|
|
Widget w;
|
|
Arg args[20];
|
|
int n;
|
|
|
|
/* make the popup shell */
|
|
n = 0;
|
|
XtSetArg (args[n], XmNisAligned, True); n++;
|
|
XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
|
|
pu.pu_w = XmCreatePopupMenu (listt_w, "SLPopup", args, n);
|
|
|
|
/* add the name, separator and controls.
|
|
* we always wants these so manage them now.
|
|
*/
|
|
pu.name_w = XmCreateLabel (pu.pu_w, "SLLab", args, 0);
|
|
XtManageChild (pu.name_w);
|
|
w = XmCreateSeparator (pu.pu_w, "SLSep", args, 0);
|
|
XtManageChild (w);
|
|
w = XmCreatePushButton (pu.pu_w, "Sky Mark", args, 0);
|
|
XtAddCallback (w, XmNactivateCallback, slpu_mark_cb, 0);
|
|
XtManageChild (w);
|
|
wtip (w, "Mark this object on the Sky View");
|
|
w = XmCreatePushButton (pu.pu_w, "Delete", args, 0);
|
|
XtAddCallback (w, XmNactivateCallback, slpu_del_cb, 0);
|
|
XtManageChild (w);
|
|
wtip (w, "Delete this object from the list");
|
|
}
|
|
|
|
/* build the sort table in the given XmForm */
|
|
static void
|
|
sl_cr_sorttable(f_w)
|
|
Widget f_w;
|
|
{
|
|
Arg args[20];
|
|
Widget fr_w;
|
|
Widget w;
|
|
int n;
|
|
int i;
|
|
|
|
/* build in column-major order */
|
|
for (i = 0; i < NSINFO; i++) {
|
|
SortInfo *sip = &sinfo[i];
|
|
int r = i%NTROWS; /* row 0..(NTROWS-1)*/
|
|
int c = i/NTROWS; /* col 0..(NTCOLS-1)*/
|
|
int t = 100*r/NTROWS; /* top % */
|
|
int b = 100*(r+1)/NTROWS; /* bottom % */
|
|
int l = 100*c/NTCOLS; /* left % */
|
|
int h = 100*(c+1)/NTCOLS; /* right % */
|
|
int p = l + LBLPC/NTCOLS; /* left pushb % */
|
|
|
|
/* label to display sort position */
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNtopPosition, t); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNbottomPosition, b); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, l); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, p); n++;
|
|
XtSetArg (args[n], XmNshadowThickness, 2); n++;
|
|
XtSetArg (args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
|
|
fr_w = XmCreateFrame (f_w, "STFr", args, n);
|
|
XtManageChild (fr_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
|
|
w = XmCreateLabel (fr_w, sip->lname, args, n);
|
|
XtManageChild (w);
|
|
set_xmstring (w, XmNlabelString, " ");
|
|
sip->lw = w;
|
|
|
|
/* push button to define sort position */
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNtopPosition, t); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNbottomPosition, b); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, p); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, h); n++;
|
|
w = XmCreatePushButton (f_w, "STPB", args, n);
|
|
XtAddCallback (w, XmNactivateCallback, sl_so_cb,
|
|
(XtPointer)&sinfo[i]);
|
|
XtManageChild (w);
|
|
set_xmstring (w, XmNlabelString, sip->title);
|
|
sip->pw = w;
|
|
}
|
|
}
|
|
|
|
/* called from either file format TB to implement a radio pair.
|
|
* client is the opposite TB.
|
|
*/
|
|
/* ARGSUSED */
|
|
static void
|
|
sl_toggle_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
int set = XmToggleButtonGetState(w);
|
|
Widget otherw = (Widget)client;
|
|
|
|
XmToggleButtonSetState (otherw, !set, 0);
|
|
}
|
|
|
|
/* called when the Close button is hit in the file list prompt */
|
|
/* ARGSUSED */
|
|
static void
|
|
sl_close_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
XtUnmanageChild (list_w);
|
|
}
|
|
|
|
/* called when the help button is hit in the file list prompt */
|
|
/* ARGSUSED */
|
|
static void
|
|
sl_help_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
static char *msg[] = {
|
|
"List and Save Sky View objects in two formats."
|
|
};
|
|
|
|
hlp_dialog ("SkyView_list", msg, sizeof(msg)/sizeof(msg[0]));
|
|
|
|
}
|
|
|
|
/* clear most recent entry from sortorder[].
|
|
* if last, desensitize Clear and Undo.
|
|
* N.B. desensitizing is key because there is NO OVER or UNDERFLOW checking.
|
|
*/
|
|
static void
|
|
sl_clearlast()
|
|
{
|
|
SortInfo *sip;
|
|
|
|
/* clear last */
|
|
sip = sortorder[--nsortorder];
|
|
set_xmstring (sip->lw, XmNlabelString, " ");
|
|
XtSetSensitive (sip->pw, True);
|
|
|
|
/* if none left, can not clear/undo now */
|
|
if (!nsortorder) {
|
|
XtSetSensitive (clpb_w, False);
|
|
XtSetSensitive (undo_w, False);
|
|
}
|
|
}
|
|
|
|
/* called when the Clear button is hit */
|
|
/* ARGSUSED */
|
|
static void
|
|
sl_clear_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
/* clear all */
|
|
while (nsortorder)
|
|
sl_clearlast();
|
|
}
|
|
|
|
/* called when the Undo button is hit */
|
|
/* ARGSUSED */
|
|
static void
|
|
sl_undo_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
sl_clearlast();
|
|
}
|
|
|
|
/* called when any sort-order table button is hit.
|
|
* client is pointer into sinfo[]
|
|
*/
|
|
/* ARGSUSED */
|
|
static void
|
|
sl_so_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
SortInfo *sip = (SortInfo *)client;
|
|
char buf[10];
|
|
|
|
/* add this function next in sortforder list */
|
|
sortorder[nsortorder++] = sip;
|
|
|
|
/* indicate order */
|
|
sprintf (buf, "%d", nsortorder);
|
|
set_xmstring (sip->lw, XmNlabelString, buf);
|
|
|
|
/* can't use this again */
|
|
XtSetSensitive (sip->pw, False);
|
|
|
|
/* ok to clear and undo now */
|
|
XtSetSensitive (clpb_w, True);
|
|
XtSetSensitive (undo_w, True);
|
|
}
|
|
|
|
/* called when the Sort button is hit */
|
|
/* ARGSUSED */
|
|
static void
|
|
sl_sort_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
sl_sort();
|
|
}
|
|
|
|
/* called when the Save button is hit */
|
|
/* ARGSUSED */
|
|
static void
|
|
sl_save_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
char *fn;
|
|
|
|
/* get and sanity-check the appropriate file name */
|
|
if (XmToggleButtonGetState(txttb_w)) {
|
|
fn = XmTextFieldGetString (txtfn_w);
|
|
if (strlen(fn) == 0) {
|
|
xe_msg (1, "Please enter a text file name.");
|
|
XtFree (fn);
|
|
return;
|
|
}
|
|
} else {
|
|
fn = XmTextFieldGetString (edbfn_w);
|
|
if (strlen(fn) == 0) {
|
|
xe_msg (1, "Please enter an .edb file name.");
|
|
XtFree (fn);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* go, perhaps cautiously */
|
|
if (existd (fn,NULL) == 0 && confirm()) {
|
|
char buf[1024];
|
|
(void) sprintf (buf, "%s exists:\nAppend or Overwrite?", fn);
|
|
query (list_w, buf, "Append", "Overwrite", "Cancel",
|
|
sl_append_qcb, sl_write_qcb, NULL);
|
|
} else
|
|
sl_write_qcb(); /* just hammer it */
|
|
|
|
/* done with name */
|
|
XtFree (fn);
|
|
}
|
|
|
|
/* called when the Mark button is hit on the popup */
|
|
/* ARGSUSED */
|
|
static void
|
|
slpu_mark_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
/* sanity check */
|
|
if (!pu.op)
|
|
return;
|
|
|
|
sv_point (pu.op);
|
|
}
|
|
|
|
/* called when the Delete button is hit on the popup */
|
|
/* ARGSUSED */
|
|
static void
|
|
slpu_del_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
char *txt;
|
|
int end;
|
|
|
|
/* sanity check */
|
|
if (!pu.op)
|
|
return;
|
|
|
|
/* get text */
|
|
txt = XmTextGetString (listt_w);
|
|
|
|
/* delete from pu.linepos to next nl or EOS */
|
|
for (end = pu.linepos; txt[end] && txt[end] != '\n'; end++)
|
|
continue;
|
|
if (txt[end] == '\n')
|
|
end++;
|
|
XmTextReplace (listt_w, pu.linepos, end, "");
|
|
XmTextShowPosition (listt_w, pu.linepos);
|
|
|
|
XtFree (txt);
|
|
}
|
|
|
|
/* extra ButtonPress handler added to scrolled text.
|
|
* used to provide few more options based on text under pointer.
|
|
*/
|
|
static void
|
|
sl_info_eh (w, client, ev, continue_to_dispatch)
|
|
Widget w;
|
|
XtPointer client;
|
|
XEvent *ev;
|
|
Boolean *continue_to_dispatch;
|
|
{
|
|
char objname[MAXNM];
|
|
DBScan dbs;
|
|
ObjF *fs;
|
|
Obj *op;
|
|
int nfs;
|
|
char *txt;
|
|
int pos;
|
|
int i;
|
|
|
|
/* only care about button3 press */
|
|
if (!(ev->type == ButtonPress && ev->xbutton.button == Button3))
|
|
return;
|
|
|
|
/* where are we? */
|
|
pos = XmTextXYToPos (w, ev->xbutton.x, ev->xbutton.y);
|
|
if (pos < 0)
|
|
return;
|
|
|
|
/* find name at beginning of this line */
|
|
txt = XmTextGetString (w);
|
|
for (; pos > 0; --pos) {
|
|
if (txt[pos] == '\n') {
|
|
pos++;
|
|
break;
|
|
}
|
|
}
|
|
i = sprintf (objname, "%*.*s", MAXNM-1, MAXNM-1, &txt[pos]);
|
|
|
|
/* finished with txt now */
|
|
XtFree (txt);
|
|
|
|
/* dig out pure object name */
|
|
if (XmToggleButtonGetState(txttb_w)) {
|
|
while (--i >= 0 && objname[i] == ' ')
|
|
objname[i] = '\0';
|
|
if (i < 0)
|
|
return;
|
|
} else {
|
|
char *comma = strchr (objname, ',');
|
|
if (comma)
|
|
*comma = '\0';
|
|
}
|
|
|
|
/* find object with name matching that at start of this line */
|
|
sv_getfldstars (&fs, &nfs);
|
|
for (db_scaninit(&dbs, ALLM, fs, nfs); (op = db_scan(&dbs)) != NULL; )
|
|
if (!strcmp (op->o_name, objname))
|
|
break;
|
|
if (!op)
|
|
return; /* no name found */
|
|
|
|
/* set up for popup and go */
|
|
|
|
/* create popup first time */
|
|
if (!pu.pu_w)
|
|
sl_create_pu();
|
|
|
|
pu.linepos = pos;
|
|
pu.op = op;
|
|
set_xmstring (pu.name_w, XmNlabelString, objname);
|
|
XmMenuPosition (pu.pu_w, (XButtonPressedEvent *)ev);
|
|
XtManageChild (pu.pu_w);
|
|
}
|
|
|
|
/* save the text widget in the appropriate file */
|
|
static void
|
|
sl_save (how)
|
|
char *how;
|
|
{
|
|
char *fn = XmToggleButtonGetState(txttb_w)
|
|
? XmTextFieldGetString (txtfn_w)
|
|
: XmTextFieldGetString (edbfn_w);
|
|
FILE *fp = fopend (fn, NULL, how);
|
|
char *txt = XmTextGetString (listt_w);
|
|
|
|
fprintf (fp, "%s", txt);
|
|
fclose (fp);
|
|
XtFree (txt);
|
|
XtFree (fn);
|
|
}
|
|
|
|
/* called when we want to append .. filename already checked */
|
|
static void
|
|
sl_append_qcb ()
|
|
{
|
|
sl_save ("a");
|
|
}
|
|
|
|
/* called when we want to ceate a new text-format file */
|
|
static void
|
|
sl_write_qcb ()
|
|
{
|
|
sl_save ("w");
|
|
}
|
|
|
|
static int
|
|
spaceship (diff)
|
|
double diff;
|
|
{
|
|
if (diff < 0)
|
|
return (-1);
|
|
if (diff > 0)
|
|
return (1);
|
|
return (0);
|
|
}
|
|
|
|
/* compare 2 ObjInfos for RA, ala qsort() */
|
|
static int
|
|
sort_ra (const void *v1, const void* v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->op->s_ra - lp2->op->s_ra));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for HA, ala qsort() */
|
|
static int
|
|
sort_ha (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->ha - lp2->ha));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for alt, ala qsort() */
|
|
static int
|
|
sort_alt (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp2->op->s_alt - lp1->op->s_alt));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for zenith distance, ala qsort() */
|
|
static int
|
|
sort_z (const void *v1, const void *v2)
|
|
{
|
|
return (-sort_alt(v1, v2));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for az, ala qsort() */
|
|
static int
|
|
sort_az (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->op->s_az - lp2->op->s_az));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for airmass, ala qsort() */
|
|
static int
|
|
sort_airmass (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->Z - lp2->Z));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for Dec, ala qsort() */
|
|
static int
|
|
sort_dec (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->op->s_dec - lp2->op->s_dec));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for rise time, ala qsort() */
|
|
static int
|
|
sort_risetm (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int no1 = lp1->rs.rs_flags & (RS_NORISE|NORS);
|
|
int no2 = lp2->rs.rs_flags & (RS_NORISE|NORS);
|
|
|
|
/* float entries with no rise info to end of list */
|
|
if (no1)
|
|
return (no2 ? 0 : 1);
|
|
else if (no2)
|
|
return (-1);
|
|
else
|
|
return (spaceship (lp1->rs.rs_risetm - lp2->rs.rs_risetm));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for rise az, ala qsort() */
|
|
static int
|
|
sort_riseaz (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int no1 = lp1->rs.rs_flags & (RS_NORISE|NORS);
|
|
int no2 = lp2->rs.rs_flags & (RS_NORISE|NORS);
|
|
|
|
/* float entries with no rise info to end of list */
|
|
if (no1)
|
|
return (no2 ? 0 : 1);
|
|
else if (no2)
|
|
return (-1);
|
|
else
|
|
return (spaceship (lp1->rs.rs_riseaz - lp2->rs.rs_riseaz));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for set time, ala qsort() */
|
|
static int
|
|
sort_settm (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int no1 = lp1->rs.rs_flags & (RS_NOSET|NORS);
|
|
int no2 = lp2->rs.rs_flags & (RS_NOSET|NORS);
|
|
|
|
/* float entries with no rise info to end of list */
|
|
if (no1)
|
|
return (no2 ? 0 : 1);
|
|
else if (no2)
|
|
return (-1);
|
|
else
|
|
return (spaceship (lp1->rs.rs_settm - lp2->rs.rs_settm));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for set az, ala qsort() */
|
|
static int
|
|
sort_setaz (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int no1 = lp1->rs.rs_flags & (RS_NOSET|NORS);
|
|
int no2 = lp2->rs.rs_flags & (RS_NOSET|NORS);
|
|
|
|
/* float entries with no rise info to end of list */
|
|
if (no1)
|
|
return (no2 ? 0 : 1);
|
|
else if (no2)
|
|
return (-1);
|
|
else
|
|
return (spaceship (lp1->rs.rs_setaz - lp2->rs.rs_setaz));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for transit time, ala qsort() */
|
|
static int
|
|
sort_trantm (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int no1 = lp1->rs.rs_flags & (RS_ERROR|RS_NEVERUP|RS_NOTRANS);
|
|
int no2 = lp2->rs.rs_flags & (RS_ERROR|RS_NEVERUP|RS_NOTRANS);
|
|
|
|
/* float entries with no transit info to end of list */
|
|
if (no1)
|
|
return (no2 ? 0 : 1);
|
|
else if (no2)
|
|
return (-1);
|
|
else
|
|
return (spaceship (lp1->rs.rs_trantm - lp2->rs.rs_trantm));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for transit alt, ala qsort() */
|
|
static int
|
|
sort_tranalt (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int no1 = lp1->rs.rs_flags & (RS_ERROR|RS_NEVERUP|RS_NOTRANS);
|
|
int no2 = lp2->rs.rs_flags & (RS_ERROR|RS_NEVERUP|RS_NOTRANS);
|
|
|
|
/* float entries with no transit info to end of list */
|
|
if (no1)
|
|
return (no2 ? 0 : 1);
|
|
else if (no2)
|
|
return (-1);
|
|
else
|
|
return (spaceship (lp1->rs.rs_tranalt - lp2->rs.rs_tranalt));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for galactic latitude, ala qsort() */
|
|
static int
|
|
sort_glat (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->glat - lp2->glat));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for galactic longitude, ala qsort() */
|
|
static int
|
|
sort_glng (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->glng - lp2->glng));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for ecliptic latitude, ala qsort() */
|
|
static int
|
|
sort_eclat (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->eclat - lp2->eclat));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for ecliptic longitude, ala qsort() */
|
|
static int
|
|
sort_eclng (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp1->eclng - lp2->eclng));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for heliocentric latitude, ala qsort() */
|
|
static int
|
|
sort_hlat (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int ss1 = is_ssobj(lp1->op);
|
|
int ss2 = is_ssobj(lp2->op);
|
|
|
|
/* float non-solsys objects to end of list */
|
|
if (ss1) {
|
|
if (ss2)
|
|
return (spaceship(lp1->op->s_hlat - lp2->op->s_hlat));
|
|
return (-1);
|
|
} else
|
|
return (ss2 ? 1 : 0);
|
|
}
|
|
|
|
/* compare 2 ObjInfos for heliocentric longitude, ala qsort() */
|
|
static int
|
|
sort_hlng (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int ss1 = is_ssobj(lp1->op);
|
|
int ss2 = is_ssobj(lp2->op);
|
|
|
|
/* float non-solsys objects to end of list */
|
|
if (ss1) {
|
|
if (ss2)
|
|
return (spaceship(lp1->op->s_hlong - lp2->op->s_hlong));
|
|
return (-1);
|
|
} else
|
|
return (ss2 ? 1 : 0);
|
|
}
|
|
|
|
/* compare 2 ObjInfos for earth distance, ala qsort() */
|
|
static int
|
|
sort_edist (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int ss1 = is_ssobj(lp1->op);
|
|
int ss2 = is_ssobj(lp2->op);
|
|
|
|
/* float non-solsys objects to end of list */
|
|
if (ss1) {
|
|
if (ss2)
|
|
return (spaceship(lp1->op->s_edist - lp2->op->s_edist));
|
|
return (-1);
|
|
} else
|
|
return (ss2 ? 1 : 0);
|
|
}
|
|
|
|
/* compare 2 ObjInfos for sun distance, ala qsort() */
|
|
static int
|
|
sort_sdist (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
int ss1 = is_ssobj(lp1->op);
|
|
int ss2 = is_ssobj(lp2->op);
|
|
|
|
/* float non-solsys objects to end of list */
|
|
if (ss1) {
|
|
if (ss2)
|
|
return (spaceship(lp1->op->s_sdist - lp2->op->s_sdist));
|
|
return (-1);
|
|
} else
|
|
return (ss2 ? 1 : 0);
|
|
}
|
|
|
|
/* compare 2 ObjInfos for elongation , ala qsort() */
|
|
static int
|
|
sort_elong (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp2->op->s_elong - lp1->op->s_elong));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for magnitude, ala qsort() */
|
|
static int
|
|
sort_mag (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(get_mag(lp1->op) - get_mag(lp2->op)));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for constellation name, ala qsort() */
|
|
static int
|
|
sort_cns (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (strcmp(lp1->cns, lp2->cns));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for ura[], ala qsort() */
|
|
static int
|
|
sort_ura (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (strcmp(lp1->ura, lp2->ura));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for u2k[], ala qsort() */
|
|
static int
|
|
sort_u2k (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (strcmp(lp1->u2k, lp2->u2k));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for msa[] name, ala qsort() */
|
|
static int
|
|
sort_msa (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (strcmp(lp1->msa, lp2->msa));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for f_spect[], ala qsort() */
|
|
static int
|
|
sort_spect (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
Obj *op1 = lp1->op;
|
|
Obj *op2 = lp2->op;
|
|
int o1ok= is_type(op1,FIXEDM) && op1->f_class!='G' && op1->f_spect[0];
|
|
int o2ok= is_type(op2,FIXEDM) && op2->f_class!='G' && op2->f_spect[0];
|
|
|
|
if (!o1ok)
|
|
return (o2ok ? 1 : 0);
|
|
if (!o2ok)
|
|
return (o1ok ? -1 : 0);
|
|
return (strncmp (op1->f_spect, op2->f_spect, sizeof(op1->f_spect)));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for description, ala qsort() */
|
|
static int
|
|
sort_desc (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (strcmp(lp1->desc, lp2->desc));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for name, ala qsort() */
|
|
static int
|
|
sort_name (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
char *s1 = lp1->op->o_name;
|
|
char *s2 = lp2->op->o_name;
|
|
|
|
return (strnncmp(s1, s2));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for size, ala qsort() */
|
|
static int
|
|
sort_size (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
return (spaceship(lp2->op->s_size - lp1->op->s_size));
|
|
}
|
|
|
|
/* compare 2 ObjInfos for their separation from the current datatable sep
|
|
* object, ala qsort()
|
|
*/
|
|
static int
|
|
sort_sep (const void *v1, const void *v2)
|
|
{
|
|
ObjInfo *lp1 = (ObjInfo *)v1;
|
|
ObjInfo *lp2 = (ObjInfo *)v2;
|
|
double sep1 = dm_sep (lp1->op);
|
|
double sep2 = dm_sep (lp2->op);
|
|
return (spaceship (sep1 - sep2));
|
|
}
|
|
|
|
/* compare 2 ObjInfos according to each sort key, ala qsort() */
|
|
static int
|
|
mastercmp_f (const void *v1, const void *v2)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < nsortorder; i++) {
|
|
int c = (*sortorder[i]->cmp_f)(v1, v2);
|
|
if (c)
|
|
return (c);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/* append src to *dstp, growing *dstp as required.
|
|
* update *dstp and return new final length, sans trailing '\0'.
|
|
*/
|
|
static int
|
|
mstrcat (dstp, dl, src, sl)
|
|
char **dstp, *src;
|
|
int dl, sl;
|
|
{
|
|
char *newdst = XtRealloc (*dstp, sl+dl+1);
|
|
strcpy (newdst+dl, src);
|
|
*dstp = newdst;
|
|
return (sl+dl);
|
|
}
|
|
|
|
/* fill listt_w with oinfo[noinfo] in ".edb" format */
|
|
static void
|
|
fill_edbfmt (oinfo, noinfo)
|
|
ObjInfo *oinfo;
|
|
int noinfo;
|
|
{
|
|
char *txt = NULL;
|
|
int txtl = 0;
|
|
char buf[256];
|
|
char lbuf[256];
|
|
int l, i;
|
|
|
|
/* just install each db object */
|
|
for (i = 0; i < noinfo; i++) {
|
|
db_write_line (oinfo[i].op, lbuf);
|
|
l = sprintf (buf, "%s\n", lbuf);
|
|
txtl = mstrcat (&txt, txtl, buf, l);
|
|
}
|
|
|
|
/* N.B. removing last nl looks better here, but complicates line
|
|
* deleting and must be put back when saving.
|
|
*/
|
|
|
|
/* no header */
|
|
XmTextFieldSetString (hdrtf_w, "");
|
|
|
|
/* install in text widget, then finished */
|
|
XmTextSetString (listt_w, txt);
|
|
XtFree (txt);
|
|
}
|
|
|
|
/* fill listt_w with oinfo[noinfo] in ".txt" format */
|
|
static void
|
|
fill_txtfmt (oinfo, noinfo)
|
|
ObjInfo *oinfo;
|
|
int noinfo;
|
|
{
|
|
static char dashes[] = "--------------------------";
|
|
Now *np = mm_get_now();
|
|
char *txt = NULL;
|
|
int txtl = 0;
|
|
char tsbuf[64];
|
|
char buf[256];
|
|
double tmp;
|
|
int lineno;
|
|
int l, i;
|
|
|
|
/* summarize the current circumstances */
|
|
mjd_year (epoch == EOD ? mjd : epoch, &tmp);
|
|
fs_timestamp (np, tsbuf);
|
|
l = sprintf (buf, "XEphem %s Sky List: %s %s place, Epoch %7.2f, %s\n",
|
|
PATCHLEVEL,
|
|
pref_get (PREF_EQUATORIAL) == PREF_TOPO ? "Topocentric"
|
|
: "Geocentric",
|
|
epoch == EOD ? "Apparent" : "Mean",
|
|
tmp, tsbuf);
|
|
txtl = mstrcat (&txt, txtl, buf, strlen(buf));
|
|
|
|
/* print name, Data Table columns, description.
|
|
* column heading spacing based on size of data.
|
|
* lineno is used to build up a header.. goofy but works.
|
|
*/
|
|
lineno = 0;
|
|
for (i = 0; i < noinfo; i++) {
|
|
ObjInfo *lp = &oinfo[i];
|
|
Obj *op = lp->op;
|
|
char dbbuf[64];
|
|
DMCol c;
|
|
|
|
switch (lineno) {
|
|
case 0:
|
|
l = sprintf (buf, "%-*s", MAXNM-1, "Name");
|
|
break;
|
|
case 1:
|
|
l = sprintf (buf, "%.*s", MAXNM-1, dashes);
|
|
break;
|
|
default:
|
|
l = sprintf (buf, "%-*.*s", MAXNM-1, MAXNM-1, op->o_name);
|
|
break;
|
|
}
|
|
txtl = mstrcat (&txt, txtl, buf, l);
|
|
|
|
for (c = 0; c < NDMCol; c++) {
|
|
if (!dm_colFormat (np, op, &lp->rs, c, dbbuf)) {
|
|
int f, h;
|
|
switch (lineno) {
|
|
case 0: /* column heading */
|
|
f = strlen(dbbuf); /* width of field */
|
|
dm_colHeader (c, dbbuf);
|
|
h = strlen(dbbuf); /* width of heading */
|
|
l = sprintf (buf, " %*s%-*s", (f-h)/2, "", f-(f-h)/2,
|
|
dbbuf);
|
|
break;
|
|
case 1: /* dashes */
|
|
f = strlen(dbbuf);
|
|
l = sprintf (buf, " %.*s", f, dashes);
|
|
break;
|
|
default: /* real field :) */
|
|
l = sprintf (buf, " %s", dbbuf);
|
|
break;
|
|
}
|
|
txtl = mstrcat (&txt, txtl, buf, l);
|
|
}
|
|
}
|
|
|
|
switch (lineno) {
|
|
case 0:
|
|
l = sprintf (buf, " Type\n");
|
|
i--; /* repeat */
|
|
break;
|
|
case 1:
|
|
l = sprintf (buf, " %.4s\n", dashes);
|
|
i--; /* repeat */
|
|
break;
|
|
default:
|
|
l = sprintf (buf, " %s\n", lp->desc);
|
|
break;
|
|
}
|
|
txtl = mstrcat (&txt, txtl, buf, l);
|
|
|
|
lineno++;
|
|
}
|
|
|
|
/* N.B. removing last nl looks better here, but complicates line
|
|
* deleting and must be put back when saving.
|
|
*/
|
|
|
|
/* extract 2nd line and use as column heading */
|
|
sl_colhdr (txt);
|
|
|
|
/* install in text widget, then finished */
|
|
XmTextSetString (listt_w, txt);
|
|
XtFree (txt);
|
|
}
|
|
|
|
/* extract 2nd line of list and use as column heading.
|
|
* maintain common background color.
|
|
*/
|
|
static void
|
|
sl_colhdr (txt)
|
|
char *txt;
|
|
{
|
|
Pixel bg;
|
|
char *nl1, *nl2;
|
|
|
|
nl1 = strchr (txt, '\n');
|
|
nl2 = strchr (nl1+1, '\n');
|
|
|
|
*nl2 = '\0';
|
|
get_something (nl_w, XmNbackground, (XtArgVal)&bg);
|
|
set_something (hdrtf_w, XmNbackground, (XtArgVal)bg);
|
|
XmTextFieldSetString (hdrtf_w, nl1+1);
|
|
*nl2 = '\n';
|
|
}
|
|
|
|
/* sort, then fill listt_w with report.
|
|
* also show count in nl_w.
|
|
*/
|
|
static void
|
|
sl_sort ()
|
|
{
|
|
Now *np = mm_get_now();
|
|
ObjInfo *oinfo = NULL;
|
|
DBScan dbs;
|
|
char buf[128];
|
|
int noinfo;
|
|
double e;
|
|
ObjF *fs;
|
|
int nfs;
|
|
Obj *op;
|
|
|
|
if (!nsortorder) {
|
|
xe_msg (1, "Please pick at least one sort key");
|
|
return;
|
|
}
|
|
|
|
watch_cursor(1);
|
|
|
|
/* scan db for all objects on Sky screen, add to list */
|
|
e = epoch == EOD ? mjd : epoch;
|
|
sv_getfldstars (&fs, &nfs);
|
|
noinfo = 0;
|
|
for (db_scaninit(&dbs, ALLM, fs, nfs); (op = db_scan(&dbs)) != NULL; ) {
|
|
ObjInfo *lp;
|
|
|
|
if (!(op->o_flags & OBJF_ONSCREEN))
|
|
continue;
|
|
|
|
/* add to list */
|
|
oinfo = (ObjInfo *) XtRealloc ((void*)oinfo,
|
|
(noinfo+1)*sizeof(ObjInfo));
|
|
lp = &oinfo[noinfo++];
|
|
lp->op = op;
|
|
|
|
/* add supporting info for sorts */
|
|
dm_riset (np, op, &lp->rs);
|
|
lp->cns = cns_name (cns_pick (op->s_ra, op->s_dec, e));
|
|
eq_gal (e, op->s_ra, op->s_dec, &lp->glat, &lp->glng);
|
|
eq_ecl (e, op->s_gaera, op->s_gaedec, &lp->eclat, &lp->eclng);
|
|
airmass (op->s_alt, &lp->Z);
|
|
lp->desc = obj_description (op);
|
|
radec2ha (np, op->s_ra, op->s_dec, &lp->ha);
|
|
strncpy (lp->ura, um_atlas(op->s_ra, op->s_dec), sizeof(lp->ura));
|
|
strncpy (lp->u2k, u2k_atlas(op->s_ra, op->s_dec), sizeof(lp->u2k));
|
|
strncpy (lp->msa, msa_atlas(op->s_ra, op->s_dec), sizeof(lp->msa));
|
|
}
|
|
|
|
/* sort as desired */
|
|
qsort ((void *)oinfo, noinfo, sizeof(ObjInfo), mastercmp_f);
|
|
|
|
/* display list, else clear */
|
|
if (!noinfo) {
|
|
XmTextSetString (listt_w, "");
|
|
XmTextFieldSetString (hdrtf_w, "");
|
|
} else if (XmToggleButtonGetState(txttb_w))
|
|
fill_txtfmt (oinfo, noinfo);
|
|
else
|
|
fill_edbfmt (oinfo, noinfo);
|
|
|
|
/* show count -- N.B. match string set when created */
|
|
sprintf (buf, "List: %d objects. Choose columns with", noinfo);
|
|
set_xmstring (nl_w, XmNlabelString, buf);
|
|
|
|
/* free */
|
|
XtFree ((void *)oinfo);
|
|
|
|
watch_cursor(0);
|
|
}
|
|
|
|
/* For RCS Only -- Do Not Edit */
|
|
static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: skylist.c,v $ $Date: 2006/02/05 21:10:43 $ $Revision: 1.42 $ $Name: $"};
|