#############################################################################*/
#include <errno.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct pakfire_progressbar {
int nrefs;
+ FILE* f;
enum pakfire_progressbar_status {
PAKFIRE_PROGRESSBAR_INIT = 0,
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;
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) {
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);
// Done
*progressbar = p;
return 0;
-
-ERROR:
- pakfire_progressbar_free(p);
-
- return r;
}
PAKFIRE_EXPORT struct pakfire_progressbar* pakfire_progressbar_ref(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;
// 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,
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
}
// 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++) {
if (!elements[i])
continue;
- fputs(" ", p->terminal.f);
- fputs(elements[i], p->terminal.f);
+ fputs(" ", p->f);
+ fputs(elements[i], p->f);
}
return 0;