home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part07 / calmenu.c next >
Encoding:
C/C++ Source or Header  |  1993-05-15  |  10.6 KB  |  391 lines

  1. /* stuff to control the calendar in the main menu.
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <math.h>
  7. #if defined(__STDC__)
  8. #include <stdlib.h>
  9. #endif
  10. #include <X11/Xlib.h>
  11. #include <Xm/Xm.h>
  12. #include <Xm/Form.h>
  13. #include <Xm/Label.h>
  14. #include <Xm/PushB.h>
  15. #include <Xm/CascadeB.h>
  16. #include <Xm/RowColumn.h>
  17. #include "astro.h"
  18. #include "circum.h"
  19.  
  20. #if defined(__STDC__) || defined(__cplusplus)
  21. #define P_(s) s
  22. #else
  23. #define P_(s) ()
  24. #endif
  25.  
  26. extern Now *mm_get_now P_((void));
  27. extern double mjd_day P_((double jd));
  28. extern double mjd_hr P_((double jd));
  29. extern void cal_mjd P_((int mn, double dy, int yr, double *Mjd));
  30. extern void f_showit P_((Widget w, char *s));
  31. extern void get_something P_((Widget w, char *resource, char *value));
  32. extern void mjd_cal P_((double Mjd, int *mn, double *dy, int *yr));
  33. extern void mjd_dow P_((double Mjd, int *dow));
  34. extern void mjd_dpm P_((double Mjd, int *ndays));
  35. extern void mm_newcaldate P_((double newmjd));
  36. extern void moonnf P_((double Mjd, double *mjdn, double *mjdf));
  37. extern void set_something P_((Widget w, char *resource, char *value));
  38. extern void time_fromsys P_((Now *np));
  39.  
  40. Widget calm_create P_((Widget parent));
  41. void calm_set P_((Now *np));
  42. static void today_cb P_((Widget w, XtPointer client, XtPointer call));
  43. static void date_changed_cb P_((Widget w, XtPointer client, XtPointer call));
  44. static void mm_nfmoon P_((double jd, int m, int f));
  45.  
  46. #undef P_
  47.  
  48. #define    CAL_ROWS    6        /* rows in the date matrix */
  49. #define    CAL_COLS    7        /* columns in the date matrix */
  50. #define    NYEARS        12        /* num entries in the year pulldown */
  51. #define    NMONTHS        12        /* num entries in the month pulldown */
  52. static Widget m_w, mmenu_w[NMONTHS];    /* month cascade btn and pulldwn menu */
  53. static Widget y_w, ymenu_w[NYEARS];    /* year cascade btn and pulldwn menu */
  54. static Widget d_w[CAL_ROWS*CAL_COLS];    /* pushbtns in the date matrix */
  55.  
  56. /* must all be fixed-width since XmMENU_BAR RowColumns don't allow for resizing.
  57.  */
  58. static char mnames[][10] = {
  59.     "January ", "February ", "March    ", "April    ", "May      ", "June     ",
  60.     "July    ", "August   ", "September", "October  ", "November ", "December "
  61. };
  62. static char dnames[CAL_COLS][3] = {
  63.     "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"
  64. };
  65.  
  66. enum {DAY, MONTH, YEAR};
  67.  
  68. static Pixel fg_pix, bg_pix;        /* used to reverse colors "today" */
  69.  
  70. #define    NO_DATE    (999)            /* anything outside -31..31 */
  71.  
  72. /* create a calendar from parent and return the outtermost widget.
  73.  */
  74. Widget
  75. calm_create (parent)
  76. Widget parent;
  77. {
  78.     Arg args[20];
  79.     Widget form_w;
  80.     Widget rc_w;
  81.     Widget menu_w;
  82.     Widget w;
  83.     int n;
  84.     int i;
  85.  
  86.     /* create the outter form */
  87.  
  88.     n = 0;
  89.     form_w = XmCreateForm (parent, "CalForm", args, n);
  90.  
  91.     /* create the Year cascade button/pulldown menu */
  92.  
  93.     n = 0;
  94.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  95.     XtSetArg (args[n], XmNtopOffset, 2); n++;
  96.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  97.     XtSetArg (args[n], XmNrightOffset, 3); n++;
  98.     XtSetArg (args[n], XmNrowColumnType, XmMENU_BAR); n++;
  99.     XtSetArg (args[n], XmNmarginHeight, 1); n++;
  100.     XtSetArg (args[n], XmNmarginWidth, 1); n++;
  101.     XtSetArg (args[n], XmNshadowThickness, 1); n++;
  102.     rc_w = XmCreateRowColumn (form_w, "YearRC", args, n);
  103.     XtManageChild (rc_w);
  104.  
  105.     n = 0;
  106.     menu_w = XmCreatePulldownMenu (form_w, "YearPD", args, n);
  107.     /* managed by the CascadeButton */
  108.  
  109.         for (i = 0; i < NYEARS; i++) {
  110.         n = 0;
  111.         w = XmCreatePushButton (menu_w, "YearPB", args, n);
  112.         XtAddCallback (w, XmNactivateCallback, date_changed_cb,
  113.                                 (XtPointer)YEAR);
  114.         XtManageChild (w);
  115.         ymenu_w[i] = w;
  116.         }
  117.  
  118.     n = 0;
  119.     XtSetArg (args[n], XmNsubMenuId, menu_w); n++;
  120.     y_w = XmCreateCascadeButton (rc_w, "YearCB", args, n);
  121.     XtManageChild (y_w);
  122.  
  123.     /* create the Month cascade button/pulldown menu.
  124.      */
  125.  
  126.     n = 0;
  127.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  128.     XtSetArg (args[n], XmNtopOffset, 2); n++;
  129.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  130.     XtSetArg (args[n], XmNleftOffset, 3); n++;
  131.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  132.     XtSetArg (args[n], XmNrightWidget, rc_w); n++;
  133.     XtSetArg (args[n], XmNrowColumnType, XmMENU_BAR); n++;
  134.     XtSetArg (args[n], XmNmarginHeight, 1); n++;
  135.     XtSetArg (args[n], XmNmarginWidth, 1); n++;
  136.     XtSetArg (args[n], XmNshadowThickness, 1); n++;
  137.     rc_w = XmCreateRowColumn (form_w, "MonthRC", args, n);
  138.     XtManageChild (rc_w);
  139.  
  140.     n = 0;
  141.     menu_w = XmCreatePulldownMenu (form_w, "MonthPD", args, n);
  142.     /* managed by the CascadeButton */
  143.  
  144.         for (i = 0; i < NMONTHS; i++) {
  145.         n = 0;
  146.         XtSetArg (args[n], XmNuserData, i+1); n++;
  147.         w = XmCreatePushButton (menu_w, mnames[i], args, n);
  148.         XtAddCallback (w, XmNactivateCallback, date_changed_cb,
  149.                                 (XtPointer)MONTH);
  150.         XtManageChild (w);
  151.         mmenu_w[i] = w;
  152.         }
  153.  
  154.     n = 0;
  155.     XtSetArg (args[n], XmNsubMenuId, menu_w); n++;
  156.     m_w = XmCreateCascadeButton (rc_w, "MonthCB", args, n);
  157.     XtManageChild (m_w);
  158.  
  159.     /* create the rowcol for the main date matrix */
  160.  
  161.     n = 0;
  162.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  163.     XtSetArg (args[n], XmNtopWidget, rc_w); n++;
  164.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  165.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  166.     XtSetArg (args[n], XmNnumColumns, CAL_ROWS+1); n++; /* +1 for dnames*/
  167.     XtSetArg (args[n], XmNpacking, XmPACK_COLUMN); n++;
  168.     XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
  169.     XtSetArg (args[n], XmNentryAlignment, XmALIGNMENT_END); n++;
  170.     XtSetArg (args[n], XmNadjustMargin, False); n++;
  171.     XtSetArg (args[n], XmNspacing, 0); n++;
  172.     rc_w = XmCreateRowColumn (form_w, "CalRC", args, n);
  173.     XtManageChild (rc_w);
  174.  
  175.     /* add the fixed day abbreviations */
  176.  
  177.     for (i = 0; i < XtNumber(dnames); i++) {
  178.         n = 0;
  179.         XtSetArg (args[n], XmNmarginLeft, 1); n++;    /* allow for buttons' */
  180.         XtSetArg (args[n], XmNmarginRight, 1); n++;    /* allow for buttons' */
  181.         w = XmCreateLabel (rc_w, dnames[i], args, n);
  182.         XtManageChild (w);
  183.     }
  184.  
  185.     /* add the calendar entries proper */
  186.  
  187.     for (i = 0; i < CAL_ROWS*CAL_COLS; i++) {
  188.         n = 0;
  189.         XtSetArg (args[n], XmNrecomputeSize, False); n++;
  190.         XtSetArg (args[n], XmNshadowThickness, 1); n++;
  191.         d_w[i] = XmCreatePushButton (rc_w, "CD", args, n);
  192.         XtAddCallback (d_w[i], XmNactivateCallback, date_changed_cb,
  193.                                 (XtPointer)DAY);
  194.         XtManageChild (d_w[i]);
  195.     }
  196.  
  197.     /* add the Today button */
  198.  
  199.     n = 0;
  200.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  201.     XtSetArg (args[n], XmNtopOffset, 3); n++;
  202.     XtSetArg (args[n], XmNtopWidget, rc_w); n++;
  203.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  204.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  205.     w = XmCreatePushButton (form_w, "Today", args, n);
  206.     XtManageChild (w);
  207.     XtAddCallback (w, XmNactivateCallback, today_cb, NULL);
  208.  
  209.     get_something (d_w[0], XmNforeground, (char *)&fg_pix);
  210.     get_something (d_w[0], XmNbackground, (char *)&bg_pix);
  211.  
  212.     return (form_w);
  213. }
  214.  
  215. /* set the calendar to the UT time of the given Now *np.
  216.  * don't bother if still same day as before.
  217.  */
  218. void
  219. calm_set (np)
  220. Now *np;
  221. {
  222.     static double last_mjdday;
  223.     static int rv_date;
  224.     double mjdday;
  225.     char buf[32];
  226.     int m, y;
  227.     double d;
  228.     int f;        /* day of week of first day of month Sun=0 */
  229.     int nd;        /* number of days in this month */
  230.     double jd0;    /* mjd of first day of the month */
  231.     int i;
  232.  
  233.     /* don't bother if it's still the same day */
  234.     mjdday = mjd_day (mjd);
  235.     if (last_mjdday == mjdday)
  236.         return;
  237.     last_mjdday = mjdday;
  238.  
  239.     /* get today's month, day, year */
  240.     mjd_cal (mjd, &m, &d, &y);
  241.  
  242.     /* find day of week of first day of month */
  243.     cal_mjd (m, 1.0, y, &jd0);
  244.     mjd_dow (jd0, &f);
  245.  
  246.     /* undo the current reverse video date */
  247.     set_something (d_w[rv_date], XmNforeground, (char *)fg_pix);
  248.     set_something (d_w[rv_date], XmNbackground, (char *)bg_pix);
  249.  
  250.     /* label the month */
  251.     f_showit (m_w, mnames[m-1]);
  252.  
  253.     /* label the year and set the menu entries around it */
  254.     (void) sprintf (buf, "%d", y);
  255.     f_showit (y_w, buf);
  256.     for (i = 0; i < NYEARS; i++) {
  257.         int ty = (y - NYEARS/3) + i; /* current year about 1/3 down list */
  258.         (void) sprintf (buf, "%d", ty);
  259.         f_showit (ymenu_w[i], buf);
  260.         set_something (ymenu_w[i], XmNuserData, (char *)ty);
  261.     }
  262.  
  263.  
  264.     if (f < 0) {
  265.         /* can't figure it out - too hard before Gregorian */
  266.         for (i = 0; i < CAL_ROWS*CAL_COLS; i++) {
  267.         set_something (d_w[i], XmNuserData, (char *)NO_DATE);
  268.         f_showit (d_w[i], "  ");
  269.         }
  270.         return;
  271.     }
  272.  
  273.     /* find number of days in this month */
  274.     mjd_dpm (jd0, &nd);
  275.  
  276.     /* print the calendar.
  277.      * set userData to the day of the month.
  278.      * use reverse colors for today.
  279.      */
  280.     for (i = 0; i < CAL_ROWS*CAL_COLS; i++) {
  281.         if (i == f + (int)d - 1) {
  282.         set_something (d_w[i], XmNforeground, (char *)bg_pix);
  283.         set_something (d_w[i], XmNbackground, (char *)fg_pix);
  284.         rv_date = i;
  285.         }
  286.         if (i < f || i > f + nd - 1) {
  287.         f_showit (d_w[i], "  ");
  288.         } else {
  289.         (void) sprintf (buf, "%2d", i-f+1);
  290.         f_showit (d_w[i], buf);
  291.         }
  292.         set_something (d_w[i], XmNuserData, (char *)(i-f+1));
  293.     }
  294.  
  295.     /* over print the new and full moons for this month.
  296.      * TODO: don't really know which dates to use here (see moonnf())
  297.      *   so try several to be fairly safe. have to go back to 4/29/1988
  298.      *   to find the full moon on 5/1 for example.
  299.      */
  300.     mm_nfmoon (jd0-3, m, f);
  301.     mm_nfmoon (jd0+15, m, f);
  302. }
  303.  
  304. /* called when Today is pressed.
  305.  * set m/d/y but retain any partion day.
  306.  */
  307. /* ARGSUSED */
  308. static void
  309. today_cb (w, client, call)
  310. Widget w;
  311. XtPointer client;
  312. XtPointer call;
  313. {
  314.     Now *np = mm_get_now();
  315.     double newmjd;
  316.     int m, y;
  317.     double d;
  318.  
  319.     mjd_cal (mjd, &m, &d, &y);
  320.     time_fromsys (np);
  321.     newmjd = mjd_day(mjd) + (d - floor(d));
  322.     mm_newcaldate (newmjd);
  323. }
  324.  
  325. /* called when any of the calendar pushbuttons is activated.
  326.  * client is one of DAY, MONTH or YEAR.
  327.  */
  328. /* ARGSUSED */
  329. static void
  330. date_changed_cb (w, client, call)
  331. Widget w;
  332. XtPointer client;
  333. XtPointer call;
  334. {
  335.     Now *np = mm_get_now();
  336.     int code = (int)client;
  337.     double newmjd;
  338.     int x;
  339.     int m, y;
  340.     double d;
  341.  
  342.     get_something (w, XmNuserData, (char *)&x);
  343.     if (x == NO_DATE)
  344.         return;
  345.  
  346.     mjd_cal (mjd, &m, &d, &y);
  347.  
  348.     switch (code) {
  349.     case MONTH:
  350.         cal_mjd (x, d, y, &newmjd);
  351.         break;
  352.     case DAY:
  353.         d = x + mjd_hr(mjd)/24.0;    /* preserve any partial day */
  354.         cal_mjd (m, d, y, &newmjd);
  355.         break;
  356.     case YEAR:
  357.         cal_mjd (m, d, x, &newmjd);
  358.         break;
  359.     }
  360.  
  361.     mm_newcaldate (newmjd);
  362. }
  363.  
  364. /* print the new and full moons for the month contained mjd jd, where
  365.  * m is the month code for the current month and f is the day-of-the-week
  366.  * of the first day of the month.
  367.  */
  368. static void
  369. mm_nfmoon (jd, m, f)
  370. double jd;
  371. int m, f;
  372. {
  373.     static char nms[] = "NM", fms[] = "FM";
  374.     int mm, ym;
  375.     double dm;
  376.     double jdn, jdf;    /* mjd of new and full moons near jd */
  377.     int di;
  378.  
  379.     moonnf (jd, &jdn, &jdf);
  380.     mjd_cal (jdn, &mm, &dm, &ym);
  381.     if (m == mm) {
  382.         di = dm + f - 1;
  383.         f_showit (d_w[di], nms);
  384.     }
  385.     mjd_cal (jdf, &mm, &dm, &ym);
  386.     if (m == mm) {
  387.         di = dm + f - 1;
  388.         f_showit (d_w[di], fms);
  389.     }
  390. }
  391.