From nobody  Thu Sep 25 12:35:45 1997
Received: (from nobody@localhost)
          by hub.freebsd.org (8.8.7/8.8.7) id MAA07975;
          Thu, 25 Sep 1997 12:35:45 -0700 (PDT)
Message-Id: <199709251935.MAA07975@hub.freebsd.org>
Date: Thu, 25 Sep 1997 12:35:45 -0700 (PDT)
From: imp@village.org
To: freebsd-gnats-submit@freebsd.org
Subject: calendar doesn't print all dates sometimes
X-Send-Pr-Version: www-1.0

>Number:         4629
>Category:       bin
>Synopsis:       calendar(1) doesn't print all dates sometimes
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    edwin
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Sep 25 12:40:00 PDT 1997
>Closed-Date:    Tue May 04 07:59:42 UTC 2010
>Last-Modified:  Tue May 04 07:59:42 UTC 2010
>Originator:     Warner Losh
>Release:        FreeBSD 3.0-current (Sept 21)
>Organization:
The Village
>Environment:
FreeBSD harmony.village.org 3.0-CURRENT FreeBSD 3.0-CURRENT #0: Fri Aug 29 00:04:41 MDT 1997     imp@harmony.village.org:/home/imp/FreeBSD/src/sys/compile/GENERIC  i386

>Description:
Given a calendar file that is as follows
/* ------------- */
Thursday	Eat at Jordan's
/* ------------- */

calendar -B 20 will list only one day, rather than two or three.  Like
wise it will only list this entry once for -A xxx as well.  Recurring
events don't repeat properly.
>How-To-Repeat:
See description.

>Fix:
Sadly, the fix is somewhat hard because the loop that prints out the
dates will print the line in question once and then go onto the next
line w/o seeing if there are other instances of this event in the
range of dates given.

>Release-Note:
>Audit-Trail:

From: "Danny J. Zerkel" <dzerkel@columbus.rr.com>
To: freebsd-gnats-submit@FreeBSD.org, imp@village.org
Cc:  
Subject: Re: bin/4629: calendar doesn't print all dates sometimes
Date: Thu, 23 May 2002 23:33:09 -0400

 This patch handles the simplest case: weekly events.  Monthly
 events would be more difficult due to the different lengths of
 months and different kinds of monthly events.
 
 Some of the long lines from the original code may need to be
 tweaked to get this patch to apply...
 
 --- calendar.h.orig     Wed May 22 23:56:44 2002
 +++ calendar.h  Thu May 23 23:29:17 2002
 @@ -51,6 +51,7 @@
   int      getpaskha(char *, int);
   int      easter(int);
   int     isnow(char *, int *, int *, int *);
 +void    repeatweek(int *, int *);
   FILE   *opencal(void);
   void    settime(time_t);
   time_t   Mktime(char *);
 @@ -64,6 +65,7 @@
   #define        F_ISDAY         0x02 /* day of week (Sun, Mon, ...) */
   #define        F_ISDAYVAR      0x04 /* variables day of week, like SundayLast */
   #define        F_EASTER        0x08 /* Easter or easter depending days */
 +#define        F_REPEAT        0x10 /* Repeat weekly */
 
   extern int f_dayAfter; /* days after current date */
   extern int f_dayBefore; /* days bevore current date */
 --- day.c.orig  Thu May 23 00:02:34 2002
 +++ day.c       Thu May 23 23:09:20 2002
 @@ -215,7 +215,8 @@
    *
    * Any character may separate them, or they may not be separated.  Any line,
    * following a line that is matched, that starts with "whitespace", is shown
 - * along with the matched line.
 + * along with the matched line.  Returns the number of matching days in the
 + * requested date range.
    */
   int
   isnow(endp, monthp, dayp, varp)
 @@ -225,6 +226,7 @@
          int     *varp;
   {
          int day, flags, month = 0, v1, v2;
 +       int nummatches;
 
          /*
           * CONVENTION
 @@ -260,8 +262,12 @@
                  /* {Day,Weekday} {Month,Monthname} ... */
                  /* if no recognizable month, assume just a day alone
                   * in other words, find month or use current month */
 -               if (!(month = getfield(endp, &endp, &flags)))
 +               if (!(month = getfield(endp, &endp, &flags))) {
                          month = tp->tm_mon + 1;
 +                       /* Weekdays may match multiple time in a range */
 +                       if (flags & F_ISDAY && day <= 7)
 +                               flags |= F_REPEAT;
 +               }
          }
 
          /* 2. {Monthname} XYZ ... */
 @@ -378,18 +384,56 @@
   #ifdef DEBUG
          fprintf(stderr, "day2: day %d(%d-%d) yday %d\n", *dayp, day, cumdays[month], 
 tp->tm_yday);
   #endif
 +       /* Find the earliest matching weekday in the range */
 +       if (flags & F_REPEAT) {
 +               while (day - 7 >= tp->tm_yday - f_dayBefore) {
 +                       day -= 7;
 +                       *dayp -= 7;
 +               }
 +               /* Adjust the month and day, to fit the day */
 +               while (*dayp < 1) {
 +                       *monthp -= 1;
 +                       if (*monthp < 1)
 +                               *monthp = 12;
 +                       *dayp += cumdays[*monthp + 1] - cumdays[*monthp];
 +               }
 +       }
 +       nummatches = 0;
 +
          /* if today or today + offset days */
          if (day >= tp->tm_yday - f_dayBefore &&
              day <= tp->tm_yday + offset + f_dayAfter)
 -               return (1);
 +               nummatches = 1;
 
          /* if number of days left in this year + days to event in next year */
 -       if (yrdays - tp->tm_yday + day <= offset + f_dayAfter ||
 +       else if (yrdays - tp->tm_yday + day <= offset + f_dayAfter ||
              /* a year backward, eg. 6 Jan and 10 days before -> 27. Dec */
 -           tp->tm_yday + day - f_dayBefore < 0
 -           )
 -               return (1);
 -       return (0);
 +           tp->tm_yday + day - f_dayBefore < 0)
 +               nummatches = 1;
 +
 +       if (nummatches && flags & F_REPEAT)
 +               /* Return number of matching days in range */
 +               return ((tp->tm_yday - day + offset + f_dayAfter + 7) / 7);
 +       return (nummatches);
 +}
 +
 +
 +void
 +repeatweek(monthp, dayp)
 +       int *monthp;
 +       int *dayp;
 +{
 +       int days;
 +
 +       days = *dayp + cumdays[*monthp] + 7;
 +       if (days > cumdays[*monthp + 1]) {
 +               if (*monthp == 12) {
 +                       *monthp = 1;
 +                       days -= yrdays;
 +               } else
 +                       *monthp += 1;
 +       }
 +       *dayp = days - cumdays[*monthp];
   }
 
 
 --- io.c.orig   Thu May 23 00:26:52 2002
 +++ io.c        Thu May 23 23:03:10 2002
 @@ -134,7 +134,7 @@
                          continue;
                  }
                  if (buf[0] != '\t') {
 -                       printing = isnow(buf, &month, &day, &var) ? 1 : 0;
 +                       printing = isnow(buf, &month, &day, &var);
                          if ((p = strchr(buf, '\t')) == NULL)
                                  continue;
                          if (p > buf && p[-1] == '*')
 @@ -144,19 +144,28 @@
                                  char dbuf[80];
 
                                  if (d_first < 0)
 -                                       d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
 +                                       d_first =
 +                                           (*nl_langinfo(D_MD_ORDER) == 'd');
                                  tm.tm_sec = 0;  /* unused */
                                  tm.tm_min = 0;  /* unused */
                                  tm.tm_hour = 0; /* unused */
                                  tm.tm_wday = 0; /* unused */
 -                               tm.tm_mon = month - 1;
 -                               tm.tm_mday = day;
                                  tm.tm_year = tp->tm_year; /* unused */
 -                               (void)strftime(dbuf, sizeof(dbuf),
 -                                              d_first ? "%e %b" : "%b %e",
 -                                              &tm);
 -                               (void)fprintf(fp, "%s%c%s\n", dbuf,
 -                                   var ? '*' : ' ', p);
 +                               for (;;) {
 +                                       tm.tm_mon = month - 1;
 +                                       tm.tm_mday = day;
 +                                       /* Print additional date */
 +                                       (void)strftime(dbuf, sizeof(dbuf),
 +                                           d_first ? "%e %b" : "%b %e",
 +                                           &tm);
 +                                       (void)fprintf(fp, "%s%c%s\n", dbuf,
 +                                           var ? '*' : ' ', p);
 +                                       printing--;
 +                                       if (!printing)
 +                                               break;
 +                                       /* Increment by 1 week */
 +                                       repeatweek(&month, &day);
 +                               }
                          }
                  }
                  else if (printing)
 
 -- Danny J. Zerkel
 dzerkel@columbus.rr.com
 
Responsible-Changed-From-To: freebsd-bugs->grog 
Responsible-Changed-By: kris 
Responsible-Changed-When: Thu Nov 6 19:05:26 PST 2003 
Responsible-Changed-Why:  
Assign to calendar maintainer 

http://www.freebsd.org/cgi/query-pr.cgi?pr=4629 
Responsible-Changed-From-To: grog->edwin 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Mon Jun 25 02:12:49 UTC 2007 
Responsible-Changed-Why:  
grog@ asked me take this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=4629 
Responsible-Changed-From-To: edwin->freebsd-bugs 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Thu Feb 14 10:27:36 UTC 2008 
Responsible-Changed-Why:  
Give back into the pool until later. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=4629 
Responsible-Changed-From-To: freebsd-bugs->edwin 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Mon Mar 1 00:41:18 UTC 2010 
Responsible-Changed-Why:  
Will be fixed in the new calendar. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=4629 
State-Changed-From-To: open->closed 
State-Changed-By: edwin 
State-Changed-When: Tue May 4 07:59:22 UTC 2010 
State-Changed-Why:  
This now works in the new calendar system. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=4629 
>Unformatted:
