]> git.ipfire.org Git - pakfire.git/commitdiff
progressbar: Respond to resize events
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 23 Apr 2021 08:14:20 +0000 (08:14 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 23 Apr 2021 08:14:20 +0000 (08:14 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/progressbar.c

index 9c1bbddc983e0e9ce5e5d348377da80323dba102..fe27629c22aacf3c3618905e60ee06ac5ccd71c7 100644 (file)
@@ -19,6 +19,7 @@
 #############################################################################*/
 
 #include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -48,6 +49,7 @@ struct pakfire_progressbar_widget {
 
 struct pakfire_progressbar {
        int nrefs;
+       FILE* f;
 
        enum pakfire_progressbar_status {
                PAKFIRE_PROGRESSBAR_INIT = 0,
@@ -61,13 +63,6 @@ struct pakfire_progressbar {
        unsigned long value_redraw;
        unsigned long update_interval;
 
-       // Store terminal settings globally
-       struct pakfire_terminal {
-               FILE* f;
-               int rows;
-               int cols;
-       } terminal;
-
        struct timespec time_start;
        struct timespec time_redraw;
 
@@ -76,28 +71,32 @@ struct pakfire_progressbar {
        unsigned int num_widgets;
 };
 
-static int pakfire_progressbar_update_terminal_size(struct pakfire_progressbar* p) {
-       int fd = fileno(p->terminal.f);
+// Store terminal settings globally
+static struct pakfire_terminal {
+       int rows;
+       int cols;
+} terminal;
+
+static void pakfire_progressbar_update_terminal_size(int signum) {
+       const int fd = STDOUT_FILENO;
 
-       // Set a default of 80x20
-       p->terminal.cols = 80;
-       p->terminal.rows = 20;
+       // Set defaults
+       terminal.rows = 80;
+       terminal.cols = 20;
 
        // Check if output file is a TTY
        int r = isatty(fd);
        if (r != 1)
-               return 0;
+               return;
 
        struct winsize w;
        r = ioctl(fd, TIOCGWINSZ, &w);
        if (r)
-               return r;
+               return;
 
        // Save result
-       p->terminal.rows = w.ws_row;
-       p->terminal.cols = w.ws_col;
-
-       return 0;
+       terminal.rows = w.ws_row;
+       terminal.cols = w.ws_col;
 }
 
 static void pakfire_progressbar_widget_free(struct pakfire_progressbar_widget* widget) {
@@ -139,12 +138,10 @@ PAKFIRE_EXPORT int pakfire_progressbar_create(
                f = stdout;
 
        // Store output
-       p->terminal.f = f;
+       p->f = stdout;
 
-       // Determine terminal size
-       int r = pakfire_progressbar_update_terminal_size(p);
-       if (r)
-               goto ERROR;
+       // Register signal handler to update terminal size
+       signal(SIGWINCH, pakfire_progressbar_update_terminal_size);
 
        // Setup widgets
        STAILQ_INIT(&p->widgets);
@@ -152,11 +149,6 @@ PAKFIRE_EXPORT int pakfire_progressbar_create(
        // Done
        *progressbar = p;
        return 0;
-
-ERROR:
-       pakfire_progressbar_free(p);
-
-       return r;
 }
 
 PAKFIRE_EXPORT struct pakfire_progressbar* pakfire_progressbar_ref(struct pakfire_progressbar* p) {
@@ -229,7 +221,7 @@ PAKFIRE_EXPORT int pakfire_progressbar_finish(struct pakfire_progressbar* p) {
                return r;
 
        // Finish line
-       r = fputs("\n", p->terminal.f);
+       r = fputs("\n", p->f);
        if (r <= 0 || r == EOF)
                return 1;
 
@@ -265,8 +257,12 @@ PAKFIRE_EXPORT void pakfire_progressbar_set_max(
        // Redraw immediately
        p->value_redraw = 0;
 
+       // Update terminal size if not set
+       if (!terminal.cols)
+               pakfire_progressbar_update_terminal_size(SIGWINCH);
+
        // Calculate update interval
-       p->update_interval = p->value_max / p->terminal.cols;
+       p->update_interval = p->value_max / terminal.cols;
 }
 
 static int pakfire_progressbar_add_widget(struct pakfire_progressbar* p,
@@ -335,7 +331,11 @@ static int pakfire_progressbar_redraw(struct pakfire_progressbar* p) {
        if (!pakfire_progressbar_needs_redraw(p))
                return 0;
 
-       unsigned int cols_left = p->terminal.cols - p->num_widgets - 2;
+       // Update terminal size if not set
+       if (!terminal.cols)
+               pakfire_progressbar_update_terminal_size(SIGWINCH);
+
+       unsigned int cols_left = terminal.cols - p->num_widgets - 2;
        int i = 0;
 
        // Create an array with the result of all print functions
@@ -382,7 +382,7 @@ static int pakfire_progressbar_redraw(struct pakfire_progressbar* p) {
        }
 
        // Reset the line
-       fputs("\r", p->terminal.f);
+       fputs("\r", p->f);
 
        // Print all elements
        for (unsigned int i = 0; i < p->num_widgets; i++) {
@@ -390,8 +390,8 @@ static int pakfire_progressbar_redraw(struct pakfire_progressbar* p) {
                if (!elements[i])
                        continue;
 
-               fputs(" ", p->terminal.f);
-               fputs(elements[i], p->terminal.f);
+               fputs(" ", p->f);
+               fputs(elements[i], p->f);
        }
 
        return 0;