mirror of https://github.com/XEphem/XEphem.git
1247 lines
35 KiB
C
1247 lines
35 KiB
C
/* provide a simple observer's log facility.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#include <ctype.h>
|
|
#include <fnmatch.h>
|
|
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/RowColumn.h>
|
|
#include <Xm/Label.h>
|
|
#include <Xm/TextF.h>
|
|
#include <Xm/Text.h>
|
|
#include <Xm/Form.h>
|
|
#include <Xm/ToggleB.h>
|
|
#include <Xm/PushB.h>
|
|
#include <Xm/Separator.h>
|
|
|
|
#include "lilxml.h"
|
|
#include "xephem.h"
|
|
|
|
typedef struct {
|
|
int justlabel; /* just a label not a field */
|
|
char *label; /* row title */
|
|
char *xml; /* xml tag, if different from label */
|
|
Widget tfw; /* TF for display/entry */
|
|
Widget ktb; /* TB whether to use as sort key */
|
|
Widget ltb; /* TB whether to list */
|
|
Widget stb; /* TB whether to use as search key */
|
|
char *srchvalue; /* fast access to search value */
|
|
int colw; /* col length */
|
|
} LogField;
|
|
|
|
/* definition of each log field.
|
|
* N.B. must stay in sync with LogTags
|
|
*/
|
|
static LogField logfields[] = {
|
|
{1, "Automatically defined fields:"},
|
|
{0, "Object"},
|
|
{0, "Location"},
|
|
{0, "Local Date", "Date"},
|
|
{0, "Local Time", "Time"},
|
|
|
|
{0, "UTC Date", "UTCDate"},
|
|
{0, "UTC Time", "UTCTime"},
|
|
{0, "JD", "JD"},
|
|
{0, "H JD", "HJD"},
|
|
{0, "Constel"},
|
|
|
|
{0, "Latitude"},
|
|
{0, "Longitude"},
|
|
{0, "RA 2000", "RA2000"},
|
|
{0, "Dec 2000", "Dec2000"},
|
|
{0, "Altitude"},
|
|
|
|
{0, "Azimuth"},
|
|
{0, "Airmass"},
|
|
{0, "Moon sep", "MoonSep"},
|
|
{0, "Moon alt", "MoonAlt"},
|
|
{0, "Moon phase", "MoonPhase"},
|
|
|
|
{0, "Sun alt", "SunAlt"},
|
|
{0, "Elongation"},
|
|
|
|
{1, "User defined fields:"},
|
|
{0, "Telescope"},
|
|
{0, "Camera"},
|
|
{0, "Eyepiece"},
|
|
{0, "Filter"},
|
|
|
|
{0, "Seeing"},
|
|
{0, "Transparency"},
|
|
{0, "User 1", "User1"},
|
|
{0, "User 2", "User2"},
|
|
};
|
|
|
|
#define NFLDS XtNumber(logfields)
|
|
|
|
#define TFCOL 20 /* n text field columns */
|
|
#define TFROW 5 /* text field rows in notes field */
|
|
|
|
#define KTBPOS 0 /* position % for sort key TB */
|
|
#define LTBPOS 8 /* position % for list TB */
|
|
#define STBPOS 16 /* position % for search TB */
|
|
#define LPOS 24 /* position % for label */
|
|
#define LTFPOS 55 /* position % of text field left side */
|
|
|
|
static int srchMatch (XMLEle *ep);
|
|
static int notesMatch (XMLEle *ep);
|
|
static int strscmp (char *s1, char *s2);
|
|
static void ol_create(void);
|
|
static void oll_create(void);
|
|
static void ol_key_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void ol_help_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void ol_close_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void ol_list_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void ol_add_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void ol1row (Widget rc_w, LogField *lp);
|
|
static void fillNowFields (void);
|
|
static void fillObjFields (Obj *op);
|
|
static void ol_writeLB(void);
|
|
static void ol_listLB(void);
|
|
static char *xmltag (LogField *lfp);
|
|
static Widget logfld (char *tag);
|
|
static void printHeadings(XMLEle **mpp, int nmpp, char **txt, int *txtl);
|
|
static void printEntry (XMLEle *ep, char **txt, int *txtl);
|
|
static void sortMatches (XMLEle **mpp, int nmpp);
|
|
static void oll_save_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void oll_save(void);
|
|
static void oll_close_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void oll_info_eh (Widget w, XtPointer client, XEvent *ev, Boolean *ctd);
|
|
|
|
static Widget olshell_w; /* main shell */
|
|
static Widget ollshell_w; /* list shell */
|
|
static Widget ollst_w; /* scrolled list */
|
|
static Widget ollstf_w; /* save text field */
|
|
static Widget notes_w; /* notes Text */
|
|
static Widget notesltb_w; /* notes list TB */
|
|
static Widget notesstb_w; /* notes search TB */
|
|
|
|
static XMLEle **matches; /* malloced list of XMLEle* in list */
|
|
static int nmatches; /* number in list */
|
|
static XMLEle *matchesroot; /* root of entries in matches[] */
|
|
|
|
static char lbfn[] = "xelogbook.xml"; /* logbook file name */
|
|
static char lbtag[] = "xelogbook"; /* outter xml tag for logbook */
|
|
static char lbetag[] = "logentry"; /* tag for each entry */
|
|
static char ntag[] = "Notes"; /* tag for notes */
|
|
static double lbver = 1.1; /* logbook version attr */
|
|
|
|
static char olcategory[] = "Logbook"; /* save category */
|
|
|
|
/* bring up observer's log, create if first time */
|
|
void
|
|
ol_manage()
|
|
{
|
|
if (!olshell_w) {
|
|
ol_create();
|
|
oll_create();
|
|
}
|
|
|
|
XtPopup (olshell_w, XtGrabNone);
|
|
set_something (olshell_w, XmNiconic, (XtArgVal)False);
|
|
}
|
|
|
|
/* return whether logbook is currently showing */
|
|
int
|
|
ol_isUp()
|
|
{
|
|
return(isUp(olshell_w));
|
|
}
|
|
|
|
/* fill log fields from given object, and Now */
|
|
void
|
|
ol_setObj (Obj *op)
|
|
{
|
|
fillNowFields();
|
|
fillObjFields(op);
|
|
}
|
|
|
|
/* called to put up or remove the watch cursor. */
|
|
void
|
|
ol_cursor (Cursor c)
|
|
{
|
|
Window win;
|
|
|
|
if (olshell_w && (win = XtWindow(olshell_w)) != 0) {
|
|
Display *dsp = XtDisplay(olshell_w);
|
|
if (c)
|
|
XDefineCursor (dsp, win, c);
|
|
else
|
|
XUndefineCursor (dsp, win);
|
|
}
|
|
}
|
|
|
|
/* create the observer log window */
|
|
static void
|
|
ol_create()
|
|
{
|
|
Widget w, sep_w;
|
|
Widget rc_w, fo_w;
|
|
Arg args[20];
|
|
int i, n;
|
|
|
|
/* create the shell and form */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNallowShellResize, True); n++;
|
|
XtSetArg (args[n], XmNcolormap, xe_cm); n++;
|
|
XtSetArg (args[n], XmNtitle, "xephem Observer's log"); n++;
|
|
XtSetArg (args[n], XmNiconName, "Logbook"); n++;
|
|
XtSetArg (args[n], XmNdeleteResponse, XmUNMAP); n++;
|
|
olshell_w = XtCreatePopupShell ("Logbook", topLevelShellWidgetClass,
|
|
toplevel_w, args, n);
|
|
setup_icon (olshell_w);
|
|
set_something (olshell_w, XmNcolormap, (XtArgVal)xe_cm);
|
|
sr_reg (olshell_w, "XEphem*Logbook.x", olcategory, 0);
|
|
sr_reg (olshell_w, "XEphem*Logbook.y", olcategory, 0);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNverticalSpacing, 10); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 10); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 10); n++;
|
|
XtSetArg (args[n], XmNfractionBase, 17); n++;
|
|
fo_w = XmCreateForm (olshell_w, "LF", args, n);
|
|
XtAddCallback (fo_w, XmNhelpCallback, ol_help_cb, 0);
|
|
XtManageChild (fo_w);
|
|
|
|
/* controls attached across the bottom */
|
|
|
|
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, 4); n++;
|
|
w = XmCreatePushButton (fo_w, "Close", args, n);
|
|
wtip (w, "Close this window");
|
|
XtAddCallback (w, XmNactivateCallback, ol_close_cb, 0);
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 5); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 8); n++;
|
|
w = XmCreatePushButton (fo_w, "List", args, n);
|
|
wtip (w, "List fields L of all logbook entries matching requirements selected with < > *, sorted by K");
|
|
XtAddCallback (w, XmNactivateCallback, ol_list_cb, 0);
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 9); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 12); n++;
|
|
w = XmCreatePushButton (fo_w, "Add", args, n);
|
|
wtip (w, "Add above fields as a new entry in the log book");
|
|
XtAddCallback (w, XmNactivateCallback, ol_add_cb, 0);
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 13); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 16); n++;
|
|
w = XmCreatePushButton (fo_w, "Help", args, n);
|
|
wtip (w, "Get more info about this window.");
|
|
XtAddCallback (w, XmNactivateCallback, ol_help_cb, 0);
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
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++;
|
|
sep_w = XmCreateSeparator (fo_w, "LS", args, n);
|
|
XtManageChild (sep_w);
|
|
|
|
/* rc for the tags */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
rc_w = XmCreateRowColumn (fo_w, "LRC", args, n);
|
|
XtManageChild (rc_w);
|
|
|
|
for (i = 0; i < NFLDS; i++)
|
|
ol1row (rc_w, &logfields[i]);
|
|
|
|
/* notes entry expands into remaining area between sep and rc */
|
|
|
|
n =0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, rc_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
w = XmCreateLabel (fo_w, "Notes", args, n);
|
|
set_xmstring (w, XmNlabelString, "Notes:");
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, rc_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, w); n++;
|
|
XtSetArg (args[n], XmNleftOffset, 5); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 0); n++;
|
|
XtSetArg (args[n], XmNmarginTop, 0); n++;
|
|
XtSetArg (args[n], XmNmarginBottom, 0); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 0); n++;
|
|
XtSetArg (args[n], XmNmarginLeft, 0); n++;
|
|
XtSetArg (args[n], XmNmarginRight, 0); n++;
|
|
notesltb_w = XmCreateToggleButton (fo_w, "L", args, n);
|
|
wtip (notesltb_w, "Include Notes in list");
|
|
XtManageChild (notesltb_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, rc_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, notesltb_w); n++;
|
|
XtSetArg (args[n], XmNleftOffset, 5); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 0); n++;
|
|
XtSetArg (args[n], XmNmarginTop, 0); n++;
|
|
XtSetArg (args[n], XmNmarginBottom, 0); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 0); n++;
|
|
XtSetArg (args[n], XmNmarginLeft, 0); n++;
|
|
XtSetArg (args[n], XmNmarginRight, 0); n++;
|
|
notesstb_w = XmCreateToggleButton (fo_w, "S", args, n);
|
|
wtip (notesstb_w, "Match notes against given glob pattern");
|
|
XtManageChild (notesstb_w);
|
|
|
|
n =0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, notesltb_w); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNbottomWidget, sep_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++;
|
|
XtSetArg (args[n], XmNrows, TFROW); n++;
|
|
notes_w = XmCreateScrolledText (fo_w, "Value", args, n);
|
|
XtManageChild (notes_w);
|
|
}
|
|
|
|
/* build up one row */
|
|
static void
|
|
ol1row (Widget rc_w, LogField *lp)
|
|
{
|
|
Widget w, fo_w;
|
|
Arg args[20];
|
|
int n;
|
|
|
|
/* main form for this row */
|
|
n = 0;
|
|
fo_w = XmCreateForm (rc_w, "LRF", args, n);
|
|
XtManageChild (fo_w);
|
|
|
|
/* sort key TB, unless just label */
|
|
if (!lp->justlabel) {
|
|
n = 0;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, KTBPOS); n++;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 0); n++;
|
|
XtSetArg (args[n], XmNmarginTop, 0); n++;
|
|
XtSetArg (args[n], XmNmarginBottom, 0); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 0); n++;
|
|
XtSetArg (args[n], XmNmarginLeft, 0); n++;
|
|
XtSetArg (args[n], XmNindicatorType, XmONE_OF_MANY); n++;
|
|
XtSetArg (args[n], XmNmarginRight, 0); n++;
|
|
w = XmCreateToggleButton (fo_w, "KTB", args, n);
|
|
XtAddCallback (w, XmNvalueChangedCallback, ol_key_cb, NULL);
|
|
set_xmstring (w, XmNlabelString, " ");
|
|
XtManageChild (w);
|
|
lp->ktb = w;
|
|
}
|
|
|
|
/* list TB, unless just label */
|
|
if (!lp->justlabel) {
|
|
n = 0;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, LTBPOS); n++;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 0); n++;
|
|
XtSetArg (args[n], XmNmarginTop, 0); n++;
|
|
XtSetArg (args[n], XmNmarginBottom, 0); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 0); n++;
|
|
XtSetArg (args[n], XmNmarginLeft, 0); n++;
|
|
XtSetArg (args[n], XmNmarginRight, 0); n++;
|
|
w = XmCreateToggleButton (fo_w, xmltag(lp), args, n);
|
|
set_xmstring (w, XmNlabelString, " ");
|
|
XtManageChild (w);
|
|
lp->ltb = w;
|
|
sr_reg (w, NULL, olcategory, 1);
|
|
}
|
|
|
|
/* search TB, if desired */
|
|
if (!lp->justlabel) {
|
|
n = 0;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, STBPOS); n++;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 0); n++;
|
|
XtSetArg (args[n], XmNmarginTop, 0); n++;
|
|
XtSetArg (args[n], XmNmarginBottom, 0); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 0); n++;
|
|
XtSetArg (args[n], XmNmarginLeft, 0); n++;
|
|
XtSetArg (args[n], XmNmarginRight, 0); n++;
|
|
w = XmCreateToggleButton (fo_w, "WTB", args, n);
|
|
set_xmstring (w, XmNlabelString, " ");
|
|
XtManageChild (w);
|
|
lp->stb = w;
|
|
}
|
|
|
|
/* field name */
|
|
n = 0;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, lp->justlabel ? 0 : LPOS); n++;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
w = XmCreateLabel (fo_w, "LRL", args, n);
|
|
set_xmstring (w, XmNlabelString, lp->label);
|
|
XtManageChild (w);
|
|
|
|
if (lp->justlabel) {
|
|
n = 0;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, w); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
w = XmCreateLabel (fo_w, "K", args, n);
|
|
wtip (w, "Select one field as the sort key for listings");
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, LTBPOS); n++;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, w); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
w = XmCreateLabel (fo_w, "L", args, n);
|
|
wtip (w, "Select the fields to be listed in a search result.");
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, STBPOS); n++;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, w); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
w = XmCreateLabel (fo_w, "S", args, n);
|
|
set_xmstring (w, XmNlabelString, "S");
|
|
wtip (w, "Select the fields to match for searching. Prefix numerical fields with < or >, other fields can use glob patterns");
|
|
XtManageChild (w);
|
|
|
|
}
|
|
|
|
/* text field, unless just a label */
|
|
if (!lp->justlabel) {
|
|
n = 0;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, LTFPOS); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNmarginTop, 0); n++;
|
|
XtSetArg (args[n], XmNmarginBottom, 0); n++;
|
|
XtSetArg (args[n], XmNcolumns, TFCOL); n++;
|
|
XtSetArg (args[n], XmNeditable, True); n++;
|
|
XtSetArg (args[n], XmNcursorPositionVisible, True); n++;
|
|
w = XmCreateTextField (fo_w, "LRTF", args, n);
|
|
fixTextCursor(w);
|
|
XtManageChild (w);
|
|
lp->tfw = w;
|
|
}
|
|
}
|
|
|
|
/* called when a K key toggles */
|
|
/* ARGSUSED */
|
|
static void
|
|
ol_key_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
int i;
|
|
|
|
/* do nothing when turning off */
|
|
if (!XmToggleButtonGetState(w))
|
|
return;
|
|
|
|
/* turn all others off, and turn on list for ths entry as a convenice */
|
|
for (i = 0; i < NFLDS; i++) {
|
|
LogField *lfp = &logfields[i];
|
|
if (lfp->ktb) {
|
|
if (lfp->ktb == w)
|
|
XmToggleButtonSetState (lfp->ltb, True, True);
|
|
else
|
|
XmToggleButtonSetState (lfp->ktb, False, True);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* callback from the overall Help button.
|
|
*/
|
|
/* ARGSUSED */
|
|
static void
|
|
ol_help_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
static char *msg[] = {
|
|
"Save observing notes",
|
|
};
|
|
|
|
hlp_dialog ("ObsLog", msg, sizeof(msg)/sizeof(msg[0]));
|
|
}
|
|
|
|
/* callback from the Close PB */
|
|
/* ARGSUSED */
|
|
static void
|
|
ol_close_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
XtPopdown (olshell_w);
|
|
}
|
|
|
|
/* callback from the List PB */
|
|
/* ARGSUSED */
|
|
static void
|
|
ol_list_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
/* fill in results */
|
|
ol_listLB();
|
|
|
|
/* display */
|
|
XtPopup (ollshell_w, XtGrabNone);
|
|
set_something (ollshell_w, XmNiconic, (XtArgVal)False);
|
|
}
|
|
|
|
/* callback from the Add PB */
|
|
/* ARGSUSED */
|
|
static void
|
|
ol_add_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
ol_writeLB();
|
|
}
|
|
|
|
/* set tags from Now */
|
|
static void
|
|
fillNowFields()
|
|
{
|
|
Now *np = mm_get_now();
|
|
double lmjd = mjd - tz/24.0;
|
|
char buf[32];
|
|
|
|
fs_date (buf, pref_get(PREF_DATE_FORMAT), mjd_day(lmjd));
|
|
XmTextFieldSetString (logfld("Date"), buf);
|
|
fs_time (buf, mjd_hr(lmjd));
|
|
XmTextFieldSetString (logfld("Time"), buf);
|
|
fs_date (buf, pref_get(PREF_DATE_FORMAT), mjd_day(mjd));
|
|
XmTextFieldSetString (logfld("UTCDate"), buf);
|
|
fs_time (buf, mjd_hr(mjd));
|
|
XmTextFieldSetString (logfld("UTCTime"), buf);
|
|
sprintf (buf, "%13.5f", mjd+MJD0);
|
|
XmTextFieldSetString (logfld("JD"), buf);
|
|
fs_dms_angle (buf, lat);
|
|
XmTextFieldSetString (logfld("Latitude"), buf);
|
|
fs_dms_angle (buf, -lng); /* + west */
|
|
XmTextFieldSetString (logfld("Longitude"), buf);
|
|
}
|
|
|
|
/* set tags from Obj op */
|
|
static void
|
|
fillObjFields (Obj *op)
|
|
{
|
|
Now *np = mm_get_now();
|
|
double e = epoch == EOD ? mjd : epoch;
|
|
double ra, dec, sep;
|
|
double hdiff, am;
|
|
Obj *fop;
|
|
char buf[32], *bp;
|
|
|
|
XmTextFieldSetString (logfld("Object"), op->o_name);
|
|
if ((bp = mm_getsite()) != NULL)
|
|
XmTextFieldSetString (logfld("Location"), bp);
|
|
|
|
/* TODO check for J2000 */
|
|
|
|
|
|
bp = cns_name (cns_pick (op->s_ra, op->s_dec, e));
|
|
bp += 5; /* skip the abbreviation */
|
|
XmTextFieldSetString (logfld("Constel"), bp);
|
|
|
|
ra = op->s_ra;
|
|
dec = op->s_dec;
|
|
if (epoch == EOD)
|
|
ap_as (np, e, &ra, &dec);
|
|
precess (e, J2000, &ra, &dec);
|
|
|
|
fs_sexa (buf, radhr(ra), 4, 36000);
|
|
XmTextFieldSetString (logfld("RA2000"), buf);
|
|
fs_sexa (buf, raddeg(dec), 4, 3600);
|
|
XmTextFieldSetString (logfld("Dec2000"), buf);
|
|
|
|
fs_sexa (buf, raddeg(op->s_alt), 4, 3600);
|
|
XmTextFieldSetString (logfld("Altitude"), buf);
|
|
fs_sexa (buf, raddeg(op->s_az), 4, 3600);
|
|
XmTextFieldSetString (logfld("Azimuth"), buf);
|
|
|
|
heliocorr (mjd+MJD0, ra, dec, &hdiff);
|
|
sprintf (buf, "%13.5f", mjd+MJD0 - hdiff);
|
|
XmTextFieldSetString (logfld("HJD"), buf);
|
|
|
|
airmass (op->s_alt, &am);
|
|
sprintf (buf, "%.4f", am);
|
|
XmTextFieldSetString (logfld("Airmass"), buf);
|
|
|
|
fop = db_basic (MOON);
|
|
dm_separation (op, fop, &sep);
|
|
fs_sexa (buf, raddeg(sep), 4, 3600);
|
|
XmTextFieldSetString (logfld("MoonSep"), buf);
|
|
fs_sexa (buf, raddeg(fop->s_alt), 4, 3600);
|
|
XmTextFieldSetString (logfld("MoonAlt"), buf);
|
|
sprintf (buf, "%10.1f", fop->s_phase);
|
|
XmTextFieldSetString (logfld("MoonPhase"), buf);
|
|
|
|
fop = db_basic (SUN);
|
|
fs_sexa (buf, raddeg(fop->s_alt), 4, 3600);
|
|
XmTextFieldSetString (logfld("SunAlt"), buf);
|
|
if (op->o_type != EARTHSAT) {
|
|
sprintf (buf, "%10.1f", op->s_elong);
|
|
XmTextFieldSetString (logfld("Elongation"), buf);
|
|
} else
|
|
XmTextFieldSetString (logfld("Elongation"), " ");
|
|
}
|
|
|
|
/* read the existing log book and list all entries matching the selected fields.
|
|
*/
|
|
static void
|
|
ol_listLB()
|
|
{
|
|
static LilXML *lp;
|
|
XMLEle *root, *ep;
|
|
char *txt = NULL;
|
|
int txtl = 0;
|
|
char fn[512];
|
|
char buf[2048];
|
|
FILE *fp;
|
|
int i;
|
|
|
|
/* open and read in the xml log */
|
|
sprintf (fn, "%s/%s", getPrivateDir(), lbfn);
|
|
fp = fopenh (fn, "r");
|
|
if (!fp) {
|
|
xe_msg (1, "%s:\n%s", fn, syserrstr());
|
|
return;
|
|
}
|
|
if (!lp)
|
|
lp = newLilXML();
|
|
root = readXMLFile (fp, lp, buf);
|
|
fclose (fp);
|
|
if (!root) {
|
|
xe_msg (1, "%s:\n%s", fn, buf);
|
|
return;
|
|
}
|
|
if (strcmp (tagXMLEle(root), lbtag)) {
|
|
delXMLEle (root);
|
|
xe_msg (1, "%s:\nNot an XEphem log file", fn);
|
|
return;
|
|
}
|
|
|
|
/* collect values from the desired search keys */
|
|
for (i = 0; i < NFLDS; i++) {
|
|
LogField *lfp = &logfields[i];
|
|
if (!lfp->justlabel && XmToggleButtonGetState(lfp->stb))
|
|
lfp->srchvalue = XmTextFieldGetString (lfp->tfw); /* XtFree! */
|
|
else
|
|
lfp->srchvalue = NULL;
|
|
}
|
|
|
|
/* scan each entry to create new matches list */
|
|
if (matches) {
|
|
delXMLEle (matchesroot);
|
|
XtFree ((char*)matches);
|
|
}
|
|
matches = NULL;
|
|
nmatches = 0;
|
|
matchesroot = root;
|
|
for (ep = nextXMLEle (root,1); ep != NULL; ep = nextXMLEle(root,0)) {
|
|
if (srchMatch(ep)) {
|
|
matches = (XMLEle **) XtRealloc ((char*)matches,
|
|
(nmatches+1)*sizeof(XMLEle *));
|
|
matches[nmatches++] = ep;
|
|
}
|
|
}
|
|
|
|
/* sort */
|
|
sortMatches (matches, nmatches);
|
|
|
|
/* print headings and figure column widths */
|
|
printHeadings (matches, nmatches, &txt, &txtl);
|
|
|
|
/* print each entry */
|
|
for (i = 0; i < nmatches; i++)
|
|
printEntry (matches[i], &txt, &txtl);
|
|
|
|
/* display */
|
|
XmTextSetString (ollst_w, txt);
|
|
|
|
/* clean up */
|
|
for (i = 0; i < NFLDS; i++)
|
|
if (logfields[i].srchvalue)
|
|
XtFree (logfields[i].srchvalue);
|
|
XtFree (txt);
|
|
}
|
|
|
|
/* append sl chars of src to *dstp, growing *dstp as required.
|
|
* update *dstp and return new final length, sans trailing '\0'.
|
|
*/
|
|
static int
|
|
mstrcat (char **dstp, int dl, char *src, int sl)
|
|
{
|
|
int newl = dl+sl;
|
|
char *newdst = XtRealloc (*dstp, newl+1);
|
|
strncpy (newdst+dl, src, sl);
|
|
newdst[newl] = '\0';
|
|
*dstp = newdst;
|
|
return (newl);
|
|
}
|
|
|
|
/* print list header.
|
|
* N.B. number of lines added here must agree with num removed in oll_info_eh()
|
|
*/
|
|
static void
|
|
printHeadings(XMLEle **mpp, int nmpp, char **txt, int *txtl)
|
|
{
|
|
static char dashes[] = "----------------------------------------------";
|
|
char buf[1024];
|
|
time_t t;
|
|
int i, j, l;
|
|
|
|
/* init colw to label length as a min width */
|
|
for (i = 0; i < NFLDS; i++)
|
|
logfields[i].colw = strlen(logfields[i].label);
|
|
|
|
/* one pass to find max col length */
|
|
for (i = 0; i < nmpp; i++) {
|
|
XMLEle *ep, *e = mpp[i];
|
|
for (j = 0; j < NFLDS; j++) {
|
|
LogField *lfp = &logfields[j];
|
|
if (!lfp->justlabel && XmToggleButtonGetState(lfp->ltb)) {
|
|
for (ep=nextXMLEle(e,1); ep!=NULL; ep=nextXMLEle(e,0)) {
|
|
if (!strcmp (xmltag(lfp), tagXMLEle(ep))) {
|
|
int l = strlen (pcdataXMLEle(ep));
|
|
if (l > lfp->colw)
|
|
lfp->colw = l;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* print col heading */
|
|
time (&t);
|
|
l = sprintf (buf, "XEphem %s Observers Log Book printed %s\n",
|
|
PATCHLEVEL, ctime(&t));
|
|
*txtl = mstrcat (txt, *txtl, buf, l);
|
|
for (i = 0; i < NFLDS; i++) {
|
|
LogField *lfp = &logfields[i];
|
|
if (!lfp->justlabel && XmToggleButtonGetState(lfp->ltb)) {
|
|
l = sprintf (buf, "%-*.*s ", lfp->colw, lfp->colw, lfp->label);
|
|
*txtl = mstrcat (txt, *txtl, buf, l);
|
|
}
|
|
}
|
|
*txtl = mstrcat (txt, *txtl, "\n", 1);
|
|
for (i = 0; i < NFLDS; i++) {
|
|
LogField *lfp = &logfields[i];
|
|
if (!lfp->justlabel && XmToggleButtonGetState(lfp->ltb)) {
|
|
l = sprintf (buf, "%-*.*s ", lfp->colw, lfp->colw, dashes);
|
|
*txtl = mstrcat (txt, *txtl, buf, l);
|
|
}
|
|
}
|
|
*txtl = mstrcat (txt, *txtl, "\n", 1);
|
|
}
|
|
|
|
/* add one entry from ep to txt */
|
|
static void
|
|
printEntry (XMLEle *ep, char **txt, int *txtl)
|
|
{
|
|
XMLEle *e, *notes = NULL;
|
|
int i;
|
|
|
|
/* show each selected list field, but just find notes for later */
|
|
for (e = nextXMLEle(ep,1); e != NULL; e = nextXMLEle(ep,0)) {
|
|
if (!strcmp (ntag, tagXMLEle(e))) {
|
|
notes = e;
|
|
continue;
|
|
}
|
|
for (i = 0; i < NFLDS; i++) {
|
|
LogField *lfp = &logfields[i];
|
|
if (!lfp->justlabel && !strcmp (xmltag(lfp), tagXMLEle(e))
|
|
&& XmToggleButtonGetState(lfp->ltb)) {
|
|
char buf[1024];
|
|
int l = sprintf (buf, "%-*.*s ", lfp->colw, lfp->colw,
|
|
pcdataXMLEle(e));
|
|
*txtl = mstrcat (txt, *txtl, buf, l);
|
|
}
|
|
}
|
|
}
|
|
*txtl = mstrcat (txt, *txtl, "\n", 1);
|
|
|
|
/* append notes if exists and wanted */
|
|
if (XmToggleButtonGetState (notesltb_w) && notes &&
|
|
pcdatalenXMLEle(notes) > 0) {
|
|
/* preceed each line with indent and # */
|
|
int l = pcdatalenXMLEle(notes);
|
|
char *np = pcdataXMLEle(notes);
|
|
*txtl = mstrcat (txt, *txtl, " # ", 4);
|
|
for (i = 0; i < l; i++) {
|
|
*txtl = mstrcat (txt, *txtl, &np[i], 1);
|
|
if (i < l-1 && np[i] == '\n')
|
|
*txtl = mstrcat (txt, *txtl, " # ", 4);
|
|
}
|
|
if (np[l-1] != '\n')
|
|
*txtl = mstrcat (txt, *txtl, "\n", 1);
|
|
}
|
|
}
|
|
|
|
/* return 1 if the given logentry satisfies all the search keys else 0 */
|
|
static int
|
|
srchMatch (XMLEle *ep)
|
|
{
|
|
XMLEle *eli;
|
|
int i;
|
|
|
|
for (eli = nextXMLEle (ep,1); eli != NULL; eli = nextXMLEle(ep,0))
|
|
for (i = 0; i < NFLDS; i++)
|
|
if (logfields[i].srchvalue &&
|
|
!strcmp (tagXMLEle(eli), xmltag(&logfields[i])) &&
|
|
!strscmp(logfields[i].srchvalue, pcdataXMLEle(eli)))
|
|
return (0);
|
|
|
|
/* all ok so far, now depends on notes if using it */
|
|
if (XmToggleButtonGetState(notesstb_w))
|
|
return (notesMatch (ep));
|
|
|
|
return (1);
|
|
}
|
|
|
|
/* return 1 if the notes field and ep match else 0 */
|
|
static int
|
|
notesMatch (XMLEle *ep)
|
|
{
|
|
char *pattern, *string;
|
|
XMLEle *nep;
|
|
int flags, ok;
|
|
|
|
/* find notes entry, fetch pattern and string */
|
|
nep = findXMLEle (ep, ntag);
|
|
if (!nep)
|
|
return (0);
|
|
string = pcdataXMLEle (nep);
|
|
pattern = XmTextGetString (notes_w);
|
|
|
|
/* test */
|
|
flags = 0;
|
|
#if defined(FNM_CASEFOLD) /* GNU extension only */
|
|
flags |= FNM_CASEFOLD;
|
|
#endif
|
|
ok = !fnmatch (pattern, string, flags);
|
|
|
|
/* clean up and return */
|
|
XtFree (pattern);
|
|
return (ok);
|
|
}
|
|
|
|
/* add the current logbook settings to logbook in the private dir */
|
|
static void
|
|
ol_writeLB()
|
|
{
|
|
FILE *fp;
|
|
char buf[1024];
|
|
char cltag[sizeof(lbtag)+10];
|
|
char *str;
|
|
int i;
|
|
|
|
/* need closing tag */
|
|
sprintf (cltag, "</%s>\n", lbtag);
|
|
|
|
/* open or create */
|
|
sprintf (buf, "%s/%s", getPrivateDir(), lbfn);
|
|
fp = fopenh (buf, "r+");
|
|
if (fp) {
|
|
/* found existing log, skip to just before closing tag */
|
|
long offset = ftell (fp);
|
|
while (fgets (buf, sizeof(buf), fp)) {
|
|
if (strcmp (buf, cltag) == 0)
|
|
break;
|
|
offset = ftell (fp);
|
|
}
|
|
if (feof(fp) || ferror(fp)) {
|
|
xe_msg (1, "Can not find %s", cltag);
|
|
return;
|
|
}
|
|
fseek (fp, offset, SEEK_SET);
|
|
} else {
|
|
/* no log, create */
|
|
if (errno != ENOENT || !(fp = fopenh (buf, "w"))) {
|
|
xe_msg (1, "%s:\n %s", buf, syserrstr());
|
|
return;
|
|
}
|
|
fprintf (fp, "<?xml version='1.0'?>\n");
|
|
fprintf (fp, "<%s version='%g'>\n", lbtag, lbver);
|
|
}
|
|
|
|
/* write new entry, notes are special */
|
|
fprintf (fp, " <%s>\n", lbetag);
|
|
for (i = 0; i < NFLDS; i++) {
|
|
LogField *lfp = &logfields[i];
|
|
if (lfp->justlabel)
|
|
continue;
|
|
str = XmTextFieldGetString (lfp->tfw);
|
|
fprintf (fp, " <%s>%s</%s>\n", xmltag(lfp),str,xmltag(lfp));
|
|
XtFree (str);
|
|
}
|
|
str = XmTextGetString (notes_w);
|
|
fprintf (fp, " <%s>\n%s\n </%s>\n", ntag, str, ntag);
|
|
XtFree (str);
|
|
fprintf (fp, " </%s>\n", lbetag);
|
|
|
|
/* finished */
|
|
fprintf (fp, "%s", cltag);
|
|
xe_msg (1, "Added new log entry");
|
|
fclose (fp);
|
|
}
|
|
|
|
/* return str as a double, noting especially dates and sexagesimal angles
|
|
*/
|
|
static double
|
|
numeric (char *str)
|
|
{
|
|
char *lslash = strchr (str, '/');
|
|
char *rslash = strrchr (str, '/');
|
|
|
|
if (lslash && rslash && lslash != rslash) {
|
|
/* 2 distinct /'s so figure it's a date in user's preferred format*/
|
|
double d; int m, y;
|
|
f_sscandate (str, pref_get(PREF_DATE_FORMAT), &m, &d, &y);
|
|
return (y + (m*32 + d)/416); /* ordinal */
|
|
} else {
|
|
double v;
|
|
f_scansexa (str, &v);
|
|
return (v);
|
|
}
|
|
}
|
|
|
|
/* return whether str matches pattern.
|
|
* if pattern starts with < or > treat things numerically, else treat as
|
|
* a wildcard match.
|
|
*/
|
|
static int
|
|
strscmp (char *pattern, char *str)
|
|
{
|
|
int flags;
|
|
|
|
if (pattern[0] == '<')
|
|
return (numeric (str) < numeric (pattern+1));
|
|
if (pattern[0] == '>')
|
|
return (numeric (str) > numeric (pattern+1));
|
|
|
|
flags = 0;
|
|
#if defined(FNM_CASEFOLD) /* GNU extension only */
|
|
flags |= FNM_CASEFOLD;
|
|
#endif
|
|
return (!fnmatch (pattern, str, flags));
|
|
}
|
|
|
|
/* return xml tag for the given logfield */
|
|
static char *
|
|
xmltag (LogField *lfp)
|
|
{
|
|
return (lfp->xml ? lfp->xml : lfp->label);
|
|
}
|
|
|
|
/* find a TextField for a field given its xml tag */
|
|
static Widget
|
|
logfld (char *tag)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < NFLDS; i++)
|
|
if (strcmp (tag, xmltag(&logfields[i])) == 0)
|
|
return (logfields[i].tfw);
|
|
|
|
printf ("Obslog bug: no such tag: %s\n", tag);
|
|
abort();
|
|
}
|
|
|
|
static char *srchtag;
|
|
|
|
static int
|
|
cmp_qsort (const void *v1, const void *v2)
|
|
{
|
|
XMLEle *ep1 = *((XMLEle **)v1);
|
|
XMLEle *ep2 = *((XMLEle **)v2);
|
|
char *sv1 = NULL, *sv2 = NULL;
|
|
XMLEle *ep;
|
|
|
|
for (ep = nextXMLEle (ep1,1); ep != NULL; ep = nextXMLEle(ep1,0)) {
|
|
if (!strcmp (srchtag, tagXMLEle(ep))) {
|
|
sv1 = pcdataXMLEle (ep);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (ep = nextXMLEle (ep2,1); ep != NULL; ep = nextXMLEle(ep2,0)) {
|
|
if (!strcmp (srchtag, tagXMLEle(ep))) {
|
|
sv2 = pcdataXMLEle (ep);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!sv1)
|
|
return (-1);
|
|
if (!sv2)
|
|
return (1);
|
|
return (strnncmp (sv1, sv2));
|
|
}
|
|
|
|
/* sort the array of XML log file elements by the selected key */
|
|
static void
|
|
sortMatches (XMLEle **mpp, int nmpp)
|
|
{
|
|
int (*sortfp) (const void *v1, const void *v2);
|
|
int i;
|
|
|
|
/* find the key, use Object if none set */
|
|
srchtag = NULL;
|
|
for (i = 0; i < NFLDS; i++) {
|
|
LogField *lfp = &logfields[i];
|
|
if (lfp->ktb && XmToggleButtonGetState(lfp->ktb)) {
|
|
srchtag = xmltag (lfp);
|
|
break;
|
|
}
|
|
}
|
|
if (!srchtag) {
|
|
/* use Object */
|
|
for (i = 0; i < NFLDS; i++) {
|
|
LogField *lfp = &logfields[i];
|
|
if (!strcmp (xmltag(lfp), "Object")) {
|
|
srchtag = xmltag (lfp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* sort by the key */
|
|
sortfp = cmp_qsort;
|
|
qsort (mpp, nmpp, sizeof(XMLEle*), sortfp);
|
|
}
|
|
|
|
/* create the observer log list window */
|
|
static void
|
|
oll_create()
|
|
{
|
|
Widget w, fo_w;
|
|
Arg args[20];
|
|
int n;
|
|
|
|
/* create the shell and form */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNallowShellResize, True); n++;
|
|
XtSetArg (args[n], XmNcolormap, xe_cm); n++;
|
|
XtSetArg (args[n], XmNtitle, "xephem Observer's log list"); n++;
|
|
XtSetArg (args[n], XmNiconName, "Log list"); n++;
|
|
XtSetArg (args[n], XmNdeleteResponse, XmUNMAP); n++;
|
|
ollshell_w = XtCreatePopupShell ("LogList", topLevelShellWidgetClass,
|
|
toplevel_w, args, n);
|
|
setup_icon (ollshell_w);
|
|
set_something (olshell_w, XmNcolormap, (XtArgVal)xe_cm);
|
|
sr_reg (ollshell_w, "XEphem*LogList.x", olcategory, 0);
|
|
sr_reg (ollshell_w, "XEphem*LogList.y", olcategory, 0);
|
|
sr_reg (ollshell_w, "XEphem*LogList.width", olcategory, 0);
|
|
sr_reg (ollshell_w, "XEphem*LogList.height", olcategory, 0);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNverticalSpacing, 10); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 10); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 10); n++;
|
|
fo_w = XmCreateForm (ollshell_w, "LL", args, n);
|
|
XtManageChild (fo_w);
|
|
|
|
/* controls attached across the bottom */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 10); n++;
|
|
w = XmCreatePushButton (fo_w, "OLS", args, n);
|
|
set_xmstring (w, XmNlabelString, "Save:");
|
|
XtAddCallback (w, XmNactivateCallback, oll_save_cb, NULL);
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, w); n++;
|
|
XtSetArg (args[n], XmNleftOffset, 10); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 75); n++;
|
|
ollstf_w = XmCreateTextField (fo_w, "filename", args, n);
|
|
XtAddCallback (ollstf_w, XmNactivateCallback, oll_save_cb, NULL);
|
|
XtManageChild (ollstf_w);
|
|
sr_reg (ollstf_w, NULL, olcategory, 1);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 90); n++;
|
|
w = XmCreatePushButton (fo_w, "OLS", args, n);
|
|
set_xmstring (w, XmNlabelString, "Close");
|
|
XtAddCallback (w, XmNactivateCallback, oll_close_cb, NULL);
|
|
XtManageChild (w);
|
|
|
|
/* scrolled text */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNbottomWidget, ollstf_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrows, 24); n++;
|
|
XtSetArg (args[n], XmNcolumns, 82); n++;
|
|
XtSetArg (args[n], XmNeditable, False); n++;
|
|
XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
|
|
XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
|
|
XtSetArg (args[n], XmNblinkRate, 0); n++;
|
|
ollst_w = XmCreateScrolledText (fo_w, "OLST", args, n);
|
|
XtAddEventHandler (ollst_w, ButtonPressMask, False, oll_info_eh, 0);
|
|
XtManageChild (ollst_w);
|
|
}
|
|
|
|
/* save the list text in file named in ollstf_w
|
|
* N.B. don't use call, this is called by a PB and a TF
|
|
*/
|
|
/* ARGSUSED */
|
|
static void
|
|
oll_save_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
char *fn;
|
|
|
|
/* get fn */
|
|
fn = XmTextFieldGetString (ollstf_w);
|
|
if (strlen (fn) == 0) {
|
|
xe_msg (1, "Please enter a file name");
|
|
XtFree (fn);
|
|
return;
|
|
}
|
|
|
|
/* go, perhaps cautiously */
|
|
if (existd (fn,NULL) == 0 && confirm()) {
|
|
char buf[1024];
|
|
(void) sprintf (buf, "%s exists:\nOverwrite?", fn);
|
|
query (ollshell_w, buf, "Yes - overwrite", "No - cancel", NULL,
|
|
oll_save, NULL, NULL);
|
|
} else
|
|
oll_save(); /* just hammer it */
|
|
|
|
/* done with name */
|
|
XtFree (fn);
|
|
}
|
|
|
|
/* write ollst_w to file named in ollstf_w */
|
|
static void
|
|
oll_save()
|
|
{
|
|
char *fn = XmTextFieldGetString (ollstf_w);
|
|
FILE *fp = fopend (fn, NULL, "w");
|
|
char *txt = XmTextGetString (ollst_w);
|
|
fprintf (fp, "%s", txt);
|
|
if (ferror(fp))
|
|
xe_msg (1, "%s:\n%s", fn, syserrstr());
|
|
else
|
|
xe_msg (1, "Wrote %s", fn);
|
|
fclose (fp);
|
|
XtFree (txt);
|
|
XtFree (fn);
|
|
}
|
|
|
|
/* callback from the Close PB in the list window */
|
|
/* ARGSUSED */
|
|
static void
|
|
oll_close_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
XtPopdown (ollshell_w);
|
|
}
|
|
|
|
/* extra ButtonPress handler added to scrolled text.
|
|
* used to provide few more options based on text under pointer.
|
|
* N.B. header offset must agree with printHeadings()
|
|
*/
|
|
static void
|
|
oll_info_eh (Widget w, XtPointer client, XEvent *ev, Boolean *c_to_dispatch)
|
|
{
|
|
XMLEle *me, *ep;
|
|
char *txt, *rastr, *decstr;
|
|
double ra, dec;
|
|
Obj o;
|
|
int pos;
|
|
int r;
|
|
|
|
/* only care about button3 press */
|
|
if (!(ev->type == ButtonPress && ev->xbutton.button == Button3))
|
|
return;
|
|
|
|
/* TODO accommodate notes */
|
|
if (XmToggleButtonGetState(notesltb_w))
|
|
return;
|
|
|
|
/* where are we? */
|
|
pos = XmTextXYToPos (w, ev->xbutton.x, ev->xbutton.y);
|
|
if (pos < 0)
|
|
return;
|
|
|
|
/* find row number */
|
|
txt = XmTextGetString (w);
|
|
for (r = 0; pos > 0; --pos)
|
|
if (txt[pos] == '\n')
|
|
r++;
|
|
XtFree (txt);
|
|
|
|
/* find match, account for header */
|
|
r -= 4;
|
|
if (r < 0 || r >= nmatches)
|
|
return;
|
|
me = matches[r];
|
|
|
|
/* pull out ra/dec, build Obj for mark */
|
|
ep = findXMLEle (me, "RA2000");
|
|
if (!ep)
|
|
return;
|
|
rastr = pcdataXMLEle (ep);
|
|
ep = findXMLEle (me, "Dec2000");
|
|
if (!ep)
|
|
return;
|
|
decstr = pcdataXMLEle (ep);
|
|
f_scansexa (rastr, &ra);
|
|
memset (&o, 0, sizeof(o));
|
|
o.o_type = FIXED;
|
|
o.f_RA = (float)hrrad(ra);
|
|
f_scansexa (decstr, &dec);
|
|
o.f_dec = (float)degrad(dec);
|
|
o.f_epoch = J2000;
|
|
|
|
obj_cir (mm_get_now(), &o);
|
|
sv_point(&o);
|
|
}
|
|
|