From b16438a23b237aa44fe9358a0b8954888bf81ea2 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Thu, 10 Dec 2020 23:57:33 +0100 Subject: Add support for counting to a specific calendar time (absolute time) --- extras.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++ extras.h | 6 +++- i3lock-extended.1 | 14 +++++++- i3lock.c | 10 +++++- unlock_indicator.c | 26 +++++++++++--- 5 files changed, 150 insertions(+), 8 deletions(-) diff --git a/extras.c b/extras.c index 37819f5..bde4172 100644 --- a/extras.c +++ b/extras.c @@ -132,6 +132,61 @@ static void i3lock_draw_led(cairo_t *cr, } +static char * i3lock_replace_str(char *to, + const char *from, + const char *old_substr, + const char *new_substr, + size_t max_length) { + + int offset; /* the offset in the tmp_str after each match */ + + /* the offset in from needed to pick up the right side after a match */ + int from_offset; + + int from_len = strlen(from); + int new_substr_len = strlen(new_substr); + int old_substr_len = strlen(old_substr); + int len_diff = old_substr_len - new_substr_len; + size_t free_space = max_length - 1; + char tmp_str[max_length]; + char *tmp_str_ptr; + + /* reserve the last byte for '\0' in case of clipping */ + strncpy(tmp_str, from, free_space); + + for (int i = 0; ; ++i) { + tmp_str_ptr = strstr(tmp_str, old_substr); + if (tmp_str_ptr == NULL) { + /* no more instances of old_substr */ + break; + } + + offset = tmp_str_ptr - tmp_str; + free_space -= offset; + if (free_space <= new_substr_len) { + strncpy(tmp_str_ptr, new_substr, free_space); + break; + } + strncpy(tmp_str_ptr, new_substr, new_substr_len); + free_space -= new_substr_len; + /* tmp_str offset -> from_offset mapping */ + from_offset = offset + old_substr_len + i * len_diff; + if (free_space <= from_len - from_offset) { + strncpy(tmp_str_ptr + new_substr_len, from + from_offset, free_space); + break; + } + strncpy(tmp_str_ptr + new_substr_len, from + from_offset, from_len - from_offset + 1); + + } + + strncpy(to, tmp_str, max_length - 1); + *(to + (max_length - 1)) = '\0'; + + return to; + +} + + void i3lock_draw_digital_clock(cairo_t *cr, const i3lock_digital_clock_t *dc, const uint32_t *resolution, @@ -440,9 +495,56 @@ void i3lock_draw_led_clock(cairo_t *cr, brokentime->tm_sec & 1, lc); } + return; + } } +char * i3lock_format_elapsed_time(char *to, + const char *template, + int max_size, + int seconds) { + + char tmp_str[max_size]; + char int_str[32]; /* more than enough for int */ + int days = seconds / 86400; + int hours = (seconds - days * 86400) / 3600; + int minutes = (seconds - days * 86400 - hours * 3600) / 60; + int rest_seconds = seconds - days * 86400 - hours * 3600 - minutes * 60; + + strncpy(tmp_str, template, max_size); + if (strlen(template) >= max_size) { + /* do a proper clipping */ + *(tmp_str + (max_size - 1)) = '\0'; + } + + /* days */ + snprintf(int_str, 32, "%d", days); + i3lock_replace_str(to, tmp_str, "%d", int_str, max_size); + strcpy(tmp_str, to); + + /* hours */ + snprintf(int_str, 32, "%d", hours); + i3lock_replace_str(to, tmp_str, "%h", int_str, max_size); + strcpy(tmp_str, to); + + /* minutes */ + snprintf(int_str, 32, "%d", minutes); + i3lock_replace_str(to, tmp_str, "%m", int_str, max_size); + strcpy(tmp_str, to); + + /* rest. seconds */ + snprintf(int_str, 32, "%d", rest_seconds); + i3lock_replace_str(to, tmp_str, "%s", int_str, max_size); + strcpy(tmp_str, to); + + /* seconds */ + snprintf(int_str, 32, "%d", seconds); + i3lock_replace_str(to, tmp_str, "%S", int_str, max_size); + + return to; + +} diff --git a/extras.h b/extras.h index d4a353e..c78ffff 100644 --- a/extras.h +++ b/extras.h @@ -88,7 +88,6 @@ void i3lock_draw_elapsed_time(cairo_t *cr, const uint32_t *resolution, const time_t *now); - void i3lock_draw_led_clock(cairo_t *cr, const i3lock_led_clock_t *lc, const uint32_t *resolution, @@ -99,4 +98,9 @@ void i3lock_draw_string(cairo_t *cr, const char *formatted_string, const i3lock_elapsed_time_t *et, const uint32_t *resolution); + +char * i3lock_format_elapsed_time(char *to, + const char *template, + int max_size, + int seconds); #endif diff --git a/i3lock-extended.1 b/i3lock-extended.1 index b0f51a7..34ea2a3 100644 --- a/i3lock-extended.1 +++ b/i3lock-extended.1 @@ -8,7 +8,7 @@ .fi .. -.TH i3lock\-extended 1 "MARCH 2020" Linux "User Manuals" +.TH i3lock\-extended 1 "DECEMBER 2020" Linux "User Manuals" .SH NAME i3lock\-extended \- improved screen locker @@ -18,6 +18,8 @@ i3lock\-extended \- improved screen locker .RB [\|\-B .IR color \|] .RB [\|\-b\|] +.RB [\|\-C +.IR seconds \|] .RB [\|\-c .IR color \|] .RB [\|\-D\|] @@ -94,6 +96,8 @@ Digital clock Elapsed time since activation .IP \[bu] Display-text +.IP \[bu] +Count to a specific calendar time (absolute time) .SH OPTIONS .TP @@ -111,6 +115,14 @@ like when opening your laptop in a boring lecture. Turn the screen into the given color instead of white. Color must be given in 3-byte. Default: ffffff (white). +.TP +.BI \-C\ seconds \fR,\ \fB\-\-count\-until= seconds +Sets the seconds since the Epoch to count to. date +%s -d ... can be used to +get the Epoch time. Then the following macros will become available for the +display-text parameter: %d - days remaining until the time set, +%h - hours remaining, %m - minutes remaining, %s - seconds remaining, +%S - total amount of seconds remaining. Default: 0 (count until is off). + .TP .B \-D, \-\-digital\-clock Display digital clock. diff --git a/i3lock.c b/i3lock.c index f7c5bdc..d492e5a 100644 --- a/i3lock.c +++ b/i3lock.c @@ -84,6 +84,7 @@ static void input_done(void); bool digital_clock = false; bool led_clock = false; bool elapsed_time = false; +int count_until = 0; /* count seconds until */ int refresh_rate = 2; /* 2 frames per second */ i3lock_digital_clock_t i3lock_digital_clock = {28, "000000", @@ -1083,6 +1084,7 @@ int main(int argc, char *argv[]) { {"dpms", no_argument, NULL, 'd'}, {"color", required_argument, NULL, 'c'}, #ifdef EXTRAS + {"count-until", no_argument, NULL, 'C'}, {"digital-clock", no_argument, NULL, 'D'}, {"digital-clock-color", required_argument, NULL, 'G'}, {"digital-clock-template", required_argument, NULL, 'T'}, @@ -1122,7 +1124,7 @@ int main(int argc, char *argv[]) { errx(EXIT_FAILURE, "i3lock is a program for X11 and does not work on Wayland. Try https://github.com/swaywm/swaylock instead"); #ifdef EXTRAS - char *optstring = "hvnbDdELc:B:G:F:J:O:R:r:S:T:W:X:x:Y:y:Z:p:ui:teI:f"; + char *optstring = "hvnbDdELC:c:B:G:F:J:O:R:r:S:T:W:X:x:Y:y:Z:p:ui:teI:f"; #else char *optstring = "hvnbdc:p:ui:teI:f"; #endif @@ -1156,6 +1158,12 @@ int main(int argc, char *argv[]) { break; } #ifdef EXTRAS + case 'C': /* count until */ + if (optarg != NULL && atoi(optarg) > 0) /* not nice with -1 and 0 */ + count_until = atoi(optarg); + DEBUG("count_until: %d\n", + count_until); + break; case 'D': digital_clock = true; break; diff --git a/unlock_indicator.c b/unlock_indicator.c index 73320cb..8f69972 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -58,12 +58,15 @@ extern bool debug_mode; #ifdef EXTRAS /* timekeeping */ +#define I3LOCK_COUNT_UNTIL_BUFFER 128 +char count_until_str[I3LOCK_COUNT_UNTIL_BUFFER]; time_t now; struct tm *brokentime; /* enable the digital clock */ extern bool digital_clock; extern bool led_clock; extern bool elapsed_time; +extern int count_until; extern i3lock_digital_clock_t i3lock_digital_clock; extern i3lock_elapsed_time_t i3lock_elapsed_time; extern i3lock_led_clock_t i3lock_led_clock; @@ -359,17 +362,30 @@ void draw_image(xcb_pixmap_t bg_pixmap, uint32_t *resolution) { resolution, brokentime); } - /* elapsed time or display text */ + /* elapsed time or counter with display text or only display text */ if (elapsed_time) { i3lock_draw_elapsed_time(xcb_ctx, &i3lock_elapsed_time, resolution, &now); } else if (display_text != NULL) { - i3lock_draw_string(xcb_ctx, - display_text, - &i3lock_elapsed_time, - resolution); + if (count_until) { + if (i3lock_format_elapsed_time( + count_until_str, + display_text, + I3LOCK_COUNT_UNTIL_BUFFER, + count_until - (int) now) != NULL) { + i3lock_draw_string(xcb_ctx, + count_until_str, + &i3lock_elapsed_time, + resolution); + } + } else { + i3lock_draw_string(xcb_ctx, + display_text, + &i3lock_elapsed_time, + resolution); + } } #endif if (xr_screens > 0) { -- cgit v1.3