/* $Id: calendar.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ #include #include #include #include #include #include "config.h" #include "pttstruct.h" #include "proto.h" #include "modes.h" typedef struct event_t { int year, month, day, days; int color; char *content; struct event_t *next; } event_t; static int MonthDay(int m, int leap) { static int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; return leap && m == 2 ? 29 : day[m - 1]; } static int IsLeap(int y) { if(y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) return 1; else return 0; } static int Days(int y, int m, int d) { int i, w; w = 1 + 365 * (y - 1) + ((y - 1) / 4) - ((y - 1) / 100) + ((y - 1) / 400) + d - 1; for(i = 1; i < m; i++) w += MonthDay(i, IsLeap(y)); return w; } static int ParseDate(char *date, event_t *t) { char *y, *m, *d; y = strtok(date, "/"); m = strtok(NULL, "/"); d = strtok(NULL, ""); if(!y || !m || !d) return 1; t->year = atoi(y); t->month = atoi(m); t->day = atoi(d); if(t->year < 1 || t->month < 1 || t->month > 12 || t->day < 1 || t->day > 31) return 1; t->days = Days(t->year, t->month, t->day); return 0; } static int ParseColor(char *color) { struct { char *str; int val; } c[] = { {"black", 0}, {"red", 1}, {"green", 2}, {"yellow", 3}, {"blue", 4}, {"magenta", 5}, {"cyan", 6}, {"white", 7} }; int i; for(i = 0; i < sizeof(c) / sizeof(c[0]); i++) if(strcasecmp(color, c[i].str) == 0) return c[i].val; return 7; } static void InsertEvent(event_t *head, event_t *t) { event_t *p; for(p = head; p->next && p->next->days < t->days; p = p->next); t->next = p->next; p->next = t; } static void FreeEvent(event_t *e) { event_t *n; while(e) { n = e->next; free(e); e = n; } } extern userec_t cuser; static event_t *ReadEvent(int today) { FILE *fp; char buf[256]; static event_t head; head.next = NULL; setcalfile(buf, cuser.userid); fp = fopen(buf, "r"); if(fp) { while(fgets(buf, sizeof(buf), fp)) { char *date, *color, *content; event_t *t; if(buf[0] == '#') continue; date = strtok(buf, " \t\n"); color = strtok(NULL, " \t\n"); content = strtok(NULL, "\n"); if(!date || !color || !content) continue; t = malloc(sizeof(event_t)); if(ParseDate(date, t) || t->days < today) { free(t); continue; } t->color = ParseColor(color) + 30; for(; *content == ' ' || *content == '\t'; content++); t->content = strdup(content); InsertEvent(&head, t); } fclose(fp); } return head.next; } static char **AllocCalBuffer(int line, int len) { int i; char **p; p = malloc(sizeof(char *) * line); p[0] = malloc(sizeof(char) * line * len); for(i = 1; i < line; i++) p[i] = p[i - 1] + len; return p; } static void FreeCalBuffer(char **buf) { free(buf[0]); free(buf); } #define CALENDAR_COLOR "\33[0;30;47m" #define HEADER_COLOR "\33[1;44m" #define HEADER_SUNDAY_COLOR "\33[31m" #define HEADER_DAY_COLOR "\33[33m" static int GenerateCalendar(char **buf, int y, int m, int today, event_t *e) { static char *week_str[7] = {"日", "一", "二", "三", "四", "五", "六"}; static char *month_color[12] = { "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m", "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m", "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m" }; static char *month_str[12] = { "一月 ", "二月 ", "三月 ", "四月 ", "五月 ", "六月 ", "七月 ", "八月 ", "九月 ", "十月 ", "十一月", "十二月" }; char *p, attr1[16], *attr2; int i, d, w, line = 0, first_day = Days(y, m, 1); /* week day banner */ p = buf[line]; p += sprintf(p, " %s%s%s%s", HEADER_COLOR, HEADER_SUNDAY_COLOR, week_str[0], HEADER_DAY_COLOR); for(i = 1; i < 7; i++) p += sprintf(p, " %s", week_str[i]); p += sprintf(p, "\33[m"); /* indent for first line */ p = buf[++line]; p += sprintf(p, " %s", CALENDAR_COLOR); for(i = 0, w = first_day % 7; i < w; i++) p += sprintf(p, " "); /* initial event */ for(; e && e->days < first_day; e = e->next); d = MonthDay(m, IsLeap(y)); for(i = 1; i <= d; i++, w = (w + 1) % 7) { attr1[0] = 0; attr2 = ""; while(e && e->days == first_day + i - 1) { sprintf(attr1, "\33[1;%dm", e->color); attr2 = CALENDAR_COLOR; e = e->next; } if(today == first_day + i - 1) { strcpy(attr1, "\33[1;37;42m"); attr2 = CALENDAR_COLOR; } p += sprintf(p, "%s%2d%s", attr1, i, attr2); if(w == 6) { p += sprintf(p, "\33[m"); p = buf[++line]; /* show month */ if(line >= 2 && line <= 4) p += sprintf(p, "%s%2.2s\33[m %s", month_color[m - 1], month_str[m - 1] + (line - 2) * 2, CALENDAR_COLOR); else if(i < d) p += sprintf(p, " %s", CALENDAR_COLOR); } else *p++ = ' '; } /* fill up the last line */ if(w) { for(w = 7 - w; w; w--) p += sprintf(p, w == 1 ? " " : " "); p += sprintf(p, "\33[m"); } return line + 1; } int calendar() { char **buf; time_t t; struct tm now; int i, y, m, today, lines = 0; event_t *head = NULL, *e = NULL; /* initialize date */ time(&t); memcpy(&now, localtime(&t), sizeof(struct tm)); today = Days(now.tm_year + 1900, now.tm_mon + 1, now.tm_mday); y = now.tm_year + 1900, m = now.tm_mon + 1; /* read event */ head = e = ReadEvent(today); /* generate calendar */ buf = AllocCalBuffer(22, 256); for(i = 0; i < 22; i++) sprintf(buf[i], "%24s", ""); for(i = 0; i < 3; i++) { lines += GenerateCalendar(buf + lines, y, m, today, e) + 1; if(m == 12) y++, m = 1; else m++; } /* output */ clear(); outc('\n'); for(i = 0; i < 22; i++) { outs(buf[i]); if(i == 0) { prints("\t\33[1;37m現在是 %d.%02d.%02d %2d:%02d:%02d%cm\33[m", now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, (now.tm_hour == 0 || now.tm_hour == 12) ? 12 : now.tm_hour % 12, now.tm_min, now.tm_sec, now.tm_hour >= 12 ? 'p' : 'a'); } else if(i >= 2 && e) { prints("\t\33[1;37m(\33[%dm%3d\33[37m)\33[m %02d/%02d %s", e->color, e->days - today, e->month, e->day, e->content); e = e->next; } outc('\n'); } FreeEvent(head); FreeCalBuffer(buf); pressanykey(); return 0; }