From 351ba155fdf7db739f45f9d4381f0b979d9037ab Mon Sep 17 00:00:00 2001 From: Patrick McDermott Date: Sun, 13 Oct 2019 20:54:32 -0400 Subject: clock_*(): New functions And create and draw the clock on the screen. --- diff --git a/src/clock.c b/src/clock.c new file mode 100644 index 0000000..0e6085c --- /dev/null +++ b/src/clock.c @@ -0,0 +1,198 @@ +/* + * Clock screen functions + * + * Copyright (C) 2019 Patrick McDermott + * + * This file is part of Timeteller. + * + * Timeteller is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Timeteller is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Timeteller. If not, see . + */ + +#include "clock.h" + +#include +#include +#include +#include +#include +#include + +#include "screen.h" + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define NUM_DIGITS 6 +#define NUM_COLONS 2 +#define DIGIT_HEIGHT 5 +#define DIGIT_WIDTH 3 +#define COLON_WIDTH 1 +#define SPACING 1 + +static const uint16_t _clock_font[] = { + 075557, /* 0 */ + 011111, /* 1 */ + 071747, /* 2 */ + 071717, /* 3 */ + 055711, /* 4 */ + 074717, /* 5 */ + 074757, /* 6 */ + 071111, /* 7 */ + 075757, /* 8 */ + 075717, /* 9 */ + 004040, /* : */ +}; +#define COLON_DIGIT 10 + +struct clock { + WINDOW *win; + int begy; + int begx; + int font_size; +}; + +struct clock * +clock_new(WINDOW *win) +{ + struct clock *clock; + + clock = calloc(1, sizeof(*clock)); + if (clock == NULL) { + return NULL; + } + + if (clock_size(clock) == false) { + free(clock); + return NULL; + } + + clock->win = win; + + return clock; +} + +bool +clock_size(struct clock *clock) +{ + int win_h; + int win_w; + int clock_h; + int clock_w; + + assert(clock); + + getmaxyx(clock->win, win_h, win_w); + if (win_h < 0 && win_w < 0) { + win_h = LINES; + win_w = COLS; + } + clock_h = DIGIT_HEIGHT + SPACING * 2; + clock_w = NUM_DIGITS * (DIGIT_WIDTH + SPACING) + + NUM_COLONS * (COLON_WIDTH + SPACING) + + SPACING; + clock_w *= 2; /* A "dot" is two columns wide. */ + if (win_h < clock_h || win_w < clock_w) { + return false; + } + clock->font_size = MIN(win_h / clock_h, win_w / clock_w); + clock_h *= clock->font_size; + clock_w *= clock->font_size; + clock->begy = (win_h - clock_h ) / 2; + clock->begx = (win_w - clock_w + 1) / 2; + + return true; +} + +/* begy and begx are measured in dots from the top left corner of clock area. */ +static void +_clock_draw_dot(struct clock *clock, int begy, int begx, int dot) +{ + chtype ch; + int y; + int x; + + assert(clock); + + ch = ' ' | (dot ? A_REVERSE : 0); + + begy = clock->begy + begy * clock->font_size; + begx = clock->begx + (begx * clock->font_size) * 2; + for (y = 0; y < clock->font_size; ++y) { + for (x = 0; x < clock->font_size; ++x) { + mvwaddch(clock->win, begy + y, begx + x * 2 , ch); + mvwaddch(clock->win, begy + y, begx + x * 2 + 1, ch); + } + } +} + +/* begx is measured in dots from the left side of clock area. */ +static void +_clock_draw_digit(struct clock *clock, int begx, int d) +{ + int i; + int y; + int x; + int dot; + + assert(clock); + + for (i = 0; i < DIGIT_HEIGHT * DIGIT_WIDTH; ++i) { + y = 1 + i / DIGIT_WIDTH; + x = begx + i % DIGIT_WIDTH; + dot = _clock_font[d] & (1 << (DIGIT_HEIGHT*DIGIT_WIDTH-1-i)); + _clock_draw_dot(clock, y, x, dot); + } +} + +void +clock_draw(struct clock *clock) +{ + time_t t = 0; + struct tm *tm; + int x; + + assert(clock); + + time(&t); + if (t < (time_t) 0) { + return; + } + + tm = localtime(&t); + if (tm == NULL) { + return; + } + + x = 0; + _clock_draw_digit(clock, x += SPACING , tm->tm_hour / 10); + _clock_draw_digit(clock, x += SPACING + DIGIT_WIDTH, tm->tm_hour % 10); + _clock_draw_digit(clock, x += SPACING + DIGIT_WIDTH, COLON_DIGIT); + _clock_draw_digit(clock, x += SPACING + COLON_WIDTH, tm->tm_min / 10); + _clock_draw_digit(clock, x += SPACING + DIGIT_WIDTH, tm->tm_min % 10); + _clock_draw_digit(clock, x += SPACING + DIGIT_WIDTH, COLON_DIGIT); + _clock_draw_digit(clock, x += SPACING + COLON_WIDTH, tm->tm_sec / 10); + _clock_draw_digit(clock, x += SPACING + DIGIT_WIDTH, tm->tm_sec % 10); +} + +struct clock * +clock_destroy(struct clock **clock_p) +{ + struct clock *clock; + + assert(clock_p && *clock_p); + + clock = *clock_p; + + free(clock); + return clock = NULL; +} diff --git a/src/clock.h b/src/clock.h new file mode 100644 index 0000000..eedda1c --- /dev/null +++ b/src/clock.h @@ -0,0 +1,44 @@ +/* + * Clock screen functions + * + * Copyright (C) 2019 Patrick McDermott + * + * This file is part of Timeteller. + * + * Timeteller is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Timeteller is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Timeteller. If not, see . + */ + +#ifndef CLOCK_H_ +#define CLOCK_H_ + +#include +#include + +#include "screen.h" + +struct clock; + +struct clock * +clock_new(WINDOW *win); + +bool +clock_size(struct clock *clock); + +void +clock_draw(struct clock *clock); + +struct clock * +clock_destroy(struct clock **clock_p); + +#endif /* CLOCK_H_ */ diff --git a/src/local.mk b/src/local.mk index d9142ac..0429b52 100644 --- a/src/local.mk +++ b/src/local.mk @@ -1,4 +1,6 @@ timeteller_SOURCES += \ + %reldir%/clock.c \ + %reldir%/clock.h \ %reldir%/main.c \ %reldir%/screen.c \ %reldir%/screen.h \ diff --git a/src/main.c b/src/main.c index 673dd24..a3118db 100644 --- a/src/main.c +++ b/src/main.c @@ -67,6 +67,7 @@ main(int argc, char **argv) screen = screen_new(); + screen_draw(screen); speech_play_time(speech); screen_destroy(&screen); diff --git a/src/screen.c b/src/screen.c index a8b8b26..f705701 100644 --- a/src/screen.c +++ b/src/screen.c @@ -25,8 +25,11 @@ #include #include +#include "clock.h" + struct screen { - WINDOW *win; + WINDOW *win; + struct clock *clock; }; struct screen * @@ -46,12 +49,23 @@ screen_new(void) } curs_set(0); /* Ignore errors. */ + screen->clock = clock_new(screen->win); + if (screen->clock == NULL) { + free(screen); + return NULL; + } + return screen; } void screen_draw(struct screen *screen) { + assert(screen); + + clock_draw(screen->clock); + + refresh(); } struct screen * @@ -66,6 +80,8 @@ screen_destroy(struct screen **screen_p) delwin(screen->win); endwin(); + clock_destroy(&screen->clock); + free(screen); return screen = NULL; } -- cgit v0.9.1