home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume13 / xcal / part04 / xcal_strip.c < prev    next >
C/C++ Source or Header  |  1991-05-12  |  17KB  |  729 lines

  1. #ifndef lint
  2. static char *sccsid = "@(#)xcal_strip.c    3.10 (Hillside Systems) 1/16/91";
  3. static char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
  4. #endif  /* lint */
  5. /***
  6.  
  7. * module name:
  8.     xcal_strip.c
  9. * function:
  10.     Deal with the popup strip calendars obtained either by
  11.     selection and the middle button, or by the < and > buttons
  12.     on each strip.
  13. * history:
  14.     Written November 1989
  15.     Peter Collinson
  16.     Hillside Systems
  17. * (C) Copyright: 1989 Hillside Systems/Peter Collinson
  18.     
  19.     For full permissions and copyright notice - see xcal.c
  20. ***/
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <X11/Intrinsic.h>
  24. #include <X11/StringDefs.h>
  25. #include <X11/Shell.h>
  26. #include <X11/Xaw/Paned.h>
  27. #include <X11/Xaw/Command.h>
  28. #include <X11/Xaw/Label.h>
  29. #include <X11/Xaw/Dialog.h>
  30. #include <X11/Xaw/AsciiText.h>
  31. #include "xcal.h"
  32.  
  33. static XtCallbackRec callbacks[] = {
  34.    {NULL,NULL},
  35.    {NULL,NULL},
  36.    {NULL,NULL},
  37.    {NULL,NULL}
  38. };
  39. #define ClearCallbacks() bzero((caddr_t)callbacks, sizeof (callbacks))
  40.  
  41. Date    callb;        /* contains date when calendar day button pressed */
  42.  
  43. /*
  44.  *    Forward routines local to this file
  45.  */
  46. void MakeMonth();
  47. void    DayBack();
  48. #ifndef LONG_IS_32_BITS
  49. void    YmBack();
  50. #endif
  51. void    StripQuit();
  52. void    StripHelp();
  53. void    WeeklyHelp();
  54. void    MakeNewMonth();
  55.  
  56. Cardinal DateSum();
  57. Cardinal NumberOfDays();
  58. Cardinal FirstDay();
  59. Cardinal JanuaryOne();
  60.  
  61. /*
  62.  *    Local routines
  63.  */
  64. static void    CreateActionBar();
  65. static void    CreateWeeklyActionBar();
  66.  
  67. /*
  68. *    Start a strip calendar happening
  69.  *    a callback of left button 
  70.  */
  71. /* ARGSUSED */
  72. void
  73. DoCalendar(w, closure, call_data)
  74.     Widget w;
  75.     caddr_t    closure;
  76.     caddr_t call_data;
  77. {
  78.     NewMonthStrip(&today);        /* today is global */
  79. }
  80.  
  81. /* ARGSUSED */
  82. void
  83. DoWeekly(w, closure, call_data)
  84.     Widget w;
  85.     caddr_t    closure;
  86.     caddr_t call_data;
  87. {
  88.     Date    thisday;
  89.  
  90.     thisday.day = 0;
  91.     thisday.month = 0;
  92.     thisday.year = 0;
  93.     thisday.wday = 0;
  94.     NewMonthStrip(&thisday);    /* today is global */
  95. }
  96.  
  97.  
  98. /*
  99.  *    Start a strip calendar happening
  100.  *    a callback of the > or < buttons in another strip
  101.  */
  102. /* ARGSUSED */
  103. static void
  104. MakeNewMonth(w, closure, call_data)
  105.     Widget w;
  106.     caddr_t    closure;
  107.     caddr_t call_data;
  108. {
  109.     Date    thisday;
  110.  
  111.     thisday.year = YrUnpack((Cardinal)closure);
  112.     thisday.month = MoUnpack((Cardinal)closure);
  113.     thisday.day = today.day;
  114.     NewMonthStrip(&thisday);
  115. }
  116.  
  117. /* 
  118.  *    Do all the X stuff to popup a Strip calendar
  119.  *    A calendar strip is:
  120.  *
  121.  *    Popup ("<month year>")        // Name is the month and the year
  122.  *        Paned ("<month>")        // Name is the month
  123.  *        Label ("header")    // optional contains Month Year
  124.  *        Form ("action")        // < Quit >
  125.  *            Command ("back")    // contains < 
  126.  *            Label ("quit")    // contains Quit
  127.  *            Command ("next")    // contains >
  128.  *    (Then many of..)
  129.  *        Form ("<dd DDD>")    // where dd is the day number, DDD is the
  130.  *                    // day of the week
  131.  *            Label ("label")    // contains the string above
  132.  *            Command ("info")    // contains the text from the file
  133.  *        
  134.  */
  135. void
  136. NewMonthStrip(td)
  137.     Date    *td;
  138. {
  139.     Widget        shell, mon, dw, lw, lwi, form;
  140.     Arg        args[15];
  141.     char        nbuf[256];
  142.     char        iconName[80];
  143.     int        type;
  144.     MonthEntry    *me;
  145.     Instance    *ins;
  146.     register int    i;
  147.     register Cardinal nargs;
  148.     Cardinal    thisDay;
  149.     Cardinal    startLoop;
  150.     String        dayStr;
  151.     Cardinal    numberOfDays;
  152.     Boolean        defaultsAreSet = False;
  153.     Boolean        markThisMonth = False;
  154.     Cardinal    adjustLabelY;
  155.     Cardinal    adjustInfoY;
  156.     Dimension    labelH, infoH;
  157.     Dimension    width;
  158.     Dimension    totalWidth;
  159.  
  160.     type = (td->day == 0) ? ME_WEEKLY : ME_MONTHLY;
  161.     
  162.     /*
  163.      *    There are lots of differences between
  164.      *    Months and weekly strips here.
  165.      *    Later tests are done using a switch structure
  166.      */
  167.     switch (type)
  168.     {
  169.     case ME_MONTHLY:
  170.         (void) sprintf(iconName, "%s %d", appResources.smon[td->month], td->year);
  171.         XtSetArg(args[0], XtNiconName, iconName);
  172.         shell = XtCreatePopupShell(XtNewString(iconName), topLevelShellWidgetClass, toplevel, args, 1);
  173.         ins = RegisterMonth(td->year, td->month, shell);    
  174.         mon = XtCreateManagedWidget(appResources.mon[td->month], panedWidgetClass, shell, NULL, 0);
  175.         thisDay = FirstDay(td->month, td->year);
  176.         numberOfDays = NumberOfDays(td->month, td->year);
  177.         startLoop = 1;
  178.         /*
  179.          *    Get the map for this year
  180.          */
  181.         me = GetMonthEntry(td->year, td->month);
  182.         me->me_type = type;
  183.         /*
  184.          *    Title bar is month and date
  185.          */
  186.         (void) sprintf(nbuf, "%s %d", appResources.mon[td->month], td->year);
  187.         /*
  188.          *    see if we will need to worry about marking today's entry
  189.          */
  190.         if (appResources.markToday && td->year == today.year && td->month == today.month)
  191.             markThisMonth = True;
  192.         break;
  193.     case ME_WEEKLY:
  194.         (void) strcpy(iconName, appResources.weekly);
  195.         XtSetArg(args[0], XtNiconName, iconName);
  196.         shell = XtCreatePopupShell(XtNewString(iconName), topLevelShellWidgetClass, toplevel, args, 1);
  197.         ins = RegisterMonth(0, 0, shell);    
  198.         mon = XtCreateManagedWidget(iconName, panedWidgetClass, shell, NULL, 0);
  199.         thisDay = 0;
  200.         numberOfDays = 6;    /* test is <= */
  201.         startLoop = 0;
  202.         /*
  203.          *    Get the map for this year
  204.          */
  205.         me = GetWeeklyEntry();
  206.         me->me_type = type;
  207.         /*
  208.          *    Title bar is from the resources
  209.          */
  210.         strcpy(nbuf, iconName);
  211.         /*
  212.          *    see if we will need to worry about marking today's entry
  213.          */
  214.         if (appResources.markToday)
  215.             markThisMonth = True;
  216.         break;
  217.     }
  218.     /*
  219.      *    Find size of title bar
  220.      *    by creating the widget and then throwing it away
  221.      */
  222.     XtSetArg(args[0], XtNlabel, "mmmmmmmmm NNNN");
  223.     lw = XtCreateManagedWidget("sizer", labelWidgetClass, shell, args, 1);
  224.     XtSetArg(args[0], XtNwidth, &totalWidth);
  225.     XtGetValues(lw, args, 1);
  226.     XtDestroyWidget(lw);
  227.     /*
  228.      *    Width is affected by a resource value
  229.      */
  230.     if (appResources.minstripwidth && appResources.minstripwidth > totalWidth)
  231.         totalWidth = appResources.minstripwidth;
  232.     /*
  233.      *    Now set the title bar should we need it
  234.      */
  235.     if (appResources.useWmTitle)
  236.     {    XtSetArg(args[0], XtNlabel, XtNewString(nbuf));
  237.         (void) XtCreateManagedWidget("header", labelWidgetClass, mon, args, 1);
  238.     }
  239.         
  240.     /*
  241.      *    Action bar
  242.      */
  243.     nargs = 0;
  244.     XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
  245.     XtSetArg(args[nargs], XtNdefaultDistance, 2); nargs++;
  246.     dw = XtCreateManagedWidget("action", formWidgetClass, mon, args, nargs);
  247.  
  248.     switch (type)
  249.     {
  250.     case ME_MONTHLY:
  251.         CreateActionBar(shell, dw, mon, td);
  252.         break;
  253.     case ME_WEEKLY:
  254.         CreateWeeklyActionBar(shell, dw);
  255.         break;
  256.     }
  257.  
  258. #ifdef    LONG_IS_32_BITS
  259.     callbacks[0].callback = DayBack;
  260. #else
  261.     callbacks[0].callback = YmBack;
  262.     callbacks[1].callback = DayBack;
  263. #endif
  264.     for (i = startLoop; i <= numberOfDays; i++)
  265.     {
  266.         dayStr = appResources.sday[thisDay];
  267.         switch(type)
  268.         {
  269.         case ME_MONTHLY:
  270.             (void) sprintf(nbuf, "%2d %s", i, dayStr);
  271.             break;
  272.         case ME_WEEKLY:
  273.             (void) strcpy(nbuf, dayStr);
  274.             break;
  275.         }
  276. #ifdef LONG_IS_32_BITS
  277.         callbacks[0].closure = (caddr_t)DatePack(thisDay, i, td->month, td->year);
  278. #else
  279.         callbacks[0].closure = (caddr_t)DatePack(td->month, td->year);
  280.         callbacks[1].closure = (caddr_t)DayPack(thisDay, i);
  281. #endif        
  282.  
  283.         thisDay = (thisDay+1)%7;
  284.         
  285.         /*
  286.          *    Each line in the strip is
  287.          *    form containing
  288.          *    label - command
  289.          */
  290.         nargs = 0;
  291.         XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
  292.         XtSetArg(args[nargs], XtNdefaultDistance, 0); nargs++;
  293.         form = XtCreateManagedWidget(dayStr, formWidgetClass, mon, args, nargs);
  294.         
  295.         nargs = 0;
  296.         XtSetArg(args[nargs], XtNlabel, XtNewString(nbuf)); nargs++;
  297.                         /* a little naughty here */
  298.                         /* this string memory is lost */
  299.                         /* on quit */
  300.         XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
  301.         XtSetArg(args[nargs], XtNjustify, XtJustifyLeft); nargs++;
  302.         XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
  303.         XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  304.         XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
  305.  
  306.         ins->i_day_label[i] = lw = XtCreateManagedWidget("label", labelWidgetClass, form, args, nargs);
  307.  
  308.         /*
  309.          *    To get a handle on the old values which are lost by
  310.          *    highlighting we get them after we have created the
  311.          *    widget. Then we highlight today.
  312.          */
  313.         if (markThisMonth &&
  314.             ((type == ME_MONTHLY && today.day == i) ||
  315.              (type == ME_WEEKLY && today.wday == i)))
  316.         {
  317.             nargs = 0;
  318.             XtSetArg(args[nargs], XtNforeground, &ins->i_col.fg); nargs++;
  319.             XtSetArg(args[nargs], XtNbackground, &ins->i_col.bg); nargs++;
  320.             XtSetArg(args[nargs], XtNfont, &ins->i_font); nargs++;
  321.             XtGetValues(lw, args, nargs);
  322.  
  323.             nargs = 0;
  324.             XtSetArg(args[nargs], XtNforeground, appResources.today.fg); nargs++;
  325.             XtSetArg(args[nargs], XtNbackground, appResources.today.bg); nargs++;
  326.             XtSetArg(args[nargs], XtNfont, appResources.fontToday); nargs++;
  327.             XtSetValues(lw, args, nargs);
  328.         }
  329.         /*
  330.          *    Done the first time through
  331.          *    Gets the width of the line we have just made
  332.          */
  333.         if (defaultsAreSet == False)
  334.         {    /* compute text width */
  335.             nargs = 0;
  336.             XtSetArg(args[nargs], XtNwidth, &width); nargs++;
  337.             XtSetArg(args[nargs], XtNheight, &labelH); nargs++;
  338.             XtGetValues(lw, args, nargs);
  339.             defaultsAreSet = True;
  340.         }
  341.         /*
  342.          *    Start processing the RHS of the line
  343.          *    This contains text from the file
  344.          *    should any exist
  345.          */
  346.         nargs = 0;
  347.         XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
  348.         XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  349.         XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
  350.         XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  351.         XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
  352.         XtSetArg(args[nargs], XtNjustify, XtJustifyLeft); nargs++;
  353.         XtSetArg(args[nargs], XtNwidth, totalWidth - width); nargs++;
  354.  
  355.         if (me->me_have[i])
  356.         {    XtSetArg(args[nargs], XtNforeground, appResources.marked.fg); nargs++;
  357.             XtSetArg(args[nargs], XtNbackground, appResources.marked.bg); nargs++;
  358.             XtSetArg(args[nargs], XtNlabel, me->me_have[i]); nargs++;
  359.         }
  360.         else
  361.         {    XtSetArg(args[nargs], XtNlabel, "    "); nargs++;    }
  362.         ins->i_day_info[i] = lwi = XtCreateManagedWidget("info", commandWidgetClass, form, args, nargs);
  363.  
  364.         /* deal with height */
  365.         XtSetArg(args[0], XtNheight, &infoH);
  366.         XtGetValues(lwi, args, 1);
  367.         if (labelH < infoH)
  368.         {    adjustLabelY = ((infoH-labelH)/2);
  369.             /* fix up widget */
  370.             nargs = 0;
  371.             XtSetArg(args[nargs], XtNvertDistance, adjustLabelY); nargs++;
  372.                         XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
  373.             XtSetValues(lw, args, nargs);
  374.         }
  375.         else
  376.         if (labelH > infoH)
  377.         {    adjustInfoY = ((labelH - infoH)/2);
  378.             /* fix up widget 1 */
  379.             nargs = 0;
  380.             XtSetArg(args[nargs], XtNvertDistance, adjustInfoY); nargs++;
  381.                         XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
  382.             XtSetValues(lwi, args, nargs);
  383.         }
  384.  
  385.         /*
  386.          *    cope with 1752
  387.          */
  388.         if (td->year == 1752 && td->month == 8 && i == 2)
  389.         {    i = 13;
  390.             numberOfDays += 11;    /* giving back the 11 days */
  391.         }
  392.     }
  393.     ClearCallbacks();
  394.  
  395.     XtPopup(shell, XtGrabNone);
  396. }
  397.  
  398. /*
  399.  *    Create action bar for normal monthly strip
  400.  */
  401. static void
  402. CreateActionBar(shell, dw, mon, td)
  403.     Widget    shell;
  404.     Widget    dw;
  405.     Widget    mon;
  406.     Date    *td;
  407. {
  408.     Widget        lw;
  409.     register Cardinal nargs;
  410.     Arg        args[8];
  411.  
  412.     /*
  413.      *    back one month
  414.      *    label "<" from resources
  415.      */
  416.     callbacks[0].callback = MakeNewMonth;
  417.     callbacks[0].closure = (caddr_t)DateSum(td, -1);
  418.     nargs = 0;
  419.     XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  420.     XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
  421.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  422.     XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
  423.     lw = XtCreateManagedWidget("back", commandWidgetClass, dw, args, nargs);
  424.     ClearCallbacks();
  425.  
  426.     /*
  427.      *    Quit button
  428.      *    label "quit" from resources
  429.      */
  430.     callbacks[0].callback = StripQuit;
  431.     callbacks[0].closure = (caddr_t)shell;
  432.     nargs = 0;
  433.     XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  434.     XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
  435.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  436.     XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
  437.     lw = XtCreateManagedWidget("quit", commandWidgetClass, dw, args, nargs);
  438.     ClearCallbacks();
  439.  
  440.     /*
  441.      *    On one month
  442.      *    label ">" from reources
  443.      */
  444.     callbacks[0].callback = MakeNewMonth;
  445.     callbacks[0].closure = (caddr_t)DateSum(td, 1);
  446.     nargs = 0;
  447.     XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  448.     XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
  449.     XtSetArg(args[nargs], XtNleft, XtChainRight); nargs++;
  450.     XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
  451.     lw = XtCreateManagedWidget("next", commandWidgetClass, dw, args, nargs);
  452.     ClearCallbacks();
  453.  
  454.     /*
  455.      *    Help button
  456.      *    label help from resources
  457.      */
  458.     if (appResources.giveHelp)
  459.     {    
  460.         callbacks[0].callback = StripHelp;
  461.         callbacks[0].closure = (caddr_t)0;
  462.         nargs = 0;
  463.         XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  464.         XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
  465.         lw = XtCreateManagedWidget("help", commandWidgetClass, mon, args, nargs);
  466.         ClearCallbacks();
  467.     }
  468. }
  469.  
  470. /*
  471.  *    Create action bar for normal monthly strip
  472.  */
  473. static void
  474. CreateWeeklyActionBar(shell, dw)
  475.     Widget    shell;
  476.     Widget    dw;
  477. {
  478.     Widget        lw;
  479.     register Cardinal nargs;
  480.     Arg        args[8];
  481.  
  482.     /*
  483.      *    Quit button
  484.      *    label "quit" from resources
  485.      */
  486.     callbacks[0].callback = StripQuit;
  487.     callbacks[0].closure = (caddr_t)shell;
  488.     nargs = 0;
  489.     XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  490.     XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
  491.     XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  492.     XtSetArg(args[nargs], XtNright, appResources.giveHelp ? XtChainLeft: XtChainRight); nargs++;
  493.     lw = XtCreateManagedWidget("quit", commandWidgetClass, dw, args, nargs);
  494.     ClearCallbacks();
  495.  
  496.     /*
  497.      *    Help button
  498.      *    label help from resources
  499.      */
  500.     if (appResources.giveHelp)
  501.     {    
  502.         callbacks[0].callback = WeeklyHelp;
  503.         callbacks[0].closure = (caddr_t)0;
  504.         nargs = 0;
  505.         XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
  506.         XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
  507.         XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
  508.         XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
  509.         lw = XtCreateManagedWidget("help", commandWidgetClass, dw, args, nargs);
  510.         ClearCallbacks();
  511.     }
  512. }
  513.  
  514. /*
  515.  *    Called when the date changes to ensure that
  516.  *    the correct day has the appropriate highlights
  517.  */
  518. void
  519. ChangeHighlight(old, new)
  520.     Date    *old;
  521.     Date    *new;
  522. {
  523.     register Instance *ins;
  524.     Arg        args[5];
  525.     Cardinal    nargs;
  526.  
  527.     for (ins = FindInstanceList(old); ins; ins = ins->i_next)
  528.     {    nargs = 0;    
  529.         XtSetArg(args[nargs], XtNforeground, ins->i_col.fg); nargs++;
  530.         XtSetArg(args[nargs], XtNbackground, ins->i_col.bg); nargs++;
  531.         XtSetArg(args[nargs], XtNfont, ins->i_font); nargs++;
  532.         XtSetValues(ins->i_day_label[old->day], args, nargs);
  533.     }
  534.  
  535.     for (ins = FindInstanceList(new); ins; ins = ins->i_next)
  536.     {    nargs = 0;
  537.         XtSetArg(args[nargs], XtNforeground, &ins->i_col.fg); nargs++;
  538.         XtSetArg(args[nargs], XtNbackground, &ins->i_col.bg); nargs++;
  539.         XtSetArg(args[nargs], XtNfont, &ins->i_font); nargs++;
  540.         XtGetValues(ins->i_day_label[new->day], args, nargs);
  541.  
  542.         nargs = 0;    
  543.         XtSetArg(args[nargs], XtNforeground, appResources.today.fg); nargs++;
  544.         XtSetArg(args[nargs], XtNbackground, appResources.today.bg); nargs++;
  545.         XtSetArg(args[nargs], XtNfont, appResources.fontToday); nargs++;
  546.         XtSetValues(ins->i_day_label[new->day], args, nargs);
  547.     }
  548. }
  549.  
  550. /*
  551.  *    Call back from a quit button to lose a month strip
  552.  */
  553. /* ARGSUSED */
  554. static void
  555. StripQuit(w, closure, call_data)
  556.     Widget w;
  557.     caddr_t    closure;
  558.     caddr_t call_data;
  559. {
  560.     XtPopdown((Widget)closure);
  561.     XtDestroyWidget((Widget)closure);
  562. }
  563.     
  564.  
  565. /*
  566.  *    Month arithmetic and packing
  567.  */
  568. static Cardinal
  569. DateSum(td, inx)
  570.     Date    *td;
  571.     int    inx;
  572. {
  573.     int    m, y;
  574.  
  575.     m = td->month;
  576.     y = td->year;
  577.     m += inx;
  578.     if (m < 0)
  579.     {    m = 11;
  580.         y--;
  581.     }
  582.     else
  583.     if (m > 11)
  584.     {    m = 0;
  585.         y++;
  586.     }
  587. #ifdef LONG_IS_32_BITS
  588.     return(DatePack(0, 0, m, y));
  589. #else
  590.     return(DatePack(m, y));
  591. #endif
  592. }
  593.  
  594. /*
  595.  *    Call back from day selection button press
  596.  *    This is done in two stages if cannot fold dates into a closure
  597.  */
  598. /* ARGSUSED */
  599. static void
  600. DayBack(w, closure, call_data)
  601.     Widget w;
  602.     caddr_t    closure;
  603.     caddr_t call_data;
  604. {
  605. #ifdef LONG_IS_32_BITS
  606.     callb.month = MoUnpack((Cardinal)closure);
  607.     callb.year = YrUnpack((Cardinal)closure);
  608. #endif
  609.     callb.day = DyUnpack((Cardinal)closure);
  610.     callb.wday = WdUnpack((Cardinal)closure);
  611.     StartEditing(w, &callb);
  612. }
  613.  
  614. #ifndef LONG_IS_32_BITS
  615. /* ARGSUSED */
  616. static void
  617. YmBack(w, closure, call_data)
  618.     Widget w;
  619.     caddr_t    closure;
  620.     caddr_t call_data;
  621. {
  622.     callb.month = MoUnpack((Cardinal)closure);
  623.     callb.year = YrUnpack((Cardinal)closure);
  624. }
  625. #endif
  626.  
  627. /*
  628.  *    Stolen from xcalendar.c
  629.  */
  630. /* taken from cal.c */
  631.  
  632. char    mon[] = {
  633.    31, 29, 31, 30,
  634.    31, 30, 31, 31,
  635.    30, 31, 30, 31,
  636. };
  637.  
  638. static Cardinal calInit = 0;
  639.  
  640. static Cardinal
  641. NumberOfDays(m, y)
  642.     Cardinal m, y;
  643. {
  644.     if(calInit != y)
  645.         (void) FirstDay(m, y); /* set side effect */
  646.     return mon[m];
  647. }
  648.  
  649. /* should be called first */
  650. static Cardinal
  651. FirstDay(m, y)
  652.      Cardinal m, y;
  653. {
  654.     register d, i;
  655.  
  656.     calInit = y;
  657.     d = JanuaryOne(y);
  658.     mon[1] = 29;
  659.     mon[8] = 30;
  660.    
  661.     switch((JanuaryOne(y+1)+7-d)%7)
  662.     {
  663.       
  664.     /*
  665.      *    non-leap year
  666.      */
  667.     case 1:
  668.         mon[1] = 28;
  669.         break;
  670.       
  671.     /*
  672.      *    1752
  673.      */
  674.     default:
  675.         mon[8] = 19;
  676.         break;
  677.  
  678.     /*
  679.      *    leap year
  680.      */
  681.     case 2:
  682.         ;
  683.     }
  684.    
  685.     for(i=0; i<m; i++)
  686.         d += mon[i];
  687.  
  688.     return(d%7);
  689. }
  690.  
  691. /*
  692.  *    return day of the week
  693.  *    of jan 1 of given year
  694.  */
  695. static Cardinal
  696. JanuaryOne(yr)
  697.     Cardinal yr;
  698. {
  699.     register Cardinal y, d;
  700.  
  701. /*
  702.  *    normal gregorian calendar
  703.  *    one extra day per four years
  704.  */
  705.  
  706.     y = yr;
  707.     d = 4+y+(y+3)/4;
  708.  
  709. /*
  710.  *    julian calendar
  711.  *    regular gregorian
  712.  *    less three days per 400
  713.  */
  714.  
  715.     if(y > 1800) {
  716.         d -= (y-1701)/100;
  717.         d += (y-1601)/400;
  718.     }
  719.  
  720. /*
  721.  *    great calendar changeover instant
  722.  */
  723.  
  724.     if(y > 1752)
  725.         d += 3;
  726.  
  727.     return(d%7);
  728. }
  729.