mirror of https://github.com/XEphem/XEphem.git
281 lines
7.6 KiB
C
281 lines
7.6 KiB
C
/* this file contains the code to tigger a browser to display help information.
|
|
* to run IE XEHELPURL to full FAT path of xephem.html, such as :
|
|
* export XEHELPURL='d:\xephem\help\xephem.html'
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/Form.h>
|
|
#include <Xm/PushB.h>
|
|
#include <Xm/ToggleB.h>
|
|
#include <Xm/RowColumn.h>
|
|
#include <Xm/Label.h>
|
|
#include <Xm/TextF.h>
|
|
|
|
#include "xephem.h"
|
|
|
|
char helpcategory[] = "Help"; /* Save category */
|
|
|
|
static void hlp_create (void);
|
|
static void hlp_close_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void hlp_radio_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void runCmd (char *cmd);
|
|
|
|
#define NBROWSER 7 /* browser choices we support */
|
|
typedef struct {
|
|
Widget tb_w; /* selection TB */
|
|
Widget nam_w; /* common name, defs in resources */
|
|
Widget cmd_w; /* command, defs in resources */
|
|
} Browser;
|
|
static Browser browser[NBROWSER]; /* entries for browser specs */
|
|
static Browser *curb; /* pointer to current choice */
|
|
|
|
static Widget hlp_w; /* main help shell */
|
|
|
|
static char help_instructions[] =
|
|
"XEphem uses a web browser to display help. Use this window to define a\n"
|
|
"shell command that sends a URL to your preferred browser. The full URL\n"
|
|
"will be substituted where each %s occurs. Select from the examples or\n"
|
|
"create a line for your browser; they are live so you can test without\n"
|
|
"first closing. Please email us your changes for the user-contrib page.\n";
|
|
|
|
/* trigger help for the given tag.
|
|
* if fail so and use the deflt provided, if any.
|
|
*/
|
|
void
|
|
hlp_dialog (tag, deflt, ndeflt)
|
|
char *tag; /* tag to look for in help file */
|
|
char *deflt[]; /* help text to use if tag not found */
|
|
int ndeflt; /* number of strings in deflt[] */
|
|
{
|
|
static char *hurl;
|
|
static int triedhurl;
|
|
char cmd[1024];
|
|
char url[1024];
|
|
char *fmt;
|
|
int i, l, urll;
|
|
|
|
if (!triedhurl) {
|
|
hurl = getenv ("XEHELPURL");
|
|
triedhurl = 1;
|
|
}
|
|
|
|
if (!hlp_w)
|
|
hlp_create ();
|
|
|
|
if (!curb) {
|
|
xe_msg (1, "Please choose a browser for help");
|
|
return;
|
|
}
|
|
|
|
/* build url with tag and get length */
|
|
if (hurl)
|
|
urll = sprintf (url, "%s#%s", hurl, tag);
|
|
else
|
|
urll = sprintf (url, "file://%s/help/xephem.html#%s",
|
|
getShareDir(), tag);
|
|
|
|
/* scan fmt and sub url for each %s */
|
|
fmt = XmTextFieldGetString (curb->cmd_w);
|
|
for (l = i = 0; fmt[i]; i++) {
|
|
if (fmt[i] == '%' && fmt[i+1] == 's') {
|
|
strcpy (cmd+l, url);
|
|
l += urll;
|
|
i++;
|
|
} else
|
|
cmd[l++] = fmt[i];
|
|
}
|
|
XtFree (fmt);
|
|
|
|
/* run as background */
|
|
strcpy (cmd+l, " &");
|
|
runCmd (cmd);
|
|
}
|
|
|
|
void
|
|
hlp_config (void)
|
|
{
|
|
if (!hlp_w)
|
|
hlp_create ();
|
|
|
|
XtPopup (hlp_w, XtGrabNone);
|
|
set_something (hlp_w, XmNiconic, (XtArgVal)False);
|
|
}
|
|
|
|
/* create the help configuration window (hlp_w).
|
|
*/
|
|
static void
|
|
hlp_create (void)
|
|
{
|
|
Widget w, f_w, l_w;
|
|
Arg args[20];
|
|
int i;
|
|
int n;
|
|
|
|
/* make the help shell and rc */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNcolormap, xe_cm); n++;
|
|
XtSetArg (args[n], XmNiconName, "Help"); n++;
|
|
XtSetArg (args[n], XmNdeleteResponse, XmUNMAP); n++;
|
|
XtSetArg (args[n], XmNtitle, "xephem Help configure"); n++;
|
|
hlp_w = XtCreatePopupShell ("HelpConfig", topLevelShellWidgetClass,
|
|
toplevel_w, args, n);
|
|
setup_icon (hlp_w);
|
|
set_something (hlp_w, XmNcolormap, (XtArgVal)xe_cm);
|
|
sr_reg (hlp_w, "XEphem*HelpConfig.x", helpcategory, 0);
|
|
sr_reg (hlp_w, "XEphem*HelpConfig.y", helpcategory, 0);
|
|
sr_reg (hlp_w, "XEphem*HelpConfig.width", helpcategory, 0);
|
|
|
|
/* make the main form */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNmarginHeight, 10); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 10); n++;
|
|
XtSetArg (args[n], XmNverticalSpacing, 10); n++;
|
|
f_w = XmCreateForm (hlp_w, "HelpF", args, n);
|
|
XtManageChild (f_w);
|
|
|
|
/* make the title label */
|
|
|
|
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++;
|
|
l_w = XmCreateLabel (f_w, "HL", args, n);
|
|
set_xmstring (l_w, XmNlabelString, help_instructions);
|
|
XtManageChild (l_w);
|
|
|
|
/* make each browser control */
|
|
|
|
for (i = 0; i < NBROWSER; i++) {
|
|
Browser *bp = &browser[i];
|
|
Widget topw = i == 0 ? l_w : bp[-1].cmd_w;
|
|
char name[32];
|
|
|
|
/* control TB on left */
|
|
|
|
sprintf (name, "BrowserChoice%d", i);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, topw); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
bp->tb_w = XmCreateToggleButton (f_w, name, args, n);
|
|
XtAddCallback (bp->tb_w, XmNvalueChangedCallback, hlp_radio_cb, 0);
|
|
set_xmstring (bp->tb_w, XmNlabelString, " ");
|
|
wtip (bp->tb_w, "Try using this browser command");
|
|
sr_reg (bp->tb_w, NULL, helpcategory, 1);
|
|
XtManageChild (bp->tb_w);
|
|
if (XmToggleButtonGetState(bp->tb_w))
|
|
curb = bp;
|
|
|
|
/* name */
|
|
|
|
sprintf (name, "BrowserName%d", i);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, topw); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, bp->tb_w); n++;
|
|
XtSetArg (args[n], XmNcolumns, 10); n++;
|
|
bp->nam_w = XmCreateTextField (f_w, name, args, n);
|
|
wtip (bp->nam_w, "Browser name");
|
|
sr_reg (bp->nam_w, NULL, helpcategory, 1);
|
|
XtManageChild (bp->nam_w);
|
|
|
|
/* remainder is command */
|
|
|
|
sprintf (name, "BrowserCmd%d", i);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, topw); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, bp->nam_w); n++;
|
|
XtSetArg (args[n], XmNleftOffset, 10); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
bp->cmd_w = XmCreateTextField (f_w, name, args, n);
|
|
wtip (bp->cmd_w, "Browser command");
|
|
sr_reg (bp->cmd_w, NULL, helpcategory, 1);
|
|
XtManageChild (bp->cmd_w);
|
|
}
|
|
|
|
/* make the Close button */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNtopWidget, browser[NBROWSER-1].cmd_w); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
|
|
XtSetArg (args[n], XmNleftPosition, 30); n++;
|
|
w = XmCreatePushButton (f_w, "Close", args, n);
|
|
wtip (w, "Close this Help window");
|
|
XtAddCallback (w, XmNactivateCallback, hlp_close_cb, 0);
|
|
XtManageChild (w);
|
|
}
|
|
|
|
/* called on Close */
|
|
/* ARGSUSED */
|
|
static void
|
|
hlp_close_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
XtPopdown (hlp_w);
|
|
}
|
|
|
|
/* called when any TB changes */
|
|
/* ARGSUSED */
|
|
static void
|
|
hlp_radio_cb (Widget w, XtPointer client, XtPointer call)
|
|
{
|
|
int set = XmToggleButtonGetState(w);
|
|
int i;
|
|
|
|
if (!set)
|
|
return;
|
|
|
|
/* we are coming on, save in curb and turn all others off */
|
|
for (i = 0; i < NBROWSER; i++) {
|
|
if (browser[i].tb_w == w)
|
|
curb = &browser[i];
|
|
else
|
|
XmToggleButtonSetState (browser[i].tb_w, False, False);
|
|
}
|
|
}
|
|
|
|
/* run the given shell command, return immediately.
|
|
*/
|
|
static void
|
|
runCmd (char *cmd)
|
|
{
|
|
int i, pid;
|
|
|
|
/* log cmd */
|
|
xe_msg (0, "Running '%s'", cmd);
|
|
|
|
/* launch in new shell, parent resumes */
|
|
pid = fork();
|
|
if (pid < 0) {
|
|
xe_msg (1, "fork: %s", syserrstr());
|
|
return;
|
|
}
|
|
if (pid == 0) {
|
|
/* child execs sh to run cmd */
|
|
for (i = 3; i < 100; i++)
|
|
close (i);
|
|
execl ("/bin/sh", "sh", "-c", cmd, NULL);
|
|
_exit(1);
|
|
}
|
|
|
|
/* N.B. we depend on SIGCHLD/reapchildren() in main to avoid zombies */
|
|
}
|
|
|