*~
.vimrc
acal
+test
tags
│ 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 │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ ────────┼─────────┴─────────┴─────────┴─────────┴─────────┴──────── │
{
endwin();
refresh();
+ screen_resize();
screen_draw();
}
# 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 $@ $<
{ "Help", help_init, help_draw, help_run, {KEY_F(8), '8', 'h', '?'} },
};
-int active = 0;
+int active = 2;
/* Local functions */
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);
}
}
}
+/* 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 */
/* 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);
--- /dev/null
+#include "util.h"
+
+int main(int argc, char **argv)
+{
+ test_time();
+ return 0;
+}
--- /dev/null
+/* Time Keeping Bugs Abound! */
+
+#include <stdio.h>
+
+#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");
+ }
+}
--- /dev/null
+/* 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);
+#include <string.h>
#include <ncurses.h>
+#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)
{
/* 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 */