/* main() for xephem. * Copyright (c) 1990-2013 by Elwood Charles Downey */ #include #include #include #include #include #if defined(__NUTC__) #include #endif #include #include /* for XT_REVISION */ #include /* define WANT_EDITRES if want to try and support X11R5's EditRes feature. * this will require linking with -lXmu and -lXext too. #define WANT_EDITRES */ #if defined(WANT_EDITRES) && (XT_REVISION >= 5) #define DO_EDITRES #endif #ifdef DO_EDITRES #include #endif #include #include #include #include #include #include #include #include #include #include #if XmVersion >= 1002 #include #endif /* XmVersion >= 1002 */ #include "xephem.h" extern char Version_resource[]; extern char maincategory[]; #define NMINCOL 150 /* min colors we want for the main colormap */ /* these are used to describe and semi-automate making the main pulldown menus */ typedef struct { char *tip; /* tip text, if any */ char *name; /* button name, or separator name if !cb */ /* N.B. watch for a few special cases */ char *label; /* button label (use name if 0) */ char *acc; /* button accelerator, if any */ char *acctext; /* button accelerator text, if any */ char mne; /* button mnemonic */ void (*cb)(); /* button callback, or NULL if none */ XtPointer client; /* button callback client data */ } ButtonInfo; typedef struct { char *tip; /* tip text, if any */ char *cb_name; /* cascade button name */ char *cb_label; /* cascade button label (use name if 0) */ char cb_mne; /* cascade button mnemonic */ char *pd_name; /* pulldown menu name */ ButtonInfo *bip; /* array of ButtonInfos, one per button in pulldown */ int nbip; /* number of entries in bip[] */ } PullDownMenu; #define SEPARATOR_N "MainSep" /* special ButtonInfo->name */ static void addOurDBs (void); static void chk_args (int argc, char *argv[]); static void chk_pos (void); static void chk_version (void); static void set_title (void); static void make_main_window (void); static Widget make_pulldown (Widget mb_w, PullDownMenu *pdmp); static void setup_sigs (void); static void m_activate_cb (Widget w, XtPointer client, XtPointer call); static void x_quit (void); static void initialUps(void); /* client arg to m_activate_cb(). */ typedef enum { PROGRESS, QUIT, GALLERY, MSGTXT, NETSETUP, EXTIN, SUNV, DATA, MOONV, EARTH, MARSV, JUPMOON, SATMOON, UMOON, SKYVIEW, SOLARSYS, PLOT, LIST, SEARCH, GLANCE, AAVSO, CCONV, OBSLOG, EDB, OBJS, CLOSEOBJS, FAVS, FIELDSTARS, WEBDB, MOVIELOOP, ABOUT, REFERENCES, CONFIGHLP, INTRO, MAINMENU, FILEHLP, VIEWHLP, TOOLSHLP, OBJHLP, PREFHLP, OPERATION, CONTEXTHLP, SRCHHLP, DATETIME, NOTES } MBOptions; Widget toplevel_w; #define XtD XtDisplay(toplevel_w) Colormap xe_cm; XtAppContext xe_app; char myclass[] = "XEphem"; #define xephem_width 32 #define xephem_height 32 static unsigned char xephem_bits[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xfe, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0x7f, 0x1e, 0x8e, 0x01, 0xbc, 0x3d, 0xc4, 0x03, 0x7c, 0x7e, 0xe0, 0xe3, 0xbd, 0x7d, 0xe0, 0xe3, 0x7f, 0xfe, 0xf0, 0x63, 0xbf, 0xfd, 0xf0, 0x03, 0x7f, 0xfe, 0xf0, 0x03, 0xbf, 0xfd, 0xf0, 0x63, 0x7f, 0x7e, 0xe0, 0xe3, 0xbf, 0x7d, 0xe0, 0xe3, 0x7d, 0x3e, 0xc2, 0x03, 0xbc, 0x1d, 0x87, 0x01, 0x7c, 0xfe, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0x7f, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55}; static XrmOptionDescRec options[] = { {"--help", ".help", XrmoptionIsArg, NULL}, {"-help", ".help", XrmoptionIsArg, NULL}, {"-install", ".install", XrmoptionSepArg, NULL}, {"-log", ".log", XrmoptionIsArg, NULL}, {"-nowin", ".nowin", XrmoptionIsArg, NULL}, {"-prfb", ".prfb", XrmoptionIsArg, NULL}, {"-resfile", ".resfile", XrmoptionSepArg, NULL}, }; int main(argc, argv) int argc; char *argv[]; { Arg args[10]; int n; /* set up signal handling */ setup_sigs(); /* check for -nosplash or nosplash file .. can't wait for resources */ splashOpen (&argc, argv, options, XtNumber(options)); #ifdef __APPLE__ /* hack around two-level namespace linker problem in libXt wrt libXm. * first appeared in XFree86 4.2.0 build; should remain harmless in * subsequent builds even if the problem is fixed. */ { extern void *topLevelShellClassRec; extern void *transientShellClassRec; extern void *vendorShellClassRec; topLevelShellClassRec = (void *) &vendorShellClassRec; transientShellClassRec = (void *) &vendorShellClassRec; } #endif /* check for alternate env before starting toolkit. * (don't even ask why this is here) */ newEnv(&argc, argv); /* set this before using fallbacks[] */ (void)sprintf (Version_resource,"%s.Version: %s", myclass, PATCHLEVEL); /* open display and gather standard resources. * we grab fallbacks[] last */ splashMsg ("Building shell\n"); n = 0; XtSetArg (args[n], XmNallowShellResize, True); n++; toplevel_w = XtAppInitialize (&xe_app, myclass, options, XtNumber(options), &argc, argv, NULL, args, n); /* add our resources from non-standard places */ splashMsg ("Reading X resources\n"); addOurDBs(); splashMsg ("Checking args\n"); chk_args (argc, argv); chk_version(); set_title(); /* load xe_cm and toplevel_w with default or private colormap */ splashMsg ("Checking colormap\n"); xe_cm = checkCM (DefaultColormap(XtD,DefaultScreen(XtD)), NMINCOL); set_something (toplevel_w, XmNcolormap, (XtArgVal)xe_cm); #ifdef DO_EDITRES XtAddEventHandler (toplevel_w, (EventMask)0, True, _XEditResCheckMessages, NULL); #endif #if WANT_TEAR_OFF /* install converter so tearOffModel can be set in resource files * to TEAR_OFF_{EN,DIS}ABLED. */ XmRepTypeInstallTearOffModelConverter(); #endif /* connect up the icon pixmap */ splashMsg ("Building icon\n"); setup_icon (toplevel_w); /* make the main menu bar and form (other stuff is in mainmenu.c) */ splashMsg ("Building main window system\n"); make_main_window (); /* set up networking, but don't manage it here */ splashMsg ("Init networking\n"); net_create(); /* start in night mode? */ splashMsg ("Checking night mode\n"); sr_chknightv(); /* install then monitor position */ chk_pos(); /* here we go */ splashMsg ("Realizing top widget\n"); XtRealizeWidget(toplevel_w); splashClose(); if (!getXRes ("nowin", NULL)) initialUps(); XtAppMainLoop(xe_app); printf ("XtAppMainLoop returned :-)\n"); return (1); } /* called to put up or remove the watch cursor. */ void main_cursor (c) Cursor c; { Window win; if (toplevel_w && (win = XtWindow(toplevel_w)) != 0) { Display *dsp = XtD; if (c) XDefineCursor (dsp, win, c); else XUndefineCursor (dsp, win); } } /* look for -env arg. * if find replace as specified and remove from argv list. */ void newEnv (int *argcp, char *argv[]) { int argc = *argcp; int i; /* look for any/all -env */ for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-env") == 0) { char *argeq, *newenv; int n; /* new value is in next arg */ if (i == argc-1) { printf ("-env requires another arg\n"); abort(); } newenv = argv[++i]; argeq = strchr (newenv, '='); if (!argeq) { printf ("%s: -env requires X=Y\n", newenv); abort(); } #if defined(__NUTC__) { /* convert filenames to internal format. * N.B. assumes exactly 1 file name */ char *cp, *cpeq; cp = strcpy (malloc (PATH_MAX+1), newenv); cpeq = strchr (cp, '='); (void) _NutPathToNutc (argeq+1, cpeq+1, 1); newenv = cp; } #endif /* install new env */ putenv (newenv); /* remove from argv */ (*argcp) -= 2; for (n = i+1; n < argc; n++) argv[n-2] = argv[n]; } } argv[*argcp] = NULL; } /* connect up logo.gif */ void make_logo (Widget rc) { Display *dsp = XtDisplay(toplevel_w); char fn[1024]; unsigned char gif[200000]; char why[1024]; Arg args[20]; Widget f_w, l_w; Pixmap pm; FILE *fp; int w, h; int ngif; int n; /* open and read the gif */ (void) sprintf (fn, "%s/auxil/logo.gif", getShareDir()); fp = fopenh (fn, "rb"); if (!fp) { (void) fprintf (stderr, "%s: %s\n", fn, syserrstr()); return; /* darn */ } ngif = fread (gif, 1, sizeof(gif), fp); fclose (fp); if (ngif < 0) { (void) fprintf (stderr, "%s: %s\n", fn, syserrstr()); return; /* darn again */ } if (ngif == sizeof(gif)) { (void) fprintf (stderr, "%s: Max size = %d\n", fn,(int)sizeof(gif)); return; /* darn again */ } /* convert to pm */ if (gif2pm (dsp, xe_cm, gif, ngif, &w, &h, &pm, why) < 0) { fprintf (stderr, "%s: %s\n", fn, why); return; /* darn again */ } /* put pm in a label and let it handle it from now on. * put label in a form so it stretches clear across the rc */ n = 0; f_w = XmCreateForm (rc, "LogoForm", args, n); XtManageChild (f_w); n = 0; XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++; XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++; XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++; XtSetArg (args[n], XmNlabelType, XmPIXMAP); n++; XtSetArg (args[n], XmNlabelPixmap, pm); n++; XtSetArg (args[n], XmNalignment, XmALIGNMENT_CENTER); n++; l_w = XmCreateLabel (f_w, "LogoLabel", args, n); wtip (l_w, "The file /auxil/logo.gif"); XtManageChild (l_w); } /* add the xephem icon to shell widget w */ void setup_icon (Widget w) { static Pixmap pm; if (!pm) { Display *dsp = XtDisplay (w); Window win = RootWindow (dsp, DefaultScreen(dsp)); pm = XCreateBitmapFromData (dsp, win, (char *)xephem_bits, xephem_width, xephem_height); } set_something (w, XmNiconPixmap, (XtArgVal)pm); set_something (w, XmNiconMask, (XtArgVal)pm); } /* merge more resource files into final db; harmless if missing. * finally add any fallbacks[] not already in db. */ static void addOurDBs() { XrmDatabase dspdb = XtDatabase (XtD); XrmDatabase fbdb = NULL; char **pp, *p; /* check in TELHOME */ if ((p = getenv("TELHOME")) != NULL) { char fullp[256]; sprintf (fullp, "%s/archive/config/XEphem", p); XrmCombineFileDatabase(fullp, &dspdb, True); } /* then non-standard system-wide */ XrmCombineFileDatabase("/etc/XEphem", &dspdb, True); /* then per-user's so it has max priority */ XrmCombineFileDatabase(userResFile(), &dspdb, True); /* finally add any fallbacks[] not already known */ for (pp = fallbacks; (p = *pp++) != NULL; ) XrmPutLineResource (&fbdb, p); /* creates fbdb if first */ XrmCombineDatabase (fbdb, &dspdb, False); /* Combine evidently uses pointers.. we die if we destroy fbdb XrmDestroyDatabase (fbdb); */ } /* ARGSUSED */ static void chk_args (argc, argv) int argc; char *argv[]; { if (getXRes ("log", NULL)) { /* trouble output, if any, goes to log flie */ char buf[1024]; sprintf (buf, "%s/exitlog.txt", getPrivateDir()); freopen (buf, "at", stdout); freopen (buf, "at", stderr); } if (getXRes ("prfb", NULL)) { String *fbp = fallbacks; for (fbp = fallbacks; *fbp != NULL; fbp++) printf ("%s\n", *fbp); exit (0); } if (argc > 1 || getXRes ("help", NULL)) { fprintf (stderr, "Usage: xephem [options]\n"); fprintf (stderr, "Purpose: interactive astronomical ephemeris.\n"); fprintf (stderr, "Version: %s Build: %s\n", PATCHLEVEL, PATCHDATE); fprintf (stderr, "Options:\n"); fprintf (stderr, " -env N=V : set alternate env Name=Value\n"); fprintf (stderr, " -help : print this message then exit\n"); fprintf (stderr, " -install {yes|no|guess}: whether to install a private colormap\n"); fprintf (stderr, " -log : save exit trouble to private log\n"); fprintf (stderr, " -nosplash : disable splash screen\n"); fprintf (stderr, " -nowin : do not restore windows\n"); fprintf (stderr, " -prfb : print all fallback resources then exit\n"); fprintf (stderr, " -resfile f: load alternate resource file, f\n"); fprintf (stderr, " -splash : enable splash screen\n"); exit (0); } } /* support position of main window in our preferences system */ static void chk_pos() { Position x = (Position)atoi(getXRes ("x", "100")); /* XEphem.x */ Position y = (Position)atoi(getXRes ("y", "100")); /* XEphem.y */ set_something (toplevel_w, XmNx, (XtArgVal)x); set_something (toplevel_w, XmNy, (XtArgVal)y); sr_reg (toplevel_w, "XEphem.x", maincategory, 0); sr_reg (toplevel_w, "XEphem.y", maincategory, 0); } /* insure that resource version and (sometimes) X server matches. */ static void chk_version() { char *v = getXRes ("Version", "??"); if (strcmp (v, PATCHLEVEL)) { printf ("Version skew: Found %s but should be %s\n", v, PATCHLEVEL); abort(); } } static void set_title() { char title[100]; (void) sprintf (title, "XEphem %s", PATCHLEVEL); set_something (toplevel_w, XmNtitle, (XtArgVal) title); } /* put together the menu bar, the main form, and fill in the form with the * initial xephem buttons. */ static void make_main_window () { static ButtonInfo file_buttons[] = { {"Display a dialog containing supporting informational messages", "SysLog", "System log...", 0, 0, 'l', m_activate_cb, (XtPointer)MSGTXT}, {"Display pictures from the Gallery collection", "Gallery", "Gallery...", 0, 0, 'G', m_activate_cb, (XtPointer)GALLERY}, {"Setup networking options", "Net", "Network setup...", 0, 0, 'N', m_activate_cb, (XtPointer)NETSETUP}, {"Set up to run xephem Time and Location from an external file", "ExtIn", "External file...", 0, 0, 'E', m_activate_cb, (XtPointer)EXTIN}, {"Display a simple Progress meter", "Progress", "Progress Meter...", 0, 0, 'P', m_activate_cb, (XtPointer)PROGRESS}, {NULL, SEPARATOR_N}, {"Run 1 Step forward", "Forward1", "Forward 1 Step", "Ctrlf", "Ctrl+f", 'F', mm_go_cb, (XtPointer)1}, {"Run 1 Step backward", "Backward1", "Backward 1 Step", "Ctrlb", "Ctrl+b", 'B', mm_go_cb, (XtPointer)-1}, {"Run or stop the main execution loop", "Update", "Update", "Ctrlu", "Ctrl+u", 'U', mm_go_cb, (XtPointer)0}, {NULL, SEPARATOR_N}, {"Exit xephem", "Quit", "Quit...", "Ctrld", "Ctrl+d", 'Q', m_activate_cb, (XtPointer)QUIT} }; static ButtonInfo view_buttons[] = { {"Display many statistics for any objects", "GenData", "Data Table...", 0, 0, 'D', m_activate_cb, (XtPointer)DATA}, {NULL, SEPARATOR_N}, {"Display an image of the Sun and supporting information", "Sun", "Sun...", 0, 0, 'S', m_activate_cb, (XtPointer)SUNV}, {"Display an image of the Moon and supporting information", "Moon", "Moon...", 0, 0, 'M', m_activate_cb, (XtPointer)MOONV}, {"Display a map of Earth and supporting information", "Earth", "Earth...", 0, 0, 'E', m_activate_cb,(XtPointer)EARTH}, {"Display an image of Mars and supporting information", "Mars", "Mars...", 0, 0, 'r', m_activate_cb, (XtPointer)MARSV}, {"Display a schematic of Jupiter, GRS, its moons, and other info", "Jupiter", "Jupiter...", 0, 0, 'J', m_activate_cb, (XtPointer)JUPMOON}, {"Display schematic of Saturn, its rings and moons, and other info", "Saturn", "Saturn...", 0, 0, 'a', m_activate_cb, (XtPointer)SATMOON}, {"Display schematic of Uranus, its moons, and other info", "Uranus", "Uranus...", 0, 0, 'U', m_activate_cb, (XtPointer)UMOON}, {NULL, SEPARATOR_N}, {"Display a full-featured map of the night sky", "SkyV", "Sky View...", 0, 0, 'V', m_activate_cb, (XtPointer)SKYVIEW}, {"Display a map of the solar system", "SolSys", "Solar System...", 0, 0, 'S', m_activate_cb, (XtPointer)SOLARSYS} }; static ButtonInfo ctrl_buttons[] = { {"Capture any XEphem values for making and displaying plots", "Plot", "Plot values...", 0, 0, 'P', m_activate_cb, (XtPointer)PLOT}, {"Capture any XEphem values in a tabular text file", "List", "List values...", 0, 0, 'L', m_activate_cb, (XtPointer)LIST}, {"Define an equation of XEphem fields and solve for min, max or 0", "Solve", "Solve equation...", 0, 0, 'S', m_activate_cb, (XtPointer)SEARCH}, {"Find all pairs of close objects in memory", "CloseObjs", "Find close pairs...", 0, 0, 'F', m_activate_cb, (XtPointer)CLOSEOBJS}, {"Show twilight and all basic objects on a 24 hour timeline map", "Glance", "Night at a glance...", 0, 0, 'N', m_activate_cb, (XtPointer)GLANCE}, #ifdef AAVSO {"Fetch light curves from AAVSO", "AAVSO", "AAVSO light curves...", 0, 0, 'A', m_activate_cb, (XtPointer)AAVSO}, #endif {"Sky coordinates converter", "Coordinates converter", "Coordinates converter...",0,0,'C', m_activate_cb, (XtPointer)CCONV}, {"Manage Observers log", "ObsLog", "Observers log book...",0,0,'O', m_activate_cb, (XtPointer)OBSLOG}, {"Movie loop control", "MLoop", "Movie loop...", 0, 0,'M', m_activate_cb, (XtPointer)MOVIELOOP}, }; static ButtonInfo objs_buttons[] = { {"Load and delete .edb files to and from memory", "Files", "Files...", 0, 0, 'L', m_activate_cb, (XtPointer)EDB}, {"Search and inspect loaded objects", "Index", "Index...", 0, 0,'S', m_activate_cb, (XtPointer)OBJS}, {"Manage list of favorites", "Favorites", "Favorites...", 0, 0,'F', m_activate_cb, (XtPointer)FAVS}, {"Download .edb or .tle files from web", "WebDB", "Download...", 0, 0, 'I', m_activate_cb, (XtPointer)WEBDB}, {"Setup field star options and catalog locations", "FieldStars", "Field stars...", 0, 0, 'C', m_activate_cb, (XtPointer)FIELDSTARS}, }; static ButtonInfo help_buttons[] = { {"Configure Help system find a browser", "Configure", "Configure help...", 0, 0, 'C', m_activate_cb, (XtPointer)CONFIGHLP}, {"Click here then roam over controls to see help tips", "onContext", "on Context", 0, 0, 'x', m_activate_cb, (XtPointer)CONTEXTHLP}, {"Overall features of xephem", "Introduction", "Introduction...", 0, 0, 'I', m_activate_cb, (XtPointer)INTRO}, {"How to control xephem's running behavior, including looping", "onOperation", "on Operation...", 0, 0, 'e', m_activate_cb, (XtPointer)OPERATION}, {"Shortcuts to setting date and time formats", "onTriad", "on Triad formats...", 0, 0, 'f', m_activate_cb, (XtPointer)DATETIME}, {NULL, SEPARATOR_N}, {"Description of the overall Main xephem menu", "onMainMenu", "on Main Window...", 0, 0, 'M', m_activate_cb, (XtPointer)MAINMENU}, {"Description of the options available under File", "onFile", "on File...", 0, 0, 'F', m_activate_cb, (XtPointer)FILEHLP}, {"Description of the options available under View", "onView", "on View...", 0, 0, 'V', m_activate_cb, (XtPointer)VIEWHLP}, {"Description of the options available under Tools", "onTools", "on Tools...", 0, 0, 'T', m_activate_cb, (XtPointer)TOOLSHLP}, {"Description of the options available under Data", "onObjects", "on Data...", 0, 0, 'D', m_activate_cb, (XtPointer)OBJHLP}, {"Description of the options available under Preferences", "onPrefs", "on Preferences...", 0, 0, 'P', m_activate_cb, (XtPointer)PREFHLP}, {NULL, SEPARATOR_N}, {"Credits, references and other kudos.", "onReferences", "Credits...", 0, 0, 'C', m_activate_cb, (XtPointer)REFERENCES}, {"A few supporting issues", "Notes", "Notes...", 0, 0, 'N', m_activate_cb,(XtPointer)NOTES}, {"Version, copyright, fun graphic", "About", "About...", 0, 0, 'A', m_activate_cb, (XtPointer)ABOUT} }; static PullDownMenu file_pd = {"Overall control functions", "File", 0, 'F', "file_pd", file_buttons,XtNumber(file_buttons)}; static PullDownMenu view_pd = {"Major display options", "View", 0, 'V', "view_pd", view_buttons,XtNumber(view_buttons)}; static PullDownMenu ctrl_pd = {"Supporting analysis tools", "Tools", 0,'T',"ctrl_pd",ctrl_buttons,XtNumber(ctrl_buttons)}; static PullDownMenu objs_pd = {"Add, delete and inspect objects in memory", "Data",0,'D',"objs_pd",objs_buttons,XtNumber(objs_buttons)}; static PullDownMenu help_pd = {"Additional information about xephem and the Main display", "Help", 0, 'H', "help_pd", help_buttons,XtNumber(help_buttons)}; Widget mainrc; Widget mb_w; Widget cb_w; Arg args[20]; int n; /* Create main window as a vertical r/c */ n = 0; XtSetArg (args[n], XmNmarginHeight, 0); n++; XtSetArg (args[n], XmNmarginWidth, 0); n++; mainrc = XmCreateRowColumn (toplevel_w, "XephemMain", args, n); XtAddCallback (mainrc, XmNhelpCallback, m_activate_cb, (XtPointer)MAINMENU); XtManageChild (mainrc); /* connect actions */ splashMsg ("Connecting actions\n"); mm_connActions (); /* Create MenuBar in mainrc */ n = 0; splashMsg ("Building main menu bar\n"); mb_w = XmCreateMenuBar (mainrc, "MB", args, n); XtManageChild (mb_w); /* create each pulldown */ (void) make_pulldown (mb_w, &file_pd); (void) make_pulldown (mb_w, &view_pd); (void) make_pulldown (mb_w, &ctrl_pd); (void) make_pulldown (mb_w, &objs_pd); pref_create_pulldown (mb_w); cb_w = make_pulldown (mb_w, &help_pd); n = 0; XtSetArg (args[n], XmNmenuHelpWidget, cb_w); n++; XtSetValues (mb_w, args, n); /* make a spot for the logo */ splashMsg ("Building logo\n"); make_logo (mainrc); /* add the remainder of the main window */ mm_create (mainrc); } /* create/manage a cascade button with a pulldown menu off a menu bar. * return the cascade button. * N.B. watch for special bip->name. */ static Widget make_pulldown (mb_w, pdmp) Widget mb_w; PullDownMenu *pdmp; { Widget pulldown_w; Widget button; Widget cascade; XmString accstr, labstr; Arg args[20]; int n; int i; /* make the pulldown menu */ n = 0; pulldown_w = XmCreatePulldownMenu (mb_w, pdmp->pd_name, args, n); /* fill it with buttons and/or separators */ for (i = 0; i < pdmp->nbip; i++) { ButtonInfo *bip = &pdmp->bip[i]; int separator = !strcmp (bip->name, SEPARATOR_N); if (separator) { Widget s = XmCreateSeparator (pulldown_w, bip->name, args, n); XtManageChild (s); continue; } accstr = NULL; labstr = NULL; n = 0; if (bip->acctext && bip->acc) { accstr = XmStringCreate(bip->acctext, XmSTRING_DEFAULT_CHARSET); XtSetArg (args[n], XmNacceleratorText, accstr); n++; XtSetArg (args[n], XmNaccelerator, bip->acc); n++; } if (bip->label) { labstr = XmStringCreate (bip->label, XmSTRING_DEFAULT_CHARSET); XtSetArg (args[n], XmNlabelString, labstr); n++; } XtSetArg (args[n], XmNmnemonic, bip->mne); n++; button = XmCreatePushButton (pulldown_w, bip->name, args, n); XtManageChild (button); if (bip->cb) XtAddCallback (button, XmNactivateCallback, bip->cb, (XtPointer)bip->client); if (accstr) XmStringFree (accstr); if (labstr) XmStringFree (labstr); if (bip->tip) wtip (button, bip->tip); } /* create a cascade button and glue them together */ labstr = NULL; n = 0; if (pdmp->cb_label) { labstr = XmStringCreate (pdmp->cb_label, XmSTRING_DEFAULT_CHARSET); XtSetArg (args[n], XmNlabelString, labstr); n++; } XtSetArg (args[n], XmNsubMenuId, pulldown_w); n++; XtSetArg (args[n], XmNmnemonic, pdmp->cb_mne); n++; cascade = XmCreateCascadeButton (mb_w, pdmp->cb_name, args, n); if (labstr) XmStringFree (labstr); XtManageChild (cascade); if (pdmp->tip) wtip (cascade, pdmp->tip); return (cascade); } /* this method of avoiding zombies courtesy Dean Huxley */ static void reapchildren (int signo) { while (wait3(NULL, WNOHANG, NULL) > 0) continue; } static void setup_sigs() { /* ignore FPE, though we do have a matherr() handler in misc.c. */ (void) signal (SIGFPE, SIG_IGN); /* we deal with write errors directly -- don't want the signal */ (void) signal (SIGPIPE, SIG_IGN); /* no zombies */ /* SIG_IGN doesn't do it on netbsd. better to reap. see * http://www.opengroup.org/onlinepubs/007908799/xsh/exit.html * http://www.opengroup.org/onlinepubs/007908799/xsh/sigaction.html * if you /do/ want to wait, the temporarily block SIGCHLD. */ signal (SIGCHLD, reapchildren); } static void hlp_onContext() { static Cursor qc; Display *dsp = XtDisplay (toplevel_w); Window root = RootWindow(dsp, DefaultScreen(dsp)); Window rw, cw; int oldtips; int rx, ry; unsigned int m; int x, y; /* make query cursor */ if (!qc) qc = XCreateFontCursor (dsp, XC_question_arrow); /* grab pointer and allow tips to work until press any button */ if (XGrabPointer (dsp, root, True, ButtonPressMask, GrabModeAsync, GrabModeSync, None, qc, CurrentTime) != GrabSuccess) { xe_msg (1, "Could not grab pointer"); return; } oldtips = pref_get (PREF_TIPS); pref_set (PREF_TIPS, PREF_TIPSON); do { if (!XQueryPointer (dsp, root, &rw, &cw, &rx, &ry, &x, &y, &m)){ xe_msg (1, "XQueryPointer error"); break; } while (XtAppPending(xe_app)) { XEvent e; XtAppNextEvent (xe_app, &e); switch (e.type) { case EnterNotify: case LeaveNotify: case Expose: XtDispatchEvent (&e); break; } } } while (!(m & Button1Mask)); XUngrabPointer (dsp, CurrentTime); /* restore to Preference */ if (oldtips == PREF_NOTIPS) wtip_alldown(); pref_set (PREF_TIPS, oldtips); } /* bring up the initial set of desired windows */ static void initialUps() { if (atoi(getXRes (dm_viewupres(), "0"))) dm_manage(); if (atoi(getXRes (sun_viewupres(), "0"))) sun_manage(); if (atoi(getXRes (m_viewupres(), "0"))) m_manage(); if (atoi(getXRes (e_viewupres(), "0"))) e_manage(); if (atoi(getXRes (mars_viewupres(), "0"))) mars_manage(); if (atoi(getXRes (jm_viewupres(), "0"))) jm_manage(); if (atoi(getXRes (sm_viewupres(), "0"))) sm_manage(); if (atoi(getXRes (um_viewupres(), "0"))) um_manage(); if (atoi(getXRes (sv_viewupres(), "0"))) sv_manage(); if (atoi(getXRes (ss_viewupres(), "0"))) ss_manage(); if (atoi(getXRes (ng_viewupres(), "0"))) ng_manage(); if (atoi(getXRes (mm_autortres(), "0"))) mm_startrt(); } /* main menubar controls callback. * client is one of MBOptions. */ /* ARGSUSED */ static void m_activate_cb (w, client, call) Widget w; XtPointer client; XtPointer call; { int code = (long int)client; watch_cursor(1); switch (code) { case MSGTXT: msg_manage(); break; case NETSETUP: net_manage(); break; case EXTIN: mm_external(); break; case PROGRESS: pm_manage(); break; case QUIT: x_quit(); break; case DATA: dm_manage(); break; case SUNV: sun_manage(); break; case EARTH: e_manage(); break; case MOONV: m_manage(); break; case MARSV: mars_manage(); break; case JUPMOON: jm_manage(); break; case SATMOON: sm_manage(); break; case UMOON: um_manage(); break; case GALLERY: gal_manage(); break; case SKYVIEW: sv_manage(); break; case SOLARSYS: ss_manage(); break; case PLOT: plot_manage(); break; case LIST: lst_manage(); break; case SEARCH: srch_manage(); break; case GLANCE: ng_manage(); break; case AAVSO: av_manage(); break; case CCONV: cc_manage(); break; case OBSLOG: ol_manage(); break; case FAVS: fav_manage(); break; case OBJS: obj_manage(); break; case EDB: db_manage(); break; case CLOSEOBJS: c_manage(); break; case FIELDSTARS:fs_manage(); break; case WEBDB: wdb_manage(); break; case MOVIELOOP: ml_manage(); break; case ABOUT: version(); break; case CONFIGHLP: hlp_config (); break; case REFERENCES:hlp_dialog ("Credits", NULL, 0); break; case INTRO: hlp_dialog ("Intro", NULL, 0); break; case MAINMENU: hlp_dialog ("MainMenu", NULL, 0); break; case FILEHLP: hlp_dialog ("MainMenu_file", NULL, 0); break; case VIEWHLP: hlp_dialog ("MainMenu_view", NULL, 0); break; case TOOLSHLP: hlp_dialog ("MainMenu_tools", NULL, 0); break; case OBJHLP: hlp_dialog ("MainMenu_objects", NULL, 0); break; case PREFHLP: hlp_dialog ("MainMenu_preferences", NULL, 0); break; case OPERATION: hlp_dialog ("Operation", NULL, 0); break; case DATETIME: hlp_dialog ("Date_time", NULL, 0); break; case NOTES: hlp_dialog ("Notes", NULL, 0); break; case CONTEXTHLP:hlp_onContext (); break; default: printf ("Main menu bug: code=%d\n", code); abort(); } watch_cursor(0); } /* outta here */ static void goodbye() { XtCloseDisplay (XtDisplay (toplevel_w)); exit(0); } /* user wants to quit */ static void x_quit() { int nchg = sr_refresh(); if (confirm()) { if (!nchg || (sr_autosaveon() && !sr_save(0)) || sr_isUp()) { query (toplevel_w, "Exit xephem?", " Yes ", " No ", 0, goodbye, 0, 0); } else { query (toplevel_w, "Review unsaved Major\nresources before exiting?", " Yes ", " No ", 0, sr_xmanage, goodbye, 0); } } else { if (nchg > 0 && sr_autosaveon() && sr_save(0) < 0) return; /* abort exit if save failed */ goodbye(); } }