diff --git a/res/config.ini b/res/config.ini index 45dc7da..e454e10 100644 --- a/res/config.ini +++ b/res/config.ini @@ -6,6 +6,11 @@ # 1 -> CMatrix #animation = 0 +# format string for clock in top right corner (see strftime specification) +#clock = %c + +# enable/disable big clock +#bigclock = true # The character used to mask the password #asterisk = * diff --git a/src/bigclock.h b/src/bigclock.h new file mode 100644 index 0000000..2de834a --- /dev/null +++ b/src/bigclock.h @@ -0,0 +1,146 @@ +#include + +#define CLOCK_W 5 +#define CLOCK_H 5 + +#if defined(__linux__) || defined(__FreeBSD__) + #define X 0x2593 + #define _ 0x0000 +#else + #define X '#' + #define _ 0 +#endif + +#if CLOCK_W == 5 && CLOCK_H == 5 + +uint32_t CLOCK_0[] = { + X,X,X,X,X, + X,X,_,X,X, + X,X,_,X,X, + X,X,_,X,X, + X,X,X,X,X +}; + +uint32_t CLOCK_1[] = { + _,_,_,X,X, + _,_,_,X,X, + _,_,_,X,X, + _,_,_,X,X, + _,_,_,X,X +}; + +uint32_t CLOCK_2[] = { + X,X,X,X,X, + _,_,_,X,X, + X,X,X,X,X, + X,X,_,_,_, + X,X,X,X,X +}; + +uint32_t CLOCK_3[] = { + X,X,X,X,X, + _,_,_,X,X, + X,X,X,X,X, + _,_,_,X,X, + X,X,X,X,X +}; + +uint32_t CLOCK_4[] = { + X,X,_,X,X, + X,X,_,X,X, + X,X,X,X,X, + _,_,_,X,X, + _,_,_,X,X +}; + +uint32_t CLOCK_5[] = { + X,X,X,X,X, + X,X,_,_,_, + X,X,X,X,X, + _,_,_,X,X, + X,X,X,X,X +}; + +uint32_t CLOCK_6[] = { + X,X,X,X,X, + X,X,_,_,_, + X,X,X,X,X, + X,X,_,X,X, + X,X,X,X,X, +}; + +uint32_t CLOCK_7[] = { + X,X,X,X,X, + _,_,_,X,X, + _,_,_,X,X, + _,_,_,X,X, + _,_,_,X,X +}; + +uint32_t CLOCK_8[] = { + X,X,X,X,X, + X,X,_,X,X, + X,X,X,X,X, + X,X,_,X,X, + X,X,X,X,X +}; + +uint32_t CLOCK_9[] = { + X,X,X,X,X, + X,X,_,X,X, + X,X,X,X,X, + _,_,_,X,X, + X,X,X,X,X +}; + +uint32_t CLOCK_S[] = { + _,_,_,_,_, + _,_,X,_,_, + _,_,_,_,_, + _,_,X,_,_, + _,_,_,_,_ +}; + +uint32_t CLOCK_E[] = { + _,_,_,_,_, + _,_,_,_,_, + _,_,_,_,_, + _,_,_,_,_, + _,_,_,_,_ +}; + +#endif + +#undef X +#undef _ + +static inline uint32_t* CLOCK_N(char c) +{ + switch(c) + { + case '0': + return CLOCK_0; + case '1': + return CLOCK_1; + case '2': + return CLOCK_2; + case '3': + return CLOCK_3; + case '4': + return CLOCK_4; + case '5': + return CLOCK_5; + case '6': + return CLOCK_6; + case '7': + return CLOCK_7; + case '8': + return CLOCK_8; + case '9': + return CLOCK_9; + case ':': + return CLOCK_S; + default: + return CLOCK_E; + } +} diff --git a/src/config.c b/src/config.c index bf7f20e..1704d9d 100644 --- a/src/config.c +++ b/src/config.c @@ -161,8 +161,10 @@ void config_load(const char *cfg_path) {"animation", &config.animation, config_handle_u8}, {"asterisk", &config.asterisk, config_handle_char}, {"bg", &config.bg, config_handle_u8}, + {"bigclock", &config.bigclock, config_handle_bool}, {"blank_box", &config.blank_box, config_handle_bool}, {"blank_password", &config.blank_password, config_handle_bool}, + {"clock", &config.clock, config_handle_str}, {"console_dev", &config.console_dev, config_handle_str}, {"default_input", &config.default_input, config_handle_u8}, {"fg", &config.fg, config_handle_u8}, @@ -269,8 +271,10 @@ void config_defaults() config.animation = 0; config.asterisk = '*'; config.bg = 0; + config.bigclock = false; config.blank_box = true; config.blank_password = false; + config.clock = NULL; config.console_dev = strdup("/dev/console"); config.default_input = LOGIN_INPUT; config.fg = 9; @@ -354,6 +358,7 @@ void lang_free() void config_free() { + free(config.clock); free(config.console_dev); free(config.lang); free(config.mcookie_cmd); diff --git a/src/config.h b/src/config.h index 67985bb..914cf05 100644 --- a/src/config.h +++ b/src/config.h @@ -65,8 +65,10 @@ struct config uint8_t animation; char asterisk; uint8_t bg; + bool bigclock; bool blank_box; bool blank_password; + char* clock; char* console_dev; uint8_t default_input; uint8_t fg; diff --git a/src/draw.c b/src/draw.c index 81de187..454ee87 100644 --- a/src/draw.c +++ b/src/draw.c @@ -5,6 +5,7 @@ #include "utils.h" #include "config.h" #include "draw.h" +#include "bigclock.h" #include #include @@ -14,7 +15,9 @@ #include #include #include +#include #include +#include #if defined(__DragonFly__) || defined(__FreeBSD__) #include @@ -176,6 +179,95 @@ void draw_box(struct term_buf* buf) } } +char* time_str(char* fmt, int maxlen) +{ + time_t timer; + char* buffer = malloc(maxlen); + struct tm* tm_info; + + timer = time(NULL); + tm_info = localtime(&timer); + + if (strftime(buffer, maxlen, fmt, tm_info) == 0) + buffer[0] = '\0'; + + return buffer; +} + +extern inline uint32_t* CLOCK_N(char c); + +struct tb_cell* clock_cell(char c) +{ + struct tb_cell* cells = malloc(sizeof(struct tb_cell) * CLOCK_W * CLOCK_H); + + struct timeval tv; + gettimeofday(&tv, NULL); + if (config.animate && c == ':' && tv.tv_usec / 500000) + c = ' '; + uint32_t* clockchars = CLOCK_N(c); + + for (int i = 0; i < CLOCK_W * CLOCK_H; i++) + { + cells[i].ch = clockchars[i]; + cells[i].fg = config.fg; + cells[i].bg = config.bg; + } + + return cells; +} + +void alpha_blit(struct tb_cell* buf, uint16_t x, uint16_t y, uint16_t w, uint16_t h, struct tb_cell* cells) +{ + if (x + w >= tb_width() || y + h >= tb_height()) + return; + + for (int i = 0; i < h; i++) + { + for (int j = 0; j < w; j++) + { + struct tb_cell cell = cells[i * w + j]; + if (cell.ch) + buf[(y + i) * tb_width() + (x + j)] = cell; + } + } +} + +void draw_bigclock(struct term_buf* buf) +{ + if (!config.bigclock) + return; + + int xo = buf->width / 2 - (5 * (CLOCK_W + 1)) / 2; + int yo = (buf->height - buf->box_height) / 2 - CLOCK_H - 2; + + char* clockstr = time_str("%H:%M", 6); + struct tb_cell* clockcell; + + for (int i = 0; i < 5; i++) + { + clockcell = clock_cell(clockstr[i]); + alpha_blit(tb_cell_buffer(), xo + i * (CLOCK_W + 1), yo, CLOCK_W, CLOCK_H, clockcell); + free(clockcell); + } + + free(clockstr); +} + +void draw_clock(struct term_buf* buf) +{ + if (config.clock == NULL || strlen(config.clock) == 0) + return; + + char* clockstr = time_str(config.clock, 32); + int clockstrlen = strlen(clockstr); + + struct tb_cell* cells = strn_cell(clockstr, clockstrlen); + tb_blit(buf->width - clockstrlen, 0, clockstrlen, 1, cells); + + free(clockstr); + free(cells); +} + struct tb_cell* strn_cell(char* s, uint16_t len) // throws { struct tb_cell* cells = malloc((sizeof (struct tb_cell)) * len); diff --git a/src/draw.h b/src/draw.h index ce4cf60..0e6d164 100644 --- a/src/draw.h +++ b/src/draw.h @@ -86,4 +86,7 @@ void animate_init(struct term_buf* buf); void animate(struct term_buf* buf); bool cascade(struct term_buf* buf, uint8_t* fails); +void draw_bigclock(struct term_buf *buf); +void draw_clock(struct term_buf *buf); + #endif diff --git a/src/main.c b/src/main.c index 429b5b7..7136928 100644 --- a/src/main.c +++ b/src/main.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -187,7 +188,9 @@ int main(int argc, char** argv) (*input_handles[active_input])(input_structs[active_input], NULL); tb_clear(); animate(&buf); + draw_bigclock(&buf); draw_box(&buf); + draw_clock(&buf); draw_labels(&buf); if(!config.hide_f1_commands) draw_f_commands(); @@ -207,11 +210,26 @@ int main(int argc, char** argv) tb_present(); } - if (config.animate) { - error = tb_peek_event(&event, config.min_refresh_delta); - } else { - error = tb_poll_event(&event); + int timeout = -1; + + if (config.animate) + { + timeout = config.min_refresh_delta; } + else + { + struct timeval tv; + gettimeofday(&tv, NULL); + if (config.bigclock) + timeout = (60 - tv.tv_sec % 60) * 1000 - tv.tv_usec / 1000 + 1; + if (config.clock) + timeout = 1000 - tv.tv_usec / 1000 + 1; + } + + if (timeout == -1) + error = tb_poll_event(&event); + else + error = tb_peek_event(&event, timeout); if (error < 0) {