X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fprogress.c;h=0c809eb1ee2c182fdedbed9eb5cbe352132bf65d;hp=2e888a90b42a722fbf479bb7a6084f61afce79b4;hb=4eeabffee6e5b348d36c4f3ba0579ed086226603;hpb=96418c68851d00fd66014d2dc7bd46b3d715e525 diff --git a/src/progress.c b/src/progress.c index 2e888a90..0c809eb1 100644 --- a/src/progress.c +++ b/src/progress.c @@ -47,27 +47,30 @@ as that of the covered work. */ struct progress_implementation { const char *name; bool interactive; - void *(*create) (wgint, wgint); + void *(*create) (const char *, wgint, wgint); void (*update) (void *, wgint, double); + void (*draw) (void *); void (*finish) (void *, double); - void (*set_params) (const char *); + void (*set_params) (char *); }; /* Necessary forward declarations. */ -static void *dot_create (wgint, wgint); +static void *dot_create (const char *, wgint, wgint); static void dot_update (void *, wgint, double); static void dot_finish (void *, double); -static void dot_set_params (const char *); +static void dot_draw (void *); +static void dot_set_params (char *); -static void *bar_create (wgint, wgint); +static void *bar_create (const char *, wgint, wgint); static void bar_update (void *, wgint, double); +static void bar_draw (void *); static void bar_finish (void *, double); -static void bar_set_params (const char *); +static void bar_set_params (char *); static struct progress_implementation implementations[] = { - { "dot", 0, dot_create, dot_update, dot_finish, dot_set_params }, - { "bar", 1, bar_create, bar_update, bar_finish, bar_set_params } + { "dot", 0, dot_create, dot_update, dot_draw, dot_finish, dot_set_params }, + { "bar", 1, bar_create, bar_update, bar_draw, bar_finish, bar_set_params } }; static struct progress_implementation *current_impl; static int current_impl_locked; @@ -109,7 +112,7 @@ set_progress_implementation (const char *name) { size_t i, namelen; struct progress_implementation *pi = implementations; - const char *colon; + char *colon; if (!name) name = DEFAULT_PROGRESS_IMPLEMENTATION; @@ -151,7 +154,7 @@ progress_schedule_redirect (void) advance. */ void * -progress_create (wgint initial, wgint total) +progress_create (const char *f_download, wgint initial, wgint total) { /* Check if the log status has changed under our feet. */ if (output_redirected) @@ -161,7 +164,7 @@ progress_create (wgint initial, wgint total) output_redirected = 0; } - return current_impl->create (initial, total); + return current_impl->create (f_download, initial, total); } /* Return true if the progress gauge is "interactive", i.e. if it can @@ -170,7 +173,7 @@ progress_create (wgint initial, wgint total) and current update. */ bool -progress_interactive_p (void *progress) +progress_interactive_p (void *progress _GL_UNUSED) { return current_impl->interactive; } @@ -182,6 +185,7 @@ void progress_update (void *progress, wgint howmuch, double dltime) { current_impl->update (progress, howmuch, dltime); + current_impl->draw (progress); } /* Tell the progress gauge to clean up. Calling this will free the @@ -204,6 +208,7 @@ struct dot_progress { int accumulated; /* number of bytes accumulated after the last printed dot */ + double dltime; /* download time so far */ int rows; /* number of rows printed so far */ int dots; /* number of dots printed in this row */ @@ -213,7 +218,7 @@ struct dot_progress { /* Dot-progress backend for progress_create. */ static void * -dot_create (wgint initial, wgint total) +dot_create (const char *f_download _GL_UNUSED, wgint initial, wgint total) { struct dot_progress *dp = xnew0 (struct dot_progress); dp->initial_length = initial; @@ -237,18 +242,18 @@ dot_create (wgint initial, wgint total) /* Align the [ skipping ... ] line with the dots. To do that, insert the number of spaces equal to the number of digits in the skipped amount in K. */ - logprintf (LOG_VERBOSE, _("\n%*s[ skipping %sK ]"), + logprintf (LOG_PROGRESS, _("\n%*s[ skipping %sK ]"), 2 + skipped_k_len, "", number_to_static_string (skipped_k)); } - logprintf (LOG_VERBOSE, "\n%6sK", + logprintf (LOG_PROGRESS, "\n%6sK", number_to_static_string (skipped / 1024)); for (; remainder >= dot_bytes; remainder -= dot_bytes) { if (dp->dots % opt.dot_spacing == 0) - logputs (LOG_VERBOSE, " "); - logputs (LOG_VERBOSE, ","); + logputs (LOG_PROGRESS, " "); + logputs (LOG_PROGRESS, ","); ++dp->dots; } assert (dp->dots < opt.dots_in_line); @@ -289,7 +294,7 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) been retrieved. 12.8% will round to 12% because the 13% mark has not yet been reached. 100% is only shown when done. */ int percentage = 100.0 * bytes_displayed / dp->total_length; - logprintf (LOG_VERBOSE, "%3d%%", percentage); + logprintf (LOG_PROGRESS, "%3d%%", percentage); } { @@ -306,7 +311,7 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) if (dp->rows == dp->initial_length / ROW_BYTES) bytes_this_row -= dp->initial_length % ROW_BYTES; rate = calc_rate (bytes_this_row, dltime - dp->last_timer_value, &units); - logprintf (LOG_VERBOSE, " %4.*f%c", + logprintf (LOG_PROGRESS, " %4.*f%c", rate >= 99.95 ? 0 : rate >= 9.995 ? 1 : 2, rate, names[units]); dp->last_timer_value = dltime; @@ -323,7 +328,7 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) wgint bytes_sofar = bytes_displayed - dp->initial_length; double eta = dltime * bytes_remaining / bytes_sofar; if (eta < INT_MAX - 1) - logprintf (LOG_VERBOSE, " %s", + logprintf (LOG_PROGRESS, " %s", eta_to_human_short ((int) (eta + 0.5), true)); } } @@ -331,10 +336,10 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) { /* When done, print the total download time */ if (dltime >= 10) - logprintf (LOG_VERBOSE, "=%s", + logprintf (LOG_PROGRESS, "=%s", eta_to_human_short ((int) (dltime + 0.5), true)); else - logprintf (LOG_VERBOSE, "=%ss", print_decimal (dltime)); + logprintf (LOG_PROGRESS, "=%ss", print_decimal (dltime)); } } @@ -342,6 +347,14 @@ print_row_stats (struct dot_progress *dp, double dltime, bool last) static void dot_update (void *progress, wgint howmuch, double dltime) +{ + struct dot_progress *dp = progress; + dp->accumulated += howmuch; + dp->dltime = dltime; +} + +static void +dot_draw (void *progress) { struct dot_progress *dp = progress; int dot_bytes = opt.dot_bytes; @@ -349,16 +362,15 @@ dot_update (void *progress, wgint howmuch, double dltime) log_set_flush (false); - dp->accumulated += howmuch; for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes) { if (dp->dots == 0) - logprintf (LOG_VERBOSE, "\n%6sK", + logprintf (LOG_PROGRESS, "\n%6sK", number_to_static_string (dp->rows * ROW_BYTES / 1024)); if (dp->dots % opt.dot_spacing == 0) - logputs (LOG_VERBOSE, " "); - logputs (LOG_VERBOSE, "."); + logputs (LOG_PROGRESS, " "); + logputs (LOG_PROGRESS, "."); ++dp->dots; if (dp->dots >= opt.dots_in_line) @@ -366,7 +378,7 @@ dot_update (void *progress, wgint howmuch, double dltime) ++dp->rows; dp->dots = 0; - print_row_stats (dp, dltime, false); + print_row_stats (dp, dp->dltime, false); } } @@ -385,13 +397,13 @@ dot_finish (void *progress, double dltime) log_set_flush (false); if (dp->dots == 0) - logprintf (LOG_VERBOSE, "\n%6sK", + logprintf (LOG_PROGRESS, "\n%6sK", number_to_static_string (dp->rows * ROW_BYTES / 1024)); for (i = dp->dots; i < opt.dots_in_line; i++) { if (i % opt.dot_spacing == 0) - logputs (LOG_VERBOSE, " "); - logputs (LOG_VERBOSE, " "); + logputs (LOG_PROGRESS, " "); + logputs (LOG_PROGRESS, " "); } print_row_stats (dp, dltime, true); @@ -407,7 +419,7 @@ dot_finish (void *progress, double dltime) giga. */ static void -dot_set_params (const char *params) +dot_set_params (char *params) { if (!params || !*params) params = opt.dot_style; @@ -495,6 +507,7 @@ static volatile sig_atomic_t received_sigwinch; #define ETA_REFRESH_INTERVAL 0.99 struct bar_progress { + const char *f_download; /* Filename of the downloaded file */ wgint initial_length; /* how many bytes have been downloaded previously. */ wgint total_length; /* expected total byte count when the @@ -505,6 +518,7 @@ struct bar_progress { measured since the beginning of download. */ + double dltime; /* download time so far */ int width; /* screen width we're using at the time the progress gauge was created. this is different from @@ -551,7 +565,7 @@ static void create_image (struct bar_progress *, double, bool); static void display_image (char *); static void * -bar_create (wgint initial, wgint total) +bar_create (const char *f_download, wgint initial, wgint total) { struct bar_progress *bp = xnew0 (struct bar_progress); @@ -562,6 +576,7 @@ bar_create (wgint initial, wgint total) bp->initial_length = initial; bp->total_length = total; + bp->f_download = f_download; /* Initialize screen_width if this hasn't been done or if it might have changed, as indicated by receiving SIGWINCH. */ @@ -595,8 +610,8 @@ static void bar_update (void *progress, wgint howmuch, double dltime) { struct bar_progress *bp = progress; - bool force_screen_update = false; + bp->dltime = dltime; bp->count += howmuch; if (bp->total_length > 0 && bp->count + bp->initial_length > bp->total_length) @@ -608,6 +623,13 @@ bar_update (void *progress, wgint howmuch, double dltime) bp->total_length = bp->initial_length + bp->count; update_speed_ring (bp, howmuch, dltime); +} + +static void +bar_draw (void *progress) +{ + bool force_screen_update = false; + struct bar_progress *bp = progress; /* If SIGWINCH (the window size change signal) been received, determine the new screen size and update the screen. */ @@ -628,13 +650,13 @@ bar_update (void *progress, wgint howmuch, double dltime) received_sigwinch = 0; } - if (dltime - bp->last_screen_update < REFRESH_INTERVAL && !force_screen_update) + if (bp->dltime - bp->last_screen_update < REFRESH_INTERVAL && !force_screen_update) /* Don't update more often than five times per second. */ return; - create_image (bp, dltime, false); + create_image (bp, bp->dltime, false); display_image (bp->buffer); - bp->last_screen_update = dltime; + bp->last_screen_update = bp->dltime; } static void @@ -650,7 +672,8 @@ bar_finish (void *progress, double dltime) create_image (bp, dltime, true); display_image (bp->buffer); - logputs (LOG_VERBOSE, "\n\n"); + logputs (LOG_VERBOSE, "\n"); + logputs (LOG_PROGRESS, "\n"); xfree (bp->buffer); xfree (bp); @@ -800,7 +823,7 @@ get_eta (int *bcd) { /* TRANSLATORS: "ETA" is English-centric, but this must be short, ideally 3 chars. Abbreviate if necessary. */ - static const char eta_str[] = N_(" eta %s"); + static const char eta_str[] = N_(" eta %s"); static const char *eta_trans; static int bytes_cols_diff; if (eta_trans == NULL) @@ -845,10 +868,14 @@ get_eta (int *bcd) #ifndef MAX # define MAX(a, b) ((a) >= (b) ? (a) : (b)) #endif +#ifndef MIN +# define MIN(a, b) ((a) <= (b) ? (a) : (b)) +#endif static void create_image (struct bar_progress *bp, double dl_total_time, bool done) { + const int MAX_FILENAME_LEN = bp->width / 4; char *p = bp->buffer; wgint size = bp->initial_length + bp->count; @@ -859,9 +886,10 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) int size_grouped_pad; /* Used to pad the field width for size_grouped. */ struct bar_progress_hist *hist = &bp->hist; + int orig_filename_len = strlen (bp->f_download); /* The progress bar should look like this: - xx% [=======> ] nn,nnn 12.34KB/s eta 36m 51s + file xx% [=======> ] nnn.nnK 12.34KB/s eta 36m 51s Calculate the geometry. The idea is to assign as much room as possible to the progress bar. The other idea is to never let @@ -870,16 +898,26 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) It would be especially bad for the progress bar to be resized randomly. + "file " - Downloaded filename - MAX_FILENAME_LEN chars + 1 "xx% " or "100%" - percentage - 4 chars "[]" - progress bar decorations - 2 chars - " nnn,nnn,nnn" - downloaded bytes - 12 chars or very rarely more - " 12.5KB/s" - download rate - 9 chars + " nnn.nnK" - downloaded bytes - 7 chars + 1 + " 12.5KB/s" - download rate - 8 chars + 1 " eta 36m 51s" - ETA - 14 chars "=====>..." - progress bar - the rest */ - int dlbytes_size = 1 + MAX (size_grouped_len, 11); - int progress_size = bp->width - (4 + 2 + dlbytes_size + 8 + 14); + +#define PROGRESS_FILENAME_LEN MAX_FILENAME_LEN + 1 +#define PROGRESS_PERCENT_LEN 4 +#define PROGRESS_DECORAT_LEN 2 +#define PROGRESS_FILESIZE_LEN 7 + 1 +#define PROGRESS_DWNLOAD_RATE 8 + 1 +#define PROGRESS_ETA_LEN 14 + + int progress_size = bp->width - (PROGRESS_FILENAME_LEN + PROGRESS_PERCENT_LEN + + PROGRESS_DECORAT_LEN + PROGRESS_FILESIZE_LEN + + PROGRESS_DWNLOAD_RATE + PROGRESS_ETA_LEN); /* The difference between the number of bytes used, and the number of columns used. */ @@ -888,6 +926,27 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) if (progress_size < 5) progress_size = 0; + if (orig_filename_len <= MAX_FILENAME_LEN) + { + int padding = MAX_FILENAME_LEN - orig_filename_len; + sprintf (p, "%s ", bp->f_download); + p += orig_filename_len + 1; + for (;padding;padding--) + *p++ = ' '; + } + else + { + int offset; + + if (((orig_filename_len > MAX_FILENAME_LEN) && !opt.noscroll) && !done) + offset = ((int) bp->tick) % (orig_filename_len - MAX_FILENAME_LEN); + else + offset = 0; + memcpy (p, bp->f_download + offset, MAX_FILENAME_LEN); + p += MAX_FILENAME_LEN; + *p++ = ' '; + } + /* "xx% " */ if (bp->total_length > 0) { @@ -961,16 +1020,23 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) } *p++ = ']'; - ++bp->tick; } + ++bp->tick; - /* " 234,567,890" */ - sprintf (p, " %s", size_grouped); + /* " 234.56M" */ + const char * down_size = human_readable (size, 1000, 2); + int cols_diff = 7 - count_cols (down_size); + while (cols_diff > 0) + { + *p++=' '; + cols_diff--; + } + sprintf (p, " %s", down_size); move_to_end (p); - /* Pad with spaces to 11 chars for the size_grouped field; + /* Pad with spaces to 7 chars for the size_grouped field; * couldn't use the field width specifier in sprintf, because * it counts in bytes, not characters. */ - for (size_grouped_pad = 11 - size_grouped_len; + for (size_grouped_pad = PROGRESS_FILESIZE_LEN - 7; size_grouped_pad > 0; --size_grouped_pad) { @@ -980,8 +1046,8 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) /* " 12.52Kb/s or 12.52KB/s" */ if (hist->total_time > 0 && hist->total_bytes) { - static const char *short_units[] = { "B/s", "KB/s", "MB/s", "GB/s" }; - static const char *short_units_bits[] = { "b/s", "Kb/s", "Mb/s", "Gb/s" }; + static const char *short_units[] = { " B/s", "KB/s", "MB/s", "GB/s" }; + static const char *short_units_bits[] = { " b/s", "Kb/s", "Mb/s", "Gb/s" }; int units = 0; /* Calculate the download speed using the history ring and recent data that hasn't made it to the ring yet. */ @@ -993,7 +1059,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) move_to_end (p); } else - APPEND_LITERAL (" --.-K/s"); + APPEND_LITERAL (" --.-KB/s"); if (!done) { @@ -1070,19 +1136,27 @@ static void display_image (char *buf) { bool old = log_set_save_context (false); - logputs (LOG_VERBOSE, "\r"); - logputs (LOG_VERBOSE, buf); + logputs (LOG_PROGRESS, "\r"); + logputs (LOG_PROGRESS, buf); log_set_save_context (old); } static void -bar_set_params (const char *params) +bar_set_params (char *params) { char *term = getenv ("TERM"); - if (params - && 0 == strcmp (params, "force")) - current_impl_locked = 1; + if (params) + { + char *param = strtok (params, ":"); + do + { + if (0 == strcmp (param, "force")) + current_impl_locked = 1; + else if (0 == strcmp (param, "noscroll")) + opt.noscroll = true; + } while ((param = strtok (NULL, ":")) != NULL); + } if ((opt.lfilename #ifdef HAVE_ISATTY @@ -1112,7 +1186,7 @@ bar_set_params (const char *params) #ifdef SIGWINCH void -progress_handle_sigwinch (int sig) +progress_handle_sigwinch (int sig _GL_UNUSED) { received_sigwinch = 1; signal (SIGWINCH, progress_handle_sigwinch);