diff options
| author | Simeon Simeonov | 2020-12-10 23:57:33 +0100 |
|---|---|---|
| committer | Simeon Simeonov | 2020-12-10 23:57:33 +0100 |
| commit | b16438a23b237aa44fe9358a0b8954888bf81ea2 (patch) | |
| tree | 9e0fcb3e8f3d4b1707bd702f2bf4429299d1e2e3 | |
| parent | 12a06184e733554bafc76e643b49067fcd758fc0 (diff) | |
Add support for counting to a specific calendar time (absolute time)
| -rw-r--r-- | extras.c | 102 | ||||
| -rw-r--r-- | extras.h | 6 | ||||
| -rw-r--r-- | i3lock-extended.1 | 14 | ||||
| -rw-r--r-- | i3lock.c | 10 | ||||
| -rw-r--r-- | unlock_indicator.c | 26 |
5 files changed, 150 insertions, 8 deletions
| @@ -132,6 +132,61 @@ static void i3lock_draw_led(cairo_t *cr, | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | 134 | ||
| 135 | static char * i3lock_replace_str(char *to, | ||
| 136 | const char *from, | ||
| 137 | const char *old_substr, | ||
| 138 | const char *new_substr, | ||
| 139 | size_t max_length) { | ||
| 140 | |||
| 141 | int offset; /* the offset in the tmp_str after each match */ | ||
| 142 | |||
| 143 | /* the offset in from needed to pick up the right side after a match */ | ||
| 144 | int from_offset; | ||
| 145 | |||
| 146 | int from_len = strlen(from); | ||
| 147 | int new_substr_len = strlen(new_substr); | ||
| 148 | int old_substr_len = strlen(old_substr); | ||
| 149 | int len_diff = old_substr_len - new_substr_len; | ||
| 150 | size_t free_space = max_length - 1; | ||
| 151 | char tmp_str[max_length]; | ||
| 152 | char *tmp_str_ptr; | ||
| 153 | |||
| 154 | /* reserve the last byte for '\0' in case of clipping */ | ||
| 155 | strncpy(tmp_str, from, free_space); | ||
| 156 | |||
| 157 | for (int i = 0; ; ++i) { | ||
| 158 | tmp_str_ptr = strstr(tmp_str, old_substr); | ||
| 159 | if (tmp_str_ptr == NULL) { | ||
| 160 | /* no more instances of old_substr */ | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | |||
| 164 | offset = tmp_str_ptr - tmp_str; | ||
| 165 | free_space -= offset; | ||
| 166 | if (free_space <= new_substr_len) { | ||
| 167 | strncpy(tmp_str_ptr, new_substr, free_space); | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | strncpy(tmp_str_ptr, new_substr, new_substr_len); | ||
| 171 | free_space -= new_substr_len; | ||
| 172 | /* tmp_str offset -> from_offset mapping */ | ||
| 173 | from_offset = offset + old_substr_len + i * len_diff; | ||
| 174 | if (free_space <= from_len - from_offset) { | ||
| 175 | strncpy(tmp_str_ptr + new_substr_len, from + from_offset, free_space); | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | strncpy(tmp_str_ptr + new_substr_len, from + from_offset, from_len - from_offset + 1); | ||
| 179 | |||
| 180 | } | ||
| 181 | |||
| 182 | strncpy(to, tmp_str, max_length - 1); | ||
| 183 | *(to + (max_length - 1)) = '\0'; | ||
| 184 | |||
| 185 | return to; | ||
| 186 | |||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 135 | void i3lock_draw_digital_clock(cairo_t *cr, | 190 | void i3lock_draw_digital_clock(cairo_t *cr, |
| 136 | const i3lock_digital_clock_t *dc, | 191 | const i3lock_digital_clock_t *dc, |
| 137 | const uint32_t *resolution, | 192 | const uint32_t *resolution, |
| @@ -440,9 +495,56 @@ void i3lock_draw_led_clock(cairo_t *cr, | |||
| 440 | brokentime->tm_sec & 1, | 495 | brokentime->tm_sec & 1, |
| 441 | lc); | 496 | lc); |
| 442 | } | 497 | } |
| 498 | |||
| 443 | return; | 499 | return; |
| 500 | |||
| 444 | } | 501 | } |
| 445 | 502 | ||
| 446 | } | 503 | } |
| 447 | 504 | ||
| 448 | 505 | ||
| 506 | char * i3lock_format_elapsed_time(char *to, | ||
| 507 | const char *template, | ||
| 508 | int max_size, | ||
| 509 | int seconds) { | ||
| 510 | |||
| 511 | char tmp_str[max_size]; | ||
| 512 | char int_str[32]; /* more than enough for int */ | ||
| 513 | int days = seconds / 86400; | ||
| 514 | int hours = (seconds - days * 86400) / 3600; | ||
| 515 | int minutes = (seconds - days * 86400 - hours * 3600) / 60; | ||
| 516 | int rest_seconds = seconds - days * 86400 - hours * 3600 - minutes * 60; | ||
| 517 | |||
| 518 | strncpy(tmp_str, template, max_size); | ||
| 519 | if (strlen(template) >= max_size) { | ||
| 520 | /* do a proper clipping */ | ||
| 521 | *(tmp_str + (max_size - 1)) = '\0'; | ||
| 522 | } | ||
| 523 | |||
| 524 | /* days */ | ||
| 525 | snprintf(int_str, 32, "%d", days); | ||
| 526 | i3lock_replace_str(to, tmp_str, "%d", int_str, max_size); | ||
| 527 | strcpy(tmp_str, to); | ||
| 528 | |||
| 529 | /* hours */ | ||
| 530 | snprintf(int_str, 32, "%d", hours); | ||
| 531 | i3lock_replace_str(to, tmp_str, "%h", int_str, max_size); | ||
| 532 | strcpy(tmp_str, to); | ||
| 533 | |||
| 534 | /* minutes */ | ||
| 535 | snprintf(int_str, 32, "%d", minutes); | ||
| 536 | i3lock_replace_str(to, tmp_str, "%m", int_str, max_size); | ||
| 537 | strcpy(tmp_str, to); | ||
| 538 | |||
| 539 | /* rest. seconds */ | ||
| 540 | snprintf(int_str, 32, "%d", rest_seconds); | ||
| 541 | i3lock_replace_str(to, tmp_str, "%s", int_str, max_size); | ||
| 542 | strcpy(tmp_str, to); | ||
| 543 | |||
| 544 | /* seconds */ | ||
| 545 | snprintf(int_str, 32, "%d", seconds); | ||
| 546 | i3lock_replace_str(to, tmp_str, "%S", int_str, max_size); | ||
| 547 | |||
| 548 | return to; | ||
| 549 | |||
| 550 | } | ||
| @@ -88,7 +88,6 @@ void i3lock_draw_elapsed_time(cairo_t *cr, | |||
| 88 | const uint32_t *resolution, | 88 | const uint32_t *resolution, |
| 89 | const time_t *now); | 89 | const time_t *now); |
| 90 | 90 | ||
| 91 | |||
| 92 | void i3lock_draw_led_clock(cairo_t *cr, | 91 | void i3lock_draw_led_clock(cairo_t *cr, |
| 93 | const i3lock_led_clock_t *lc, | 92 | const i3lock_led_clock_t *lc, |
| 94 | const uint32_t *resolution, | 93 | const uint32_t *resolution, |
| @@ -99,4 +98,9 @@ void i3lock_draw_string(cairo_t *cr, | |||
| 99 | const char *formatted_string, | 98 | const char *formatted_string, |
| 100 | const i3lock_elapsed_time_t *et, | 99 | const i3lock_elapsed_time_t *et, |
| 101 | const uint32_t *resolution); | 100 | const uint32_t *resolution); |
| 101 | |||
| 102 | char * i3lock_format_elapsed_time(char *to, | ||
| 103 | const char *template, | ||
| 104 | int max_size, | ||
| 105 | int seconds); | ||
| 102 | #endif | 106 | #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 @@ | |||
| 8 | .fi | 8 | .fi |
| 9 | .. | 9 | .. |
| 10 | 10 | ||
| 11 | .TH i3lock\-extended 1 "MARCH 2020" Linux "User Manuals" | 11 | .TH i3lock\-extended 1 "DECEMBER 2020" Linux "User Manuals" |
| 12 | 12 | ||
| 13 | .SH NAME | 13 | .SH NAME |
| 14 | i3lock\-extended \- improved screen locker | 14 | i3lock\-extended \- improved screen locker |
| @@ -18,6 +18,8 @@ i3lock\-extended \- improved screen locker | |||
| 18 | .RB [\|\-B | 18 | .RB [\|\-B |
| 19 | .IR color \|] | 19 | .IR color \|] |
| 20 | .RB [\|\-b\|] | 20 | .RB [\|\-b\|] |
| 21 | .RB [\|\-C | ||
| 22 | .IR seconds \|] | ||
| 21 | .RB [\|\-c | 23 | .RB [\|\-c |
| 22 | .IR color \|] | 24 | .IR color \|] |
| 23 | .RB [\|\-D\|] | 25 | .RB [\|\-D\|] |
| @@ -94,6 +96,8 @@ Digital clock | |||
| 94 | Elapsed time since activation | 96 | Elapsed time since activation |
| 95 | .IP \[bu] | 97 | .IP \[bu] |
| 96 | Display-text | 98 | Display-text |
| 99 | .IP \[bu] | ||
| 100 | Count to a specific calendar time (absolute time) | ||
| 97 | 101 | ||
| 98 | .SH OPTIONS | 102 | .SH OPTIONS |
| 99 | .TP | 103 | .TP |
| @@ -112,6 +116,14 @@ Turn the screen into the given color instead of white. | |||
| 112 | Color must be given in 3-byte. Default: ffffff (white). | 116 | Color must be given in 3-byte. Default: ffffff (white). |
| 113 | 117 | ||
| 114 | .TP | 118 | .TP |
| 119 | .BI \-C\ seconds \fR,\ \fB\-\-count\-until= seconds | ||
| 120 | Sets the seconds since the Epoch to count to. date +%s -d ... can be used to | ||
| 121 | get the Epoch time. Then the following macros will become available for the | ||
| 122 | display-text parameter: %d - days remaining until the time set, | ||
| 123 | %h - hours remaining, %m - minutes remaining, %s - seconds remaining, | ||
| 124 | %S - total amount of seconds remaining. Default: 0 (count until is off). | ||
| 125 | |||
| 126 | .TP | ||
| 115 | .B \-D, \-\-digital\-clock | 127 | .B \-D, \-\-digital\-clock |
| 116 | Display digital clock. | 128 | Display digital clock. |
| 117 | 129 | ||
| @@ -84,6 +84,7 @@ static void input_done(void); | |||
| 84 | bool digital_clock = false; | 84 | bool digital_clock = false; |
| 85 | bool led_clock = false; | 85 | bool led_clock = false; |
| 86 | bool elapsed_time = false; | 86 | bool elapsed_time = false; |
| 87 | int count_until = 0; /* count seconds until */ | ||
| 87 | int refresh_rate = 2; /* 2 frames per second */ | 88 | int refresh_rate = 2; /* 2 frames per second */ |
| 88 | i3lock_digital_clock_t i3lock_digital_clock = {28, | 89 | i3lock_digital_clock_t i3lock_digital_clock = {28, |
| 89 | "000000", | 90 | "000000", |
| @@ -1083,6 +1084,7 @@ int main(int argc, char *argv[]) { | |||
| 1083 | {"dpms", no_argument, NULL, 'd'}, | 1084 | {"dpms", no_argument, NULL, 'd'}, |
| 1084 | {"color", required_argument, NULL, 'c'}, | 1085 | {"color", required_argument, NULL, 'c'}, |
| 1085 | #ifdef EXTRAS | 1086 | #ifdef EXTRAS |
| 1087 | {"count-until", no_argument, NULL, 'C'}, | ||
| 1086 | {"digital-clock", no_argument, NULL, 'D'}, | 1088 | {"digital-clock", no_argument, NULL, 'D'}, |
| 1087 | {"digital-clock-color", required_argument, NULL, 'G'}, | 1089 | {"digital-clock-color", required_argument, NULL, 'G'}, |
| 1088 | {"digital-clock-template", required_argument, NULL, 'T'}, | 1090 | {"digital-clock-template", required_argument, NULL, 'T'}, |
| @@ -1122,7 +1124,7 @@ int main(int argc, char *argv[]) { | |||
| 1122 | errx(EXIT_FAILURE, "i3lock is a program for X11 and does not work on Wayland. Try https://github.com/swaywm/swaylock instead"); | 1124 | errx(EXIT_FAILURE, "i3lock is a program for X11 and does not work on Wayland. Try https://github.com/swaywm/swaylock instead"); |
| 1123 | 1125 | ||
| 1124 | #ifdef EXTRAS | 1126 | #ifdef EXTRAS |
| 1125 | char *optstring = "hvnbDdELc:B:G:F:J:O:R:r:S:T:W:X:x:Y:y:Z:p:ui:teI:f"; | 1127 | char *optstring = "hvnbDdELC:c:B:G:F:J:O:R:r:S:T:W:X:x:Y:y:Z:p:ui:teI:f"; |
| 1126 | #else | 1128 | #else |
| 1127 | char *optstring = "hvnbdc:p:ui:teI:f"; | 1129 | char *optstring = "hvnbdc:p:ui:teI:f"; |
| 1128 | #endif | 1130 | #endif |
| @@ -1156,6 +1158,12 @@ int main(int argc, char *argv[]) { | |||
| 1156 | break; | 1158 | break; |
| 1157 | } | 1159 | } |
| 1158 | #ifdef EXTRAS | 1160 | #ifdef EXTRAS |
| 1161 | case 'C': /* count until */ | ||
| 1162 | if (optarg != NULL && atoi(optarg) > 0) /* not nice with -1 and 0 */ | ||
| 1163 | count_until = atoi(optarg); | ||
| 1164 | DEBUG("count_until: %d\n", | ||
| 1165 | count_until); | ||
| 1166 | break; | ||
| 1159 | case 'D': | 1167 | case 'D': |
| 1160 | digital_clock = true; | 1168 | digital_clock = true; |
| 1161 | break; | 1169 | 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; | |||
| 58 | 58 | ||
| 59 | #ifdef EXTRAS | 59 | #ifdef EXTRAS |
| 60 | /* timekeeping */ | 60 | /* timekeeping */ |
| 61 | #define I3LOCK_COUNT_UNTIL_BUFFER 128 | ||
| 62 | char count_until_str[I3LOCK_COUNT_UNTIL_BUFFER]; | ||
| 61 | time_t now; | 63 | time_t now; |
| 62 | struct tm *brokentime; | 64 | struct tm *brokentime; |
| 63 | /* enable the digital clock */ | 65 | /* enable the digital clock */ |
| 64 | extern bool digital_clock; | 66 | extern bool digital_clock; |
| 65 | extern bool led_clock; | 67 | extern bool led_clock; |
| 66 | extern bool elapsed_time; | 68 | extern bool elapsed_time; |
| 69 | extern int count_until; | ||
| 67 | extern i3lock_digital_clock_t i3lock_digital_clock; | 70 | extern i3lock_digital_clock_t i3lock_digital_clock; |
| 68 | extern i3lock_elapsed_time_t i3lock_elapsed_time; | 71 | extern i3lock_elapsed_time_t i3lock_elapsed_time; |
| 69 | extern i3lock_led_clock_t i3lock_led_clock; | 72 | extern i3lock_led_clock_t i3lock_led_clock; |
| @@ -359,17 +362,30 @@ void draw_image(xcb_pixmap_t bg_pixmap, uint32_t *resolution) { | |||
| 359 | resolution, | 362 | resolution, |
| 360 | brokentime); | 363 | brokentime); |
| 361 | } | 364 | } |
| 362 | /* elapsed time or display text */ | 365 | /* elapsed time or counter with display text or only display text */ |
| 363 | if (elapsed_time) { | 366 | if (elapsed_time) { |
| 364 | i3lock_draw_elapsed_time(xcb_ctx, | 367 | i3lock_draw_elapsed_time(xcb_ctx, |
| 365 | &i3lock_elapsed_time, | 368 | &i3lock_elapsed_time, |
| 366 | resolution, | 369 | resolution, |
| 367 | &now); | 370 | &now); |
| 368 | } else if (display_text != NULL) { | 371 | } else if (display_text != NULL) { |
| 369 | i3lock_draw_string(xcb_ctx, | 372 | if (count_until) { |
| 370 | display_text, | 373 | if (i3lock_format_elapsed_time( |
| 371 | &i3lock_elapsed_time, | 374 | count_until_str, |
| 372 | resolution); | 375 | display_text, |
| 376 | I3LOCK_COUNT_UNTIL_BUFFER, | ||
| 377 | count_until - (int) now) != NULL) { | ||
| 378 | i3lock_draw_string(xcb_ctx, | ||
| 379 | count_until_str, | ||
| 380 | &i3lock_elapsed_time, | ||
| 381 | resolution); | ||
| 382 | } | ||
| 383 | } else { | ||
| 384 | i3lock_draw_string(xcb_ctx, | ||
| 385 | display_text, | ||
| 386 | &i3lock_elapsed_time, | ||
| 387 | resolution); | ||
| 388 | } | ||
| 373 | } | 389 | } |
| 374 | #endif | 390 | #endif |
| 375 | if (xr_screens > 0) { | 391 | if (xr_screens > 0) { |
