You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.2 KiB
137 lines
3.2 KiB
/* cal.c - show calendar.
|
|
*
|
|
* Copyright 2011 Rob Landley <rob@landley.net>
|
|
*
|
|
* See http://opengroup.org/onlinepubs/9699919799/utilities/cal.html
|
|
|
|
USE_CAL(NEWTOY(cal, ">2h", TOYFLAG_USR|TOYFLAG_BIN))
|
|
|
|
config CAL
|
|
bool "cal"
|
|
default y
|
|
help
|
|
usage: cal [[MONTH] YEAR]
|
|
|
|
Print a calendar.
|
|
|
|
With one argument, prints all months of the specified year.
|
|
With two arguments, prints calendar for month and year.
|
|
|
|
-h Don't highlight today
|
|
*/
|
|
|
|
#define FOR_cal
|
|
#include "toys.h"
|
|
|
|
GLOBALS(
|
|
struct tm *now;
|
|
)
|
|
|
|
// Write calendar into buffer: each line is 20 chars wide, end indicated
|
|
// by empty string.
|
|
|
|
static char *calstrings(char *buf, struct tm *tm)
|
|
{
|
|
char temp[21];
|
|
int wday, mday, start, len, line;
|
|
|
|
// header
|
|
len = strftime(temp, 21, "%B %Y", tm);
|
|
len += (20-len)/2;
|
|
buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, "");
|
|
buf++;
|
|
buf += sprintf(buf, "Su Mo Tu We Th Fr Sa ");
|
|
buf++;
|
|
|
|
// What day of the week does this month start on?
|
|
if (tm->tm_mday>1)
|
|
start = (36+tm->tm_wday-tm->tm_mday)%7;
|
|
else start = tm->tm_wday;
|
|
|
|
// What day does this month end on? Alas, libc doesn't tell us...
|
|
len = 31;
|
|
if (tm->tm_mon == 1) {
|
|
int year = tm->tm_year;
|
|
len = 28;
|
|
if (!(year & 3) && !((year&100) && !(year&400))) len++;
|
|
} else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30;
|
|
|
|
for (mday=line=0;line<6;line++) {
|
|
for (wday=0; wday<7; wday++) {
|
|
char *pat = " ";
|
|
if (!mday ? wday==start : mday<len) {
|
|
pat = "%2d ";
|
|
if (!FLAG(h) && tm->tm_year == TT.now->tm_year &&
|
|
tm->tm_mon == TT.now->tm_mon && mday == TT.now->tm_mday-1) {
|
|
pat = "\x1b[7m%2d\x1b[m ";
|
|
}
|
|
mday++;
|
|
}
|
|
buf += sprintf(buf, pat, mday);
|
|
}
|
|
buf++;
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
// Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line
|
|
// plus 8 lines/month plus 12 months, plus the escape sequences to highlight
|
|
// today comes to a bit over 2k of our 4k buffer.
|
|
|
|
void cal_main(void)
|
|
{
|
|
time_t now = time(0);
|
|
struct tm *tm = localtime(&now);
|
|
char *buf = toybuf;
|
|
|
|
TT.now = tm;
|
|
if (!isatty(1)) toys.optflags |= FLAG_h;
|
|
|
|
if (toys.optc) {
|
|
// Conveniently starts zeroed
|
|
tm = (struct tm *)toybuf;
|
|
buf += sizeof(struct tm);
|
|
|
|
// Last argument is year, one before that (if any) is month.
|
|
tm->tm_year = atolx_range(toys.optargs[--toys.optc], 1, 9999);
|
|
tm->tm_year -= 1900;
|
|
tm->tm_mday = 1;
|
|
tm->tm_hour = 12; // noon to avoid timezone weirdness
|
|
if (toys.optc) {
|
|
tm->tm_mon = atolx_range(toys.optargs[--toys.optc], 1, 12);
|
|
tm->tm_mon--;
|
|
|
|
// Print 12 months of the year
|
|
|
|
} else {
|
|
char *bufs[12];
|
|
int i, j, k;
|
|
|
|
for (i=0; i<12; i++) {
|
|
tm->tm_mon=i;
|
|
mktime(tm);
|
|
buf = calstrings(bufs[i]=buf, tm);
|
|
}
|
|
|
|
// 4 rows, 6 lines each, 3 columns
|
|
for (i=0; i<4; i++) {
|
|
for (j=0; j<8; j++) {
|
|
for(k=0; k<3; k++) {
|
|
char **b = bufs+(k+i*3);
|
|
*b += printf("%s ", *b);
|
|
}
|
|
puts("");
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// What day of the week does that start on?
|
|
mktime(tm);
|
|
}
|
|
|
|
calstrings(buf, tm);
|
|
while (*buf) buf += printf("%s\n", buf);
|
|
}
|