mirror of https://github.com/fairyglade/ly.git
Clocks (#461)
* Added a big clock * fixed clock timing when animation is turned off * fix memory leak and segfault * rename clock to bigclock * Added formattable clock * fix clock position on first draw don't rely on box_x and box_y to position the clock, because it might not be initialized in the first frame. * fix memory leak
This commit is contained in:
parent
f9848f648b
commit
1124c126f9
|
@ -6,6 +6,11 @@
|
||||||
# 1 -> CMatrix
|
# 1 -> CMatrix
|
||||||
#animation = 0
|
#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
|
# The character used to mask the password
|
||||||
#asterisk = *
|
#asterisk = *
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -161,8 +161,10 @@ void config_load(const char *cfg_path)
|
||||||
{"animation", &config.animation, config_handle_u8},
|
{"animation", &config.animation, config_handle_u8},
|
||||||
{"asterisk", &config.asterisk, config_handle_char},
|
{"asterisk", &config.asterisk, config_handle_char},
|
||||||
{"bg", &config.bg, config_handle_u8},
|
{"bg", &config.bg, config_handle_u8},
|
||||||
|
{"bigclock", &config.bigclock, config_handle_bool},
|
||||||
{"blank_box", &config.blank_box, config_handle_bool},
|
{"blank_box", &config.blank_box, config_handle_bool},
|
||||||
{"blank_password", &config.blank_password, 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},
|
{"console_dev", &config.console_dev, config_handle_str},
|
||||||
{"default_input", &config.default_input, config_handle_u8},
|
{"default_input", &config.default_input, config_handle_u8},
|
||||||
{"fg", &config.fg, config_handle_u8},
|
{"fg", &config.fg, config_handle_u8},
|
||||||
|
@ -269,8 +271,10 @@ void config_defaults()
|
||||||
config.animation = 0;
|
config.animation = 0;
|
||||||
config.asterisk = '*';
|
config.asterisk = '*';
|
||||||
config.bg = 0;
|
config.bg = 0;
|
||||||
|
config.bigclock = false;
|
||||||
config.blank_box = true;
|
config.blank_box = true;
|
||||||
config.blank_password = false;
|
config.blank_password = false;
|
||||||
|
config.clock = NULL;
|
||||||
config.console_dev = strdup("/dev/console");
|
config.console_dev = strdup("/dev/console");
|
||||||
config.default_input = LOGIN_INPUT;
|
config.default_input = LOGIN_INPUT;
|
||||||
config.fg = 9;
|
config.fg = 9;
|
||||||
|
@ -354,6 +358,7 @@ void lang_free()
|
||||||
|
|
||||||
void config_free()
|
void config_free()
|
||||||
{
|
{
|
||||||
|
free(config.clock);
|
||||||
free(config.console_dev);
|
free(config.console_dev);
|
||||||
free(config.lang);
|
free(config.lang);
|
||||||
free(config.mcookie_cmd);
|
free(config.mcookie_cmd);
|
||||||
|
|
|
@ -65,8 +65,10 @@ struct config
|
||||||
uint8_t animation;
|
uint8_t animation;
|
||||||
char asterisk;
|
char asterisk;
|
||||||
uint8_t bg;
|
uint8_t bg;
|
||||||
|
bool bigclock;
|
||||||
bool blank_box;
|
bool blank_box;
|
||||||
bool blank_password;
|
bool blank_password;
|
||||||
|
char* clock;
|
||||||
char* console_dev;
|
char* console_dev;
|
||||||
uint8_t default_input;
|
uint8_t default_input;
|
||||||
uint8_t fg;
|
uint8_t fg;
|
||||||
|
|
92
src/draw.c
92
src/draw.c
|
@ -5,6 +5,7 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
#include "bigclock.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -14,7 +15,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
#include <sys/kbio.h>
|
#include <sys/kbio.h>
|
||||||
|
@ -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* strn_cell(char* s, uint16_t len) // throws
|
||||||
{
|
{
|
||||||
struct tb_cell* cells = malloc((sizeof (struct tb_cell)) * len);
|
struct tb_cell* cells = malloc((sizeof (struct tb_cell)) * len);
|
||||||
|
|
|
@ -86,4 +86,7 @@ void animate_init(struct term_buf* buf);
|
||||||
void animate(struct term_buf* buf);
|
void animate(struct term_buf* buf);
|
||||||
bool cascade(struct term_buf* buf, uint8_t* fails);
|
bool cascade(struct term_buf* buf, uint8_t* fails);
|
||||||
|
|
||||||
|
void draw_bigclock(struct term_buf *buf);
|
||||||
|
void draw_clock(struct term_buf *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
26
src/main.c
26
src/main.c
|
@ -14,6 +14,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -187,7 +188,9 @@ int main(int argc, char** argv)
|
||||||
(*input_handles[active_input])(input_structs[active_input], NULL);
|
(*input_handles[active_input])(input_structs[active_input], NULL);
|
||||||
tb_clear();
|
tb_clear();
|
||||||
animate(&buf);
|
animate(&buf);
|
||||||
|
draw_bigclock(&buf);
|
||||||
draw_box(&buf);
|
draw_box(&buf);
|
||||||
|
draw_clock(&buf);
|
||||||
draw_labels(&buf);
|
draw_labels(&buf);
|
||||||
if(!config.hide_f1_commands)
|
if(!config.hide_f1_commands)
|
||||||
draw_f_commands();
|
draw_f_commands();
|
||||||
|
@ -207,11 +210,26 @@ int main(int argc, char** argv)
|
||||||
tb_present();
|
tb_present();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.animate) {
|
int timeout = -1;
|
||||||
error = tb_peek_event(&event, config.min_refresh_delta);
|
|
||||||
} else {
|
if (config.animate)
|
||||||
error = tb_poll_event(&event);
|
{
|
||||||
|
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)
|
if (error < 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue