From: Andy Spencer Date: Thu, 4 Oct 2012 08:01:00 +0000 (+0000) Subject: Add utils, tests, and month view X-Git-Url: http://pileus.org/git/?p=lackey;a=commitdiff_plain;h=78e336e0f67c12e154121d293aeaca4d7c15c17a Add utils, tests, and month view --- diff --git a/.gitignore b/.gitignore index a88d9f9..a85852f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ *~ .vimrc acal +test tags diff --git a/screen.txt b/screen.txt index a510773..293f2d0 100644 --- a/screen.txt +++ b/screen.txt @@ -68,25 +68,25 @@ Month view │ Day Week Month Year │ Todo Notes │ Settings Help │ │ ─────────────────────────────────────────────────────────────────── │ │ September 2012 │ - │ Mon Tue Wed Thu Fri Sat Sun │ + │ Sun Mon Tue Wed Thu Fri Sat │ │ ─────────────────────────────────────────────────────────────────── │ - │ │ 1 │ + │ │1 │ │ │ │ │ │ │ │ ────────┬─────────┬─────────┬─────────┬─────────┬─────────┼──────── │ - │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ + │ 2 │3 │4 │5 │6 │7 │8 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────── │ - │ 9 │ 10 │ 11 │ 12 │ 13 │ 14 │ 15 │ + │ 9 │10 │11 │12 │13 │14 │15 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────── │ - │ 16 │ 17 │ 18 │ 19 │ 20 │ 21 │ 22 │ + │ 16 │17 │18 │19 │20 │21 │22 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ────────┼─────────┼─────────┼─────────┼─────────┼─────────┼──────── │ - │ 23 │ 24 │ 25 │ 26 │ 27 │ 28 │ 29 │ + │ 23 │24 │25 │26 │27 │28 │29 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ────────┼─────────┴─────────┴─────────┴─────────┴─────────┴──────── │ diff --git a/src/main.c b/src/main.c index a5d89c9..4161b03 100644 --- a/src/main.c +++ b/src/main.c @@ -22,6 +22,7 @@ static void on_sigwinch(int signum) { endwin(); refresh(); + screen_resize(); screen_draw(); } diff --git a/src/makefile b/src/makefile index 20ac4a8..afa1115 100644 --- a/src/makefile +++ b/src/makefile @@ -1,29 +1,37 @@ # Settings CC = gcc CFLAGS = -Wall --std=c99 -CPPFLAGS = +CPPFLAGS = -I. LDFLAGS = -lncursesw PROG = acal +TEST = test # Views -SOURCES = main screen +SOURCES = main screen util +TESTS = test util VIEWS = day week month year todo notes settings help -default: test +default: run-$(PROG) # Targets -all: $(PROG) +all: $(PROG) $(TEST) -test: $(PROG) +run-$(PROG): $(PROG) @urxvt -e ./$< @cat acal.log +run-$(TEST): $(TEST) + ./$< + clean: - rm -f *.o view/*.o $(PROG) + rm -f *.o view/*.o $(PROG) $(TEST) # Rules $(PROG): $(SOURCES:%=%.o) $(VIEWS:%=view/%.o) $(CC) $(CLFAGS) -o $@ $+ $(LDFLAGS) +$(TEST): $(TESTS:%=%.o) $(VIEWS:%=view/%.o) + $(CC) $(CLFAGS) -o $@ $+ $(LDFLAGS) + %.o: %.c $(SOURCES:%=%.h) makefile $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< diff --git a/src/screen.c b/src/screen.c index f31a738..b02d068 100644 --- a/src/screen.c +++ b/src/screen.c @@ -27,7 +27,7 @@ view_t views[] = { { "Help", help_init, help_draw, help_run, {KEY_F(8), '8', 'h', '?'} }, }; -int active = 0; +int active = 2; /* Local functions */ void draw_header(void) @@ -37,7 +37,7 @@ void draw_header(void) for (int i = 0; i < N_ELEMENTS(views); i++) { if (i == active) attron(A_BOLD); - printw(" %s", views[i].name); + printw("%s ", views[i].name); if (i == active) attroff(A_BOLD); } @@ -57,11 +57,21 @@ void screen_init(void) } } +/* Screen draw */ +void screen_resize(void) +{ + for (int i = 0; i < N_ELEMENTS(views); i++) + if (views[i].init) + wresize(views[i].win, LINES-2, COLS); +} + /* Screen draw */ void screen_draw(void) { draw_header(); + werase(views[active].win); views[active].draw(); + wrefresh(views[active].win); } /* Screen set */ diff --git a/src/screen.h b/src/screen.h index 7f6aa9d..116840a 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,5 +1,6 @@ /* Screen functions */ void screen_init(void); +void screen_resize(void); void screen_draw(void); int screen_run(int key, mmask_t btn, int row, int col); diff --git a/src/test.c b/src/test.c new file mode 100644 index 0000000..0619226 --- /dev/null +++ b/src/test.c @@ -0,0 +1,7 @@ +#include "util.h" + +int main(int argc, char **argv) +{ + test_time(); + return 0; +} diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..55cd265 --- /dev/null +++ b/src/util.c @@ -0,0 +1,105 @@ +/* Time Keeping Bugs Abound! */ + +#include + +#include "util.h" + +/* Helper functions */ +static int is_leap_year(year_t year) +{ + return (year % 400 == 0) ? 1 : + (year % 100 == 0) ? 0 : + (year % 4 == 0) ? 1 : 0; +} + +static wday_t day_of_week(year_t year, month_t month, day_t day) +{ + static int tmp[] = {0, 3, 2, 5, 0, 3, + 5, 1, 4, 6, 2, 4}; + if (month < 3) + year--; + int start = year + year / 4 + - year / 100 + + year / 400 + + tmp[month]; + return (start + day) % 7; +} + +/* Time functions */ +int days_in_year(year_t year) +{ + return 365 + is_leap_year(year); +} + +int days_in_month(year_t year, month_t month) +{ + static int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + int days = mdays[month]; + if (month == FEB) + days += is_leap_year(year); + return days; +} + +int weeks_in_month(year_t year, month_t month) +{ + int start = start_of_month(year, month); + int days = days_in_month(year, month); + return ((start + days)-1) / 7 + 1; +} + +wday_t start_of_month(year_t year, month_t month) +{ + return day_of_week(year, month, 1); +} + +/* Debug functions */ +const char *month_to_str(month_t month) +{ + static const char *map[] = + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; + return map[month]; +} +const char *month_to_string(month_t month) +{ + static const char *map[] = + { "January", "February", "March", "April", + "May", "June", "July", "August", + "September", "October", "November", "December" }; + return map[month]; +} + +const char *day_to_st(wday_t day) +{ + static const char *map[] = + { "Su","Mo", "Tu", "We", "Th", "Fr", "Sa" }; + return map[day]; +} +const char *day_to_str(wday_t day) +{ + static const char *map[] = + { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + return map[day]; +} +const char *day_to_string(wday_t day) +{ + static const char *map[] = + { "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" }; + return map[day]; +} + +/* Test functions */ +void test_time(void) +{ + printf("Year Month Start Weeks Days\n"); + for (int y = 2012; y <= 2012; y++) + for (int m = JAN; m <= DEC; m++) { + printf("%-5d", y); + printf("%-10s", month_to_string(m)); + printf("%-6s", day_to_str(start_of_month(y,m))); + printf("%-6d", weeks_in_month(y,m)); + printf("%-2d", days_in_month(y,m)); + printf("\n"); + } +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..57e7afc --- /dev/null +++ b/src/util.h @@ -0,0 +1,44 @@ +/* Types */ +typedef int year_t; +typedef int day_t; + +typedef enum { + JAN = 0, + FEB = 1, + MAR = 2, + APR = 3, + MAY = 4, + JUN = 5, + JUL = 6, + AUG = 7, + SEP = 8, + OCT = 9, + NOV = 10, + DEC = 11, +} month_t; + +typedef enum { + SUN = 0, + MON = 1, + TUE = 2, + WED = 3, + THU = 4, + FRI = 5, + SAT = 6, +} wday_t; + +/* Time functions */ +int days_in_year(year_t year); +int days_in_month(year_t year, month_t month); +int weeks_in_month(year_t year, month_t month); +wday_t start_of_month(year_t year, month_t month); + +/* String functions */ +const char *month_to_str(month_t month); +const char *month_to_string(month_t month); +const char *day_to_st(wday_t day); +const char *day_to_str(wday_t day); +const char *day_to_string(wday_t day); + +/* Tests */ +void test_time(void); diff --git a/src/view/month.c b/src/view/month.c index 85ef13e..d5bb538 100644 --- a/src/view/month.c +++ b/src/view/month.c @@ -1,8 +1,19 @@ +#include #include +#include "util.h" + +/* Macros */ +#define ROUND(x) ((int)((x)+0.5)) + /* Static data */ static WINDOW *win; +/* Test data */ +const static int YEAR = 2012; +const static int MONTH = SEP; +const static int DAY = 29; + /* Month init */ void month_init(WINDOW *_win) { @@ -12,8 +23,41 @@ void month_init(WINDOW *_win) /* Month draw */ void month_draw(void) { - mvwprintw(win, 0, 1, "%s\n", "month"); - wrefresh(win); + const char *name = month_to_string(MONTH); + const int start = start_of_month(YEAR, MONTH); + const int days = days_in_month(YEAR, MONTH); + const int weeks = weeks_in_month(YEAR, MONTH); + const float midpt = (float)COLS/2.0 - (strlen(name) + 1 + 4)/2.0; + const float hstep = (float)COLS/7.0; + const float vstep = (float)(LINES-4)/weeks; + + /* Print Header */ + mvwprintw(win, 0, midpt, "%s %d", name, YEAR); + for (int d = 0; d < 7; d++) + mvwprintw(win, 1, ROUND(d*hstep), "%s", day_to_str(d+SUN)); + mvwhline(win, 2, 0, ACS_HLINE, COLS); + + /* Print days */ + for (int d = 0; d < days; d++) { + int row = (start + d) / 7; + int col = (start + d) % 7; + mvwprintw(win, ROUND(3+row*vstep), ROUND(col*hstep), "%d", d+1); + } + + /* Print lines */ + for (int w = 1; w < weeks; w++) + mvwhline(win, ROUND(2+w*vstep), 0, ACS_HLINE, COLS); + for (int d = 1; d < 7; d++) { + int top = d >= start ? 0 : 1; + int bot = d <= (start+days)%7 ? weeks : weeks-1; + mvwvline(win, ROUND(3+top*vstep), ROUND(d*hstep-1), + ACS_VLINE, (bot-top)*vstep); + for (int w = 1; w < weeks; w++) { + int chr = w == top ? ACS_TTEE : + w == bot ? ACS_BTEE : ACS_PLUS; + mvwaddch(win, ROUND(2+w*vstep), ROUND(d*hstep-1), chr); + } + } } /* Month run */