summaryrefslogblamecommitdiffstats
path: root/mbbsd/calendar.c
blob: d5c1fe6149aa95dba6aed97d204f8a9951a718d6 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
          
                

                        


                                           
                         

                        
          

                         
                                                                        
 


                                            
          


                                                     




                 
          



                         


                                                           
                           



                                    
          



                                  


                          
                       
                 
 


                       

                                                       




                                              
          

                       
            


























                            
      

                      
                                                            
                                             



                            
           




                                                                    



                      
           




                      





                    






                             
                     
                                   
                         





                                                   
                         
 


                                          
                                            
                         
 
                                        
                                                        



                                              
                                                                   



                                         
     


                     





                                 

                                             
                              



                              
           

                         








                                        
          

                                                                  

                                                                      



                                                           
                              


                                                                   
 



                                                                 



                                                                      
                           

                                            
 


                                              
                                              
                               
 
                       

                                                  
                               



                                                   



                                                  
                                         
                                                          


                                                    

                     


                                     
                                       


                                                                       
                           



                                                          
 
                               

                               





                                                   
   






                                              
                         


                                                                     
 

                                
 

                                  
                            
                                    
                             
                                                                   
                    



                       
 


                
                              
                     
                     
                                                                          
                                                                      
                                                              

                                                                    
                                 











                                                                      
/* $Id$ */
#include "bbs.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)
{
    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; (unsigned)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;
    }
}

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)
{
    char    *week_str[7] = {"日", "一", "二", "三", "四", "五", "六"};
    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"
    };
    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) {
        strlcpy(attr1, "\33[1;37;42m", sizeof(attr1));
        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;
    struct tm       snow;
    int             i, y, m, today, lines = 0;
    event_t        *head = NULL, *e = NULL;

    /* initialize date */
    memcpy(&snow, localtime(&now), sizeof(struct tm));
    today = Days(snow.tm_year + 1900, snow.tm_mon + 1, snow.tm_mday);
    y = snow.tm_year + 1900, m = snow.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",
           snow.tm_year + 1900, snow.tm_mon + 1, snow.tm_mday,
           (snow.tm_hour == 0 || snow.tm_hour == 12) ?
           12 : snow.tm_hour % 12, snow.tm_min, snow.tm_sec,
           snow.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;
}