XEphem/GUI/xephem/skylist.c

1510 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 (void)
{
if (!list_w) {
sl_create_list_w();
sl_create_pu();
}
XtManageChild (list_w);
}
void
sl_unmanage (void)
{
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 (void)
{
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 (void)
{
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 (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 (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 (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 (void)
{
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 (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 (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 (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 (Widget w, XtPointer client, XtPointer call)
{
sl_sort();
}
/* called when the Save button is hit */
/* ARGSUSED */
static void
sl_save_cb (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 (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 (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 (void)
{
sl_save ("a");
}
/* called when we want to ceate a new text-format file */
static void
sl_write_qcb (void)
{
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 (void)
*/
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 (void)
{
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);
}