char *colon = strchr (name, ':');
int namelen = colon ? colon - name : strlen (name);
- for (i = 0; i < ARRAY_SIZE (implementations); i++, pi++)
+ for (i = 0; i < countof (implementations); i++, pi++)
if (!strncmp (pi->name, name, namelen))
return 1;
return 0;
colon = strchr (name, ':');
namelen = colon ? colon - name : strlen (name);
- for (i = 0; i < ARRAY_SIZE (implementations); i++, pi++)
+ for (i = 0; i < countof (implementations); i++, pi++)
if (!strncmp (pi->name, name, namelen))
{
current_impl = pi;
static void *
dot_create (long initial, long total)
{
- struct dot_progress *dp = xmalloc (sizeof (struct dot_progress));
-
- memset (dp, 0, sizeof (*dp));
-
+ struct dot_progress *dp = xnew0 (struct dot_progress);
dp->initial_length = initial;
dp->total_length = total;
static int screen_width = DEFAULT_SCREEN_WIDTH;
/* Size of the download speed history ring. */
-#define DLSPEED_HISTORY_SIZE 30
+#define DLSPEED_HISTORY_SIZE 20
/* The minimum time length of a history sample. By default, each
- sample is at least 100ms long, which means that, over the course of
- 30 samples, "current" download speed spans at least 3s into the
+ sample is at least 150ms long, which means that, over the course of
+ 20 samples, "current" download speed spans at least 3s into the
past. */
-#define DLSPEED_SAMPLE_MIN 100
+#define DLSPEED_SAMPLE_MIN 150
struct bar_progress {
long initial_length; /* how many bytes have been downloaded
static void *
bar_create (long initial, long total)
{
- struct bar_progress *bp = xmalloc (sizeof (struct bar_progress));
-
- memset (bp, 0, sizeof (*bp));
+ struct bar_progress *bp = xnew0 (struct bar_progress);
/* In theory, our callers should take care of this pathological
case, but it can sometimes happen. */
speed, over the course of no less than 3s. (Shorter intervals
produce very erratic results.)
- To do so, it samples the speed in 0.1s intervals and stores the
+ To do so, it samples the speed in 150ms intervals and stores the
recorded samples in a FIFO history ring. The ring stores no more
- than 30 intervals, hence the history covers the period of at least
- three seconds and at most 30 reads into the past. This method
- should produce good results for both very fast and very slow
- downloads.
+ than 20 intervals, hence the history covers the period of at least
+ three seconds and at most 20 reads into the past. This method
+ should produce reasonable results for downloads ranging from very
+ slow to very fast.
The idea is that for fast downloads, we get the speed over exactly
the last three seconds. For slow downloads (where a network read
- takes more than 0.1s to complete), we get the speed over a larger
+ takes more than 150ms to complete), we get the speed over a larger
time period, as large as it takes to complete thirty reads. This
is good because slow downloads tend to fluctuate more and a
- 3-second average would be very erratic. */
+ 3-second average would be too erratic. */
static void
update_speed_ring (struct bar_progress *bp, long howmuch, double dltime)
else
APPEND_LITERAL (" ");
- /* The progress bar: "[====> ]" */
+ /* The progress bar: "[====> ]" or "[++==> ]". */
if (progress_size && bp->total_length > 0)
{
- double fraction = (double)size / bp->total_length;
- int dlsz = (int)(fraction * progress_size);
+ /* Size of the initial portion. */
+ int insz = (double)bp->initial_length / bp->total_length * progress_size;
+
+ /* Size of the downloaded portion. */
+ int dlsz = (double)size / bp->total_length * progress_size;
+
char *begin;
+ int i;
assert (dlsz <= progress_size);
+ assert (insz <= dlsz);
*p++ = '[';
begin = p;
+ /* Print the initial portion of the download with '+' chars, the
+ rest with '=' and one '>'. */
+ for (i = 0; i < insz; i++)
+ *p++ = '+';
+ dlsz -= insz;
if (dlsz > 0)
{
- /* Draw dlsz-1 '=' chars and one arrow char. */
- while (dlsz-- > 1)
+ for (i = 0; i < dlsz - 1; i++)
*p++ = '=';
*p++ = '>';
}
while (p - begin < progress_size)
*p++ = ' ';
-
*p++ = ']';
}
else if (progress_size)
{
static char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
int units = 0;
- long bytes = hist->total_bytes + bp->recent_bytes;
- double tm = hist->total_time + dl_total_time - bp->recent_start;
- double dlrate = calc_rate (bytes, tm, &units);
- sprintf (p, " %7.2f%s", dlrate, short_units[units]);
+ /* Calculate the download speed using the history ring and
+ recent data that hasn't made it to the ring yet. */
+ long dlquant = hist->total_bytes + bp->recent_bytes;
+ double dltime = hist->total_time + (dl_total_time - bp->recent_start);
+ double dlspeed = calc_rate (dlquant, dltime, &units);
+ sprintf (p, " %7.2f%s", dlspeed, short_units[units]);
p += strlen (p);
}
else
APPEND_LITERAL (" --.--K/s");
- /* " ETA xx:xx:xx" */
+ /* " ETA xx:xx:xx"; wait for three seconds before displaying the ETA.
+ That's because the ETA value needs a while to become
+ reliable. */
if (bp->total_length > 0 && dl_total_time > 3000)
{
long eta;
/* Don't change the value of ETA more than approximately once
per second; doing so would cause flashing without providing
any value to the user. */
- if (dl_total_time - bp->last_eta_time < 900
- && bp->last_eta_value != 0)
+ if (bp->total_length != size
+ && bp->last_eta_value != 0
+ && dl_total_time - bp->last_eta_time < 900)
eta = bp->last_eta_value;
else
{