mirror of https://github.com/XEphem/XEphem.git
679 lines
17 KiB
C
679 lines
17 KiB
C
/* code to manage the picture gallery window
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <dirent.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/Form.h>
|
|
#include <Xm/Frame.h>
|
|
#include <Xm/Label.h>
|
|
#include <Xm/PushB.h>
|
|
#include <Xm/PanedW.h>
|
|
#include <Xm/CascadeB.h>
|
|
#include <Xm/ToggleB.h>
|
|
#include <Xm/ScrolledW.h>
|
|
#include <Xm/List.h>
|
|
#include <Xm/Text.h>
|
|
#include <Xm/Separator.h>
|
|
|
|
#include "lilxml.h"
|
|
#include "xephem.h"
|
|
|
|
static XMLEle *selGIP (void);
|
|
static Obj *selInDB (void);
|
|
static int gt_cmp (const void *g0, const void *g1);
|
|
static int namefind (char *name);
|
|
static void gal_create_shell (void);
|
|
static void gal_help_cb (Widget w, XtPointer client, XtPointer data);
|
|
static void gal_popdown_cb (Widget w, XtPointer client, XtPointer data);
|
|
static void gal_close_cb (Widget w, XtPointer client, XtPointer data);
|
|
static void gal_rescan_cb (Widget w, XtPointer client, XtPointer data);
|
|
static void gal_sel_cb (Widget w, XtPointer client, XtPointer data);
|
|
static void gal_skypt_cb (Widget w, XtPointer client, XtPointer data);
|
|
static void galReset (void);
|
|
static void addName(XMLEle *np);
|
|
static void read1Catalog (FILE *fp, XMLEle **dp, char *idxpath);
|
|
static void readCatalogs (void);
|
|
static void fillReport (XMLEle *name);
|
|
static void fillImage (XMLEle *name);
|
|
static void fillList(void);
|
|
static char *trimws (char *s);
|
|
|
|
static Widget galshell_w; /* main shell */
|
|
static Widget report_w; /* TF for showing info */
|
|
static Widget sel_w; /* SL for picking picture */
|
|
static Widget pl_w; /* picture label */
|
|
static Widget sky_w; /* sky-point PB */
|
|
static Widget psw_w; /* picture scroller window */
|
|
|
|
static char *sdir; /* handy malloced path to shared gallery dir */
|
|
static char *pdir; /* handy malloced path to private gallery dir */
|
|
|
|
static XMLEle *galroot[2]; /* XML doc tree for the shar and priv gallery */
|
|
static XMLEle **gallery; /* malloced pointers to all <name> elements */
|
|
static int ngallery; /* n gallery entries in use */
|
|
static int mgallery; /* n gallery entries malloced */
|
|
#define NMALINC 100 /* n to grow gallery[] each time */
|
|
|
|
static char galcategory[] = "Image Gallery";
|
|
|
|
/* bring up the picture menu, creating if first time */
|
|
void
|
|
gal_manage()
|
|
{
|
|
if (!galshell_w) {
|
|
gal_create_shell();
|
|
readCatalogs();
|
|
fillList();
|
|
if (ngallery > 0)
|
|
XmListSelectPos (sel_w, 1, True); /* show first */
|
|
}
|
|
|
|
XtPopup (galshell_w, XtGrabNone);
|
|
set_something (galshell_w, XmNiconic, (XtArgVal)False);
|
|
}
|
|
|
|
/* return index of first gallery entry with any name for op, else -1.
|
|
* ignore case and whitespace
|
|
*/
|
|
int
|
|
gal_opfind (Obj *op)
|
|
{
|
|
DupName *dnp;
|
|
int i, ndn, gi;
|
|
|
|
/* first try primary name */
|
|
gi = namefind (op->o_name);
|
|
if (gi >= 0)
|
|
return (gi);
|
|
|
|
/* then try other entries in dup name list */
|
|
ndn = db_dups (&dnp);
|
|
for (i = 0; i < ndn; i++) {
|
|
if (dnp[i].op == op && strcmp (dnp[i].nm, op->o_name)) {
|
|
gi = namefind (dnp[i].nm);
|
|
if (gi >= 0)
|
|
return (gi);
|
|
}
|
|
}
|
|
|
|
/* nope */
|
|
return (-1);
|
|
}
|
|
|
|
/* scroll to and display gallery entry for given object, if any */
|
|
void
|
|
gal_opscroll (Obj *op)
|
|
{
|
|
int i = gal_opfind (op);
|
|
|
|
if (i < 0)
|
|
return;
|
|
|
|
if (!isUp (galshell_w))
|
|
gal_manage();
|
|
|
|
/* select item (1 based!) and let its callback put up the image */
|
|
XmListSelectPos (sel_w, i+1, True);
|
|
XmListSetPos (sel_w, i+1); /* selecting does not scroll too */
|
|
}
|
|
|
|
/* called to put up or remove the watch cursor. */
|
|
void
|
|
gal_cursor (Cursor c)
|
|
{
|
|
Window win;
|
|
|
|
if (galshell_w && (win = XtWindow(galshell_w)) != 0) {
|
|
Display *dsp = XtDisplay(galshell_w);
|
|
if (c)
|
|
XDefineCursor (dsp, win, c);
|
|
else
|
|
XUndefineCursor (dsp, win);
|
|
}
|
|
}
|
|
|
|
/* create a shell to allow user to manage pictures . */
|
|
static void
|
|
gal_create_shell ()
|
|
{
|
|
Widget h_w, pw_w;
|
|
Widget galform_w;
|
|
Widget w;
|
|
Arg args[20];
|
|
int n;
|
|
|
|
/* create outter shell and form */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNcolormap, xe_cm); n++;
|
|
XtSetArg (args[n], XmNtitle, "xephem Image Gallery"); n++;
|
|
XtSetArg (args[n], XmNiconName, "Gallery"); n++;
|
|
XtSetArg (args[n], XmNdeleteResponse, XmUNMAP); n++;
|
|
galshell_w = XtCreatePopupShell ("Gallery", topLevelShellWidgetClass,
|
|
toplevel_w, args, n);
|
|
set_something (galshell_w, XmNcolormap, (XtArgVal)xe_cm);
|
|
XtAddCallback (galshell_w, XmNpopdownCallback, gal_popdown_cb, NULL);
|
|
setup_icon (galshell_w);
|
|
sr_reg (galshell_w, "XEphem*Gallery.x", galcategory, 0);
|
|
sr_reg (galshell_w, "XEphem*Gallery.y", galcategory, 0);
|
|
sr_reg (galshell_w, "XEphem*Gallery.height", galcategory, 0);
|
|
sr_reg (galshell_w, "XEphem*Gallery.width", galcategory, 0);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNmarginWidth, 10); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 10); n++;
|
|
XtSetArg (args[n], XmNverticalSpacing, 10); n++;
|
|
XtSetArg (args[n], XmNhorizontalSpacing, 10); n++;
|
|
galform_w = XmCreateForm (galshell_w, "GalF", args, n);
|
|
XtAddCallback (galform_w, XmNhelpCallback, gal_help_cb, 0);
|
|
XtManageChild(galform_w);
|
|
|
|
/* controls across the bottom */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 8); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 23); n++;
|
|
w = XmCreatePushButton (galform_w, "Close", args, n);
|
|
XtAddCallback (w, XmNactivateCallback, gal_close_cb, NULL);
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 31); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 46); n++;
|
|
w = XmCreatePushButton (galform_w, "Rescan", args, n);
|
|
XtAddCallback (w, XmNactivateCallback, gal_rescan_cb, NULL);
|
|
wtip (w, "Search again for gallery images");
|
|
XtManageChild (w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 54); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 69); n++;
|
|
sky_w = XmCreatePushButton (galform_w, "GS", args, n);
|
|
XtAddCallback (sky_w, XmNactivateCallback, gal_skypt_cb, NULL);
|
|
set_xmstring (sky_w, XmNlabelString, "Sky Point");
|
|
wtip (sky_w, "Zoom Sky View to this object");
|
|
XtManageChild (sky_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 77); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNrightPosition, 92); n++;
|
|
h_w = XmCreatePushButton (galform_w, "Help", args, n);
|
|
XtAddCallback (h_w, XmNactivateCallback, gal_help_cb, NULL);
|
|
XtManageChild (h_w);
|
|
|
|
/* scrolled list on right */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNbottomWidget, h_w); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNwidth, 150); n++;
|
|
XtSetArg (args[n], XmNselectionPolicy, XmBROWSE_SELECT); n++;
|
|
sel_w = XmCreateScrolledList (galform_w, "GalSL", args, n);
|
|
XtAddCallback (sel_w, XmNbrowseSelectionCallback, gal_sel_cb, NULL);
|
|
XtManageChild (sel_w);
|
|
|
|
/* paned window */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNbottomWidget, h_w); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNrightWidget, XtParent(sel_w)); n++;
|
|
XtSetArg (args[n], XmNsashHeight, 10); n++;
|
|
XtSetArg (args[n], XmNspacing, 14); n++;
|
|
pw_w = XmCreatePanedWindow (galform_w, "GalPW", args, n);
|
|
XtManageChild (pw_w);
|
|
|
|
/* scrolled window on top for image */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
|
|
psw_w = XmCreateScrolledWindow (pw_w, "GalSW", args, n);
|
|
XtManageChild (psw_w);
|
|
|
|
/* workarea is label for picture pixmap - easy! */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNrecomputeSize, True); n++;
|
|
XtSetArg (args[n], XmNlabelType, XmPIXMAP); n++;
|
|
pl_w = XmCreateLabel (psw_w, "GalDL", args, n);
|
|
XtManageChild (pl_w);
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNworkWindow, pl_w); n++;
|
|
XtSetValues (psw_w, args, n);
|
|
|
|
/* scrolled text below for report */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNeditable, False); n++;
|
|
XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
|
|
XtSetArg (args[n], XmNwordWrap, True); n++;
|
|
XtSetArg (args[n], XmNscrollHorizontal, False); n++;
|
|
XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
|
|
XtSetArg (args[n], XmNskipAdjust, True); n++;
|
|
report_w = XmCreateScrolledText (pw_w, "Report", args, n);
|
|
sr_reg (report_w, "XEphem*Gallery*Report.height", galcategory, 0);
|
|
XtManageChild (report_w);
|
|
}
|
|
|
|
/* read files and create gallery[]
|
|
*/
|
|
static void
|
|
readCatalogs()
|
|
{
|
|
char buf[1024];
|
|
char *dir[2];
|
|
int i;
|
|
|
|
/* reset current list, if any */
|
|
galReset();
|
|
|
|
/* init dir names */
|
|
if (!sdir) {
|
|
sprintf (buf, "%s/gallery", getShareDir());
|
|
sdir = XtNewString (buf); /* beware Rescan */
|
|
sprintf (buf, "%s/gallery", getPrivateDir());
|
|
pdir = XtNewString (buf); /* beware Rescan */
|
|
}
|
|
dir[0] = sdir;
|
|
dir[1] = pdir;
|
|
|
|
/* search shared and private dirs */
|
|
for (i = 0; i < XtNumber(dir); i++) {
|
|
struct dirent *dp;
|
|
DIR *dirp;
|
|
FILE *fp;
|
|
|
|
dirp = opendir (dir[i]);
|
|
if (!dirp)
|
|
continue;
|
|
|
|
while ((dp = readdir (dirp)) != NULL) {
|
|
if (strcmp (dp->d_name+strlen(dp->d_name)-4, ".gly") == 0) {
|
|
sprintf (buf, "%s/%s", dir[i], dp->d_name);
|
|
fp = fopenh (buf, "r");
|
|
if (fp) {
|
|
read1Catalog (fp, &galroot[i], buf);
|
|
fclose (fp);
|
|
} else if (errno != ENOENT) {
|
|
xe_msg (1, "%s:\n%s", buf, syserrstr());
|
|
}
|
|
}
|
|
}
|
|
|
|
closedir (dirp);
|
|
}
|
|
}
|
|
|
|
/* read in a gallery index, save XML doc in *dp, add to gallery[] */
|
|
static void
|
|
read1Catalog (FILE *fp, XMLEle **dp, char *idxpath)
|
|
{
|
|
LilXML *lp = newLilXML();
|
|
XMLEle *root = NULL;
|
|
XMLEle *ep, *ip;
|
|
int c;
|
|
|
|
/* collect gallery element */
|
|
while ((c = fgetc(fp)) != EOF) {
|
|
char buf[1024];
|
|
root = readXMLEle (lp, c, buf);
|
|
if (root)
|
|
break;
|
|
if (buf[0]) {
|
|
xe_msg (1, "%s:\n%s", idxpath, buf);
|
|
return;
|
|
}
|
|
}
|
|
if (!root || strcmp (tagXMLEle(root), "gallery")) {
|
|
xe_msg (1, "%s:\ngallery element not found", idxpath);
|
|
return;
|
|
}
|
|
|
|
/* add one element to gallery[] for each name */
|
|
for (ep = nextXMLEle(root,1); ep != NULL; ep = nextXMLEle(root,0))
|
|
if (!strcmp (tagXMLEle(ep), "image"))
|
|
for (ip = nextXMLEle(ep,1); ip != NULL; ip = nextXMLEle(ep,0))
|
|
if (!strcmp (tagXMLEle(ip), "name"))
|
|
addName (ip);
|
|
|
|
/* save doc, don't need lil scanner any more */
|
|
*dp = root;
|
|
delLilXML (lp);
|
|
}
|
|
|
|
/* compare pcdata in two XMLEle **, qsort-style */
|
|
static int
|
|
gt_cmp (const void *e1, const void *e2)
|
|
{
|
|
return (strnncmp (pcdataXMLEle(*(XMLEle **)e1), pcdataXMLEle(*(XMLEle **)e2)));
|
|
}
|
|
|
|
|
|
/* fill the target selection list from gallery[] which is a list of name elems.
|
|
*/
|
|
static void
|
|
fillList()
|
|
{
|
|
XmString *xmstrtbl;
|
|
int i;
|
|
|
|
/* sort galery by name */
|
|
qsort (gallery, ngallery, sizeof(gallery[0]), gt_cmp);
|
|
|
|
/* create tmp list of XmStrings */
|
|
xmstrtbl = (XmString *) XtMalloc (ngallery * sizeof(XmString));
|
|
for (i = 0; i < ngallery; i++)
|
|
xmstrtbl[i]= XmStringCreateSimple(trimws(pcdataXMLEle(gallery[i])));
|
|
|
|
/* replace list */
|
|
XtUnmanageChild (sel_w);
|
|
XmListDeleteAllItems (sel_w);
|
|
XmListAddItems (sel_w, xmstrtbl, ngallery, 0);
|
|
XtManageChild (sel_w);
|
|
|
|
/* clean up tmp list */
|
|
for (i = 0; i < ngallery; i++)
|
|
XmStringFree (xmstrtbl[i]);
|
|
XtFree ((char *)xmstrtbl);
|
|
}
|
|
|
|
/* Using info from XML name element nep, fill description in report_w */
|
|
static void
|
|
fillReport (XMLEle *nep)
|
|
{
|
|
XMLEle *p, *e;
|
|
int l;
|
|
|
|
/* new report */
|
|
XtUnmanageChild (report_w);
|
|
XmTextSetString (report_w, "");
|
|
|
|
/* add each name one per line */
|
|
p = parentXMLEle (nep);
|
|
l = 0;
|
|
for (e = nextXMLEle(p,1); e != NULL; e = nextXMLEle(p,0)) {
|
|
if (strcmp (tagXMLEle(e), "name") == 0) {
|
|
char *name = pcdataXMLEle(e);
|
|
XmTextInsert (report_w, l, name);
|
|
l += strlen (name);
|
|
XmTextInsert (report_w, l++, "\n");
|
|
}
|
|
}
|
|
XmTextInsert (report_w, l++, "\n");
|
|
|
|
/* add description. replace isolated \n with blank so widget can do
|
|
* the wrapping
|
|
*/
|
|
e = findXMLEle (p, "description");
|
|
if (e) {
|
|
char *dp, *des = pcdataXMLEle (e);
|
|
for (dp = des; *dp; dp++)
|
|
if (dp[0] == '\n' && dp[-1] != '\n' && dp[1] != '\n')
|
|
*dp = ' ';
|
|
XmTextInsert (report_w, l, des);
|
|
}
|
|
|
|
/* show */
|
|
XmTextShowPosition (report_w, 0);
|
|
XtManageChild (report_w);
|
|
}
|
|
|
|
/* Using info from XML name element nep, fill in the display image */
|
|
static void
|
|
fillImage (XMLEle *nep)
|
|
{
|
|
static XColor xcol[256];
|
|
static int xcolset;
|
|
XMLEle *f;
|
|
Pixmap oldpm, pm;
|
|
char buf[1024];
|
|
char *fn;
|
|
FILE *fp;
|
|
int w, h;
|
|
|
|
/* open file, look in private then shared dirs */
|
|
f = findXMLEle (parentXMLEle (nep), "file");
|
|
if (!f) {
|
|
xe_msg (1, "Gallery entry %s has no file", pcdataXMLEle(nep));
|
|
return;
|
|
}
|
|
fn = trimws(pcdataXMLEle(f));
|
|
sprintf (buf, "%s/%s", pdir, fn);
|
|
fp = fopenh (buf, "r");
|
|
if (!fp) {
|
|
sprintf (buf, "%s/%s", sdir, fn);
|
|
fp = fopenh (buf, "r");
|
|
if (!fp) {
|
|
xe_msg (1, "%s:\n%s", fn, syserrstr());
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* free last batch of colors */
|
|
if (xcolset) {
|
|
freeXColors (XtD, xe_cm, xcol, XtNumber(xcol));
|
|
xcolset = 0;
|
|
}
|
|
|
|
/* create the expose pixmap */
|
|
if (jpeg2pm (XtD, xe_cm, fp, &w, &h, &pm, xcol, buf) < 0) {
|
|
xe_msg (1, "%s:\n%s", fn, buf);
|
|
fclose (fp);
|
|
return;
|
|
}
|
|
xcolset = 1;
|
|
|
|
/* replace label pixmap and center */
|
|
get_something (pl_w, XmNlabelPixmap, (XtArgVal)&oldpm);
|
|
if (oldpm != XmUNSPECIFIED_PIXMAP)
|
|
XFreePixmap (XtD, oldpm);
|
|
set_something (pl_w, XmNlabelPixmap, (XtArgVal)pm);
|
|
centerScrollBars(psw_w);
|
|
|
|
/* clean up */
|
|
fclose (fp);
|
|
}
|
|
|
|
/* add the given <name> element to the gallery list, growing if necessary */
|
|
static void
|
|
addName(XMLEle *np)
|
|
{
|
|
if (ngallery == mgallery)
|
|
gallery = (XMLEle **) XtRealloc ((char *)gallery,
|
|
(mgallery+=NMALINC)*sizeof(XMLEle *));
|
|
gallery[ngallery++] = np;
|
|
}
|
|
|
|
/* return index of first gallery entry with name, else -1.
|
|
* ignore case and whitespace
|
|
*/
|
|
static int
|
|
namefind (char *name)
|
|
{
|
|
int t, b;
|
|
|
|
/* binary search */
|
|
t = ngallery-1;
|
|
b = 0;
|
|
while (b <= t) {
|
|
int m = (t+b)/2;
|
|
int c = strnncmp (name, pcdataXMLEle(gallery[m]));
|
|
if (c == 0)
|
|
return (m);
|
|
if (c < 0)
|
|
t = m-1;
|
|
else
|
|
b = m+1;
|
|
}
|
|
|
|
return (-1);
|
|
}
|
|
|
|
/* reclaim all storage used for the current gallery */
|
|
static void
|
|
galReset()
|
|
{
|
|
if (galroot[0]) {
|
|
delXMLEle (galroot[0]);
|
|
galroot[0] = NULL;
|
|
}
|
|
if (galroot[1]) {
|
|
delXMLEle (galroot[1]);
|
|
galroot[1] = NULL;
|
|
}
|
|
if (gallery) {
|
|
/* pointers in this list were in galroot -- already freed */
|
|
XtFree ((char *)gallery);
|
|
gallery = NULL;
|
|
}
|
|
ngallery = mgallery = 0;
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
gal_help_cb (Widget w, XtPointer client, XtPointer data)
|
|
{
|
|
static char *msg[] = {
|
|
"This tool opens and displays picture in the gallery"
|
|
};
|
|
|
|
hlp_dialog ("Gallery", msg, XtNumber(msg));
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
gal_popdown_cb (Widget w, XtPointer client, XtPointer data)
|
|
{
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
gal_close_cb (Widget w, XtPointer client, XtPointer data)
|
|
{
|
|
XtPopdown (galshell_w);
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
gal_rescan_cb (Widget w, XtPointer client, XtPointer data)
|
|
{
|
|
readCatalogs();
|
|
fillList();
|
|
XtSetSensitive(sky_w, False);
|
|
}
|
|
|
|
/* called when a list selection is made */
|
|
/* ARGSUSED */
|
|
static void
|
|
gal_sel_cb (Widget w, XtPointer client, XtPointer data)
|
|
{
|
|
XMLEle *nep;
|
|
|
|
nep = selGIP();
|
|
if (!nep)
|
|
return;
|
|
|
|
watch_cursor (1);
|
|
fillReport (nep);
|
|
fillImage (nep);
|
|
XtSetSensitive (sky_w, !!selInDB());
|
|
watch_cursor (0);
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
gal_skypt_cb (Widget w, XtPointer client, XtPointer data)
|
|
{
|
|
Obj *op = selInDB();
|
|
|
|
if (op) {
|
|
db_update (op);
|
|
sv_point (op);
|
|
}
|
|
}
|
|
|
|
/* scan db for object whose name matches that which is currently selected.
|
|
* if find return ptr, else NULL
|
|
*/
|
|
static Obj *
|
|
selInDB ()
|
|
{
|
|
DupName *dnp;
|
|
int ndn = db_dups(&dnp);
|
|
XMLEle *nep;
|
|
int i;
|
|
|
|
nep = selGIP();
|
|
if (!nep)
|
|
return (NULL);
|
|
|
|
for (i = 0; i < ndn; i++)
|
|
if (!strnncmp (pcdataXMLEle(nep), dnp[i].nm))
|
|
return (dnp[i].op);
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
/* return pointer to <name> element of currently selected target, else NULL */
|
|
XMLEle *
|
|
selGIP ()
|
|
{
|
|
int *pos, npos;
|
|
XMLEle *nep;
|
|
|
|
if (!XmListGetSelectedPos (sel_w, &pos, &npos))
|
|
return (NULL);
|
|
nep = gallery[pos[0]-1]; /* List is 1-based */
|
|
XtFree ((char *)pos);
|
|
return (nep);
|
|
}
|
|
|
|
/* trim trailing whitespace off s[] both ends IN PLACE */
|
|
static char *
|
|
trimws (char *s)
|
|
{
|
|
char *s0;
|
|
|
|
while (isspace(*s))
|
|
s++;
|
|
s0 = s;
|
|
|
|
while (*s)
|
|
s++;
|
|
|
|
do
|
|
*s-- = '\0';
|
|
while (s >= s0 && isspace(*s));
|
|
|
|
return (s0);
|
|
}
|
|
|
|
|