Subject: calendar(1) progress!
To: Ty Sarna <tsarna@endicor.com>
From: Mason Loring Bliss <mason@acheron.middleboro.ma.us>
List: current-users
Date: 05/14/1998 00:11:32
--YOl2/5bycvrmDh4d
Content-Type: text/plain; charset=us-ascii

Okay... I haven't given this heavy testing yet, but enclosed are diffs to
calendar.c that allow it to handle calendar lines like:

04/27/2000 +20@2000  Bet with Brian. ($5. Year 2000.)
05/16 +10       Regionals - Type II
05/13 +15 @1980 New format, fifteen day lookahead test. Today.
05/20 +7        New format, fifteen day lookahead test.
05/15   +100 @3000      foo
05/15   +100@1990       foo dflkjvhb
05/15   @100+1990       foo dflkjvhb

Basically, if it finds "+foo" on a line where foo is numeric, it takes that
as the number of days in advance you wish to be shown the line. If it finds
something like "@bar" on the line where bar is numeric, it takes that as
a year that you wish to track, and it spits out the number of years since
that year has passed, or the number of years away the year is, as appropriate.

The mods assume that you don't want to see the +days @year tags in your
output, so the code filters that stuff out of the output. It even handles
silly monstrosities like the following, where tags show up randomly in the
text:

05/15   foo @1972 bar+100baz@1900

The order of the + and @ tags is unimportant. Also, you can have "+" and "@"
show up elsewhere in your text, as long as they show up after the tags based
on those characters.

My next step is to take a look at the ISO date formats so that I can see
about switching calendar(1) over to a more internationally acceptable
date formatting scheme.

Incidentally, if anyone has any objections to the characters being used for
any reason, now would be the time to chime in.

Tomorrow I'll probably refine things so that if a target year is the
same as the current year, the measurement will be in days, rather than years.
This might be fun - I don't know yet. I'll give it a whack tomorrow, anyway.

Um... A final question. What's the general opinion regarding the possibility
of switching from "calendar" to ".calendar" as the default file?

PS: I'm really happy with how this is going. I finally feel like I'm con-
tributing to the NetBSD project in a tangible, if small, way. :)

-- 
Mason Loring Bliss...mason@acheron.middleboro.ma.us...www.webtrek.com/mason
"In the drowsy dark cave of the mind dreams build their nest with fragments
 dropped from day's caravan."--Rabindranath Tagore...awake ? sleep : dream;

--YOl2/5bycvrmDh4d
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="calendar.diff"

*** calendar.c.old	Thu Apr  2 07:21:39 1998
--- calendar.c	Thu May 14 00:07:00 1998
***************
*** 73,78 ****
--- 73,80 ----
  #define FALSE 0
  #endif
  
+ #define CAL_BUFFSIZE (2048 + 1)
+ 
  unsigned short lookahead = 1, weekend = 2;
  char *fname = "calendar", *datestr = NULL;
  struct passwd *pw;
***************
*** 85,92 ****
--- 87,96 ----
  void	 closecal __P((FILE *));
  int	 getday __P((char *));
  int	 getfield __P((char *, char **, int *));
+ int	 GetOffset __P((char *, int));
  void	 getmmdd(struct tm *tp, char *ds);
  int	 getmonth __P((char *));
+ void	 GetYear __P((char *));
  int	 isnow __P((char *));
  int	 main __P((int, char **));
  FILE	*opencal __P((void));
***************
*** 154,164 ****
  void
  cal()
  {
  	int printing;
  	char *p;
  	FILE *fp;
  	int ch;
! 	char buf[2048 + 1];
  
  	if ((fp = opencal()) == NULL)
  		return;
--- 158,170 ----
  void
  cal()
  {
+ 	int offset_save;
+ 	extern int offset;
  	int printing;
  	char *p;
  	FILE *fp;
  	int ch;
! 	char buf[CAL_BUFFSIZE];
  
  	if ((fp = opencal()) == NULL)
  		return;
***************
*** 169,181 ****
  			while ((ch = getchar()) != '\n' && ch != EOF);
  		if (buf[0] == '\0')
  			continue;
! 		if (buf[0] != '\t')
  			printing = isnow(buf) ? 1 : 0;
! 		if (printing)
! 			(void)fprintf(fp, "%s\n", buf);
  	}
  	closecal(fp);
  }
  
  struct iovec header[] = {
  	{ "From: ", 6 },
--- 175,276 ----
  			while ((ch = getchar()) != '\n' && ch != EOF);
  		if (buf[0] == '\0')
  			continue;
! 		if (buf[0] != '\t') {
! 			offset_save = offset;
! 			offset = GetOffset(buf, offset);
! 			offset = offset > offset_save ? offset : offset_save;
  			printing = isnow(buf) ? 1 : 0;
! 			offset = offset_save;
! 		}
! 		if (printing) {
! 			(void) GetYear(buf);
! 			(void) fprintf(fp, "%s\n", buf);
! 		}
  	}
  	closecal(fp);
  }
+ 
+ 
+ /*
+  * GetOffset() - if there's an offset directive, figure out what the offset
+  *	should be and pass it back. Remove the directive from the source.
+  */
+ int GetOffset(char *buf, int offset)
+ {
+ 	int offset_save, i, x;
+ 	char *p;
+ 
+ 	/* See if we have an offset marker... */
+ 	offset_save = offset;
+ 	if ((p = strchr(buf, '+')) != '\0')
+ 		if (sscanf((char *) (p + 1), "%i", &offset) == 1) {
+ 
+ 			/* Use the original if it was larger. */
+ 			offset = offset_save > offset ? offset_save : offset;
+ 
+ 			/* Find the extent of our marker. */
+ 			for (i = (p - buf) + 1; (isdigit(buf[i])) && (i < CAL_BUFFSIZE - 1); ++i) ;
+ 			x = strlen(buf + i);
+ 
+ 			/* Eradicate whitespace immediately before p */
+ 			if (isspace(*(p-1)))
+ 				--p;
+ 
+ 			/* Remove the space the new offset marker occupied. */
+ 			memmove((void *) p, (void *) (buf + i), x);
+ 			buf[(p - buf) + x] = '\0';
+ 
+ 			return offset;
+ 		}
+ 		return offset_save;
+ }
+ 
+ 
+ /*
+  * GetYear() - if there's a year directive, replace it in the source buffer
+  *	with output of the form: "(X years ago)" with X being the number of
+  *	years between the indicated year and the current year.
+  */
+ void GetYear(char *buf)
+ {
+ 	int		i, x, y, year, passed;
+ 	char		*p;
+ 	char		broiled[100];
+ 	time_t		stime;
+ 	struct tm	*ltime;
+ 
+ 	/* Do we have a (potential) year marker? */
+ 	if ((p = strchr(buf, '@')) != '\0')
+ 		/* Does it have numbers after it? */
+ 		if (sscanf((char *) (p + 1), "%i", &year) == 1) {
+ 
+ 			/* Looks good so far - figure out the offset. */
+ 			stime = time(&stime);
+ 			ltime = localtime(&stime);
+ 			if (ltime->tm_year + 1900 > year) {
+ 				passed = ltime->tm_year + 1900 - year;
+ 				y = sprintf(broiled, " (%i years ago)", passed);
+ 			} else {
+ 				passed = year - (ltime->tm_year + 1900);
+ 				y = sprintf(broiled, " (%i years away)", passed);
+ 			}
+ 
+ 			/* Find the extent of our marker. */
+ 			for (i = (p - buf) + 1; (isdigit(buf[i])) && (i < CAL_BUFFSIZE - 1); ++i) ;
+ 			x = strlen(buf + i);
+ 
+ 			/* Eradicate whitespace immediately before p */
+ 			if (isspace(*(p-1)))
+ 				--p;
+ 
+ 			/* Move the end of the string forward, then tack on
+ 				the "elapsed" string. */
+ 			memmove((void *) p, (void *) buf + i, x);
+ 			memmove((void *) p + x, broiled, y);
+ 			buf[(p - buf) + x + y] = '\0';
+ 		}
+ }
+ 
  
  struct iovec header[] = {
  	{ "From: ", 6 },

--YOl2/5bycvrmDh4d--