From 05463c7121b7a438a21fdcf41cfe3c5339c476b5 Mon Sep 17 00:00:00 2001 From: hniksic Date: Sat, 24 Nov 2001 20:46:26 -0800 Subject: [PATCH] [svn] Commit progress bar tweaks. Published in . --- src/ChangeLog | 12 +++++ src/ftp.c | 4 +- src/http.c | 2 +- src/progress.c | 129 ++++++++++++++++++++++++++++++++----------------- src/retr.c | 42 ++++++++++------ src/retr.h | 3 +- 6 files changed, 131 insertions(+), 61 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 68e13dfe..032eace7 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2001-11-25 Hrvoje Niksic + + * progress.c (dot_create): Align the "[ skipping ... ]" string + with the dots. + + * retr.c (rate): Split into two functions: calc_rate and + retr_rate. + + * progress.c (create_image): Draw a dummy progress bar even when + total size is unknown. + (display_image): Place the text cursor at the end of the "image". + 2001-11-25 Hrvoje Niksic * url.c (reencode_string): Use unsigned char, not char -- diff --git a/src/ftp.c b/src/ftp.c index 5f18c709..abad6a15 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -924,7 +924,7 @@ Error in server response, closing control connection.\n")); con->dltime = wtimer_elapsed (timer); wtimer_delete (timer); tms = time_str (NULL); - tmrate = rate (*len - restval, con->dltime, 0); + tmrate = retr_rate (*len - restval, con->dltime, 0); /* Close data connection socket. */ closeport (dtsock); /* Close the local file. */ @@ -1173,7 +1173,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) } /* Time? */ tms = time_str (NULL); - tmrate = rate (len - restval, con->dltime, 0); + tmrate = retr_rate (len - restval, con->dltime, 0); /* If we get out of the switch above without continue'ing, we've successfully downloaded a file. Remember this fact. */ diff --git a/src/http.c b/src/http.c index 8d79de51..80f5b631 100644 --- a/src/http.c +++ b/src/http.c @@ -1752,7 +1752,7 @@ The sizes do not match (local %ld) -- retrieving.\n"), local_size); return RETROK; } - tmrate = rate (hstat.len - hstat.restval, hstat.dltime, 0); + tmrate = retr_rate (hstat.len - hstat.restval, hstat.dltime, 0); if (hstat.len == hstat.contlen) { diff --git a/src/progress.c b/src/progress.c index e167b7bf..bf68f560 100644 --- a/src/progress.c +++ b/src/progress.c @@ -190,9 +190,16 @@ dot_create (long initial, long total) if (skipped) { - logputs (LOG_VERBOSE, "\n "); /* leave spacing untranslated */ - logprintf (LOG_VERBOSE, _("[ skipping %dK ]"), - (int) (skipped / 1024)); + int skipped_k = (int) (skipped / 1024); /* skipped amount in K */ + int skipped_k_len = numdigit (skipped_k); + if (skipped_k_len < 5) + skipped_k_len = 5; + + /* 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%s", + 2 + skipped_k_len, "", _("[ skipping %dK ]")); } logprintf (LOG_VERBOSE, "\n%5ldK", skipped / 1024); @@ -224,7 +231,7 @@ print_download_speed (struct dot_progress *dp, long bytes) { long timer_value = wtimer_elapsed (dp->timer); logprintf (LOG_VERBOSE, " %s", - rate (bytes, timer_value - dp->last_timer_value, 1)); + retr_rate (bytes, timer_value - dp->last_timer_value, 1)); dp->last_timer_value = timer_value; } @@ -380,6 +387,8 @@ struct bar_progress { progress gauge was created. */ char *buffer; /* buffer where the bar "image" is stored. */ + + int tick; }; static void create_image PARAMS ((struct bar_progress *, long)); @@ -468,44 +477,53 @@ create_image (struct bar_progress *bp, long dltime) long size = bp->initial_length + bp->count; /* The progress bar should look like this: - xxx% |=======> | xx KB/s nnnnn ETA: 00:00 + xx% [=======> ] xx KB/s nnnnn ETA 00:00 Calculate its geometry: - "xxx% " - percentage - 5 chars - "| ... |" - progress bar decorations - 2 chars - "1012.56 K/s " - dl rate - 12 chars - "nnnn " - downloaded bytes - 11 chars - "ETA: xx:xx:xx" - ETA - 13 chars + "xx% " or "100%" - percentage - 4 chars exactly + "[]" - progress bar decorations - 2 chars exactly + "1012.56K/s " - dl rate - 11 chars exactly + "n,nnn,nnn,nnn " - downloaded bytes - 14 or less chars + "ETA xx:xx:xx" - ETA - 12 or less chars - "=====>..." - progress bar content - the rest + "=====>..." - progress bar content - the rest */ - int progress_len = screen_width - (5 + 2 + 12 + 11 + 13); + int progress_size = screen_width - (4 + 2 + 11 + 14 + 12); - if (progress_len < 7) - progress_len = 0; + if (progress_size < 5) + progress_size = 0; - /* "xxx% " */ + /* "xxx%" */ if (bp->total_length > 0) { int percentage = (int)(100.0 * size / bp->total_length); assert (percentage <= 100); - sprintf (p, "%3d%% ", percentage); - p += 5; + if (percentage < 100) + sprintf (p, "%2d%% ", percentage); + else + strcpy (p, "100%"); + p += 4; + } + else + { + int i = 5; + while (i--) + *p++ = ' '; } - /* The progress bar: "|====> | " */ - if (progress_len && bp->total_length > 0) + /* The progress bar: "|====> |" */ + if (progress_size && bp->total_length > 0) { double fraction = (double)size / bp->total_length; - int dlsz = (int)(fraction * progress_len); + int dlsz = (int)(fraction * progress_size); char *begin; - assert (dlsz <= progress_len); + assert (dlsz <= progress_size); - *p++ = '|'; + *p++ = '['; begin = p; if (dlsz > 0) @@ -516,20 +534,46 @@ create_image (struct bar_progress *bp, long dltime) *p++ = '>'; } - while (p - begin < progress_len) + while (p - begin < progress_size) *p++ = ' '; - *p++ = '|'; - *p++ = ' '; + *p++ = ']'; + } + else if (progress_size) + { + /* If we can't draw a real progress bar, then at least show + *something* to the user. */ + int ind = bp->tick % (progress_size * 2 - 6); + int i, pos; + + /* Make the star move in two directions. */ + if (ind < progress_size - 2) + pos = ind + 1; + else + pos = progress_size - (ind - progress_size + 5); + + *p++ = '['; + for (i = 0; i < progress_size; i++) + { + if (i == pos - 1) *p++ = '<'; + else if (i == pos ) *p++ = '='; + else if (i == pos + 1) *p++ = '>'; + else + *p++ = ' '; + } + *p++ = ']'; + + ++bp->tick; } - /* "1012.45 K/s " */ + /* "1012.45K/s " */ if (dltime && bp->count) { - char *rt = rate (bp->count, dltime, 1); - strcpy (p, rt); + static char *short_units[] = { "B/s", "K/s", "M/s", "G/s" }; + int units = 0; + double dlrate = calc_rate (bp->count, dltime, &units); + sprintf (p, "%7.2f%s ", dlrate, short_units[units]); p += strlen (p); - *p++ = ' '; } else { @@ -537,11 +581,15 @@ create_image (struct bar_progress *bp, long dltime) p += 12; } - /* "12376 " */ - sprintf (p, "%ld ", size); + /* "1,234,567 " */ + /* If there are 7 or less digits (9 because of "legible" comas), + print the number in constant space. This will prevent the "ETA" + string from jerking as the data begins to arrive. */ + sprintf (p, "%9s", legible (size)); p += strlen (p); + *p++ = ' '; - /* "ETA: xx:xx:xx" */ + /* "ETA xx:xx:xx" */ if (bp->total_length > 0 && bp->count > 0) { int eta, eta_hrs, eta_min, eta_sec; @@ -560,7 +608,6 @@ create_image (struct bar_progress *bp, long dltime) *p++ = 'E'; *p++ = 'T'; *p++ = 'A'; - *p++ = ':'; *p++ = ' '; if (eta_hrs > 99) @@ -574,8 +621,8 @@ create_image (struct bar_progress *bp, long dltime) } else if (bp->total_length > 0) { - strcpy (p, "ETA: --:--"); - p += 10; + strcpy (p, "ETA --:--"); + p += 9; } assert (p - bp->buffer <= screen_width); @@ -591,15 +638,11 @@ create_image (struct bar_progress *bp, long dltime) static void display_image (char *buf) { - int len = strlen (buf); - char *del_buf = alloca (len + 1); - - logputs (LOG_VERBOSE, buf); - - memset (del_buf, '\b', len); - del_buf[len] = '\0'; - + char *del_buf = alloca (screen_width + 1); + memset (del_buf, '\b', screen_width); + del_buf[screen_width] = '\0'; logputs (LOG_VERBOSE, del_buf); + logputs (LOG_VERBOSE, buf); } static void diff --git a/src/retr.c b/src/retr.c index dcd81226..d613da7c 100644 --- a/src/retr.c +++ b/src/retr.c @@ -147,16 +147,31 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected, } /* Return a printed representation of the download rate, as - appropriate for the speed. Appropriate means that if rate is - greater than 1K/s, kilobytes are used, and if rate is greater than - 1MB/s, megabytes are used. - - If PAD is non-zero, strings will be padded to the width of 7 - characters (xxxx.xx). */ + appropriate for the speed. If PAD is non-zero, strings will be + padded to the width of 7 characters (xxxx.xx). */ char * -rate (long bytes, long msecs, int pad) +retr_rate (long bytes, long msecs, int pad) +{ + static char res[20]; + static char *rate_names[] = {"B/s", "KB/s", "MB/s", "GB/s" }; + int units = 0; + + double dlrate = calc_rate (bytes, msecs, &units); + sprintf (res, pad ? "%7.2f %s" : "%.2f %s", dlrate, rate_names[units]); + + return res; +} + +/* Calculate the download rate and trim it as appropriate for the + speed. Appropriate means that if rate is greater than 1K/s, + kilobytes are used, and if rate is greater than 1MB/s, megabytes + are used. + + UNITS is zero for B/s, one for KB/s, two for MB/s, and three for + GB/s. */ +double +calc_rate (long bytes, long msecs, int *units) { - static char res[15]; double dlrate; assert (msecs >= 0); @@ -170,18 +185,17 @@ rate (long bytes, long msecs, int pad) dlrate = (double)1000 * bytes / msecs; if (dlrate < 1024.0) - sprintf (res, pad ? "%7.2f B/s" : "%.2f B/s", dlrate); + *units = 0; else if (dlrate < 1024.0 * 1024.0) - sprintf (res, pad ? "%7.2f K/s" : "%.2f K/s", dlrate / 1024.0); + *units = 1, dlrate /= 1024.0; else if (dlrate < 1024.0 * 1024.0 * 1024.0) - sprintf (res, pad ? "%7.2f M/s" : "%.2f M/s", dlrate / (1024.0 * 1024.0)); + *units = 2, dlrate /= (1024.0 * 1024.0); else /* Maybe someone will need this one day. More realistically, it will get tickled by buggy timers. */ - sprintf (res, pad ? "%7.2f GB/s" : "%.2f GB/s", - dlrate / (1024.0 * 1024.0 * 1024.0)); + *units = 3, dlrate /= (1024.0 * 1024.0 * 1024.0); - return res; + return dlrate; } static int diff --git a/src/retr.h b/src/retr.h index b9d5a378..18cea141 100644 --- a/src/retr.h +++ b/src/retr.h @@ -28,7 +28,8 @@ uerr_t retrieve_url PARAMS ((const char *, char **, char **, const char *, int *)); uerr_t retrieve_from_file PARAMS ((const char *, int, int *)); -char *rate PARAMS ((long, long, int)); +char *retr_rate PARAMS ((long, long, int)); +double calc_rate PARAMS ((long, long, int *)); void printwhat PARAMS ((int, int)); void downloaded_increase PARAMS ((unsigned long));