summaryrefslogblamecommitdiffstats
path: root/mbbsd/calendar.c
blob: 78ca46cf8fe00752810ac157a6a1feeba4ea94b9 (plain) (tree)



























































































































































































































































































                                                                              
/* $Id: calendar.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#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;
}