]> sjero.net Git - wget/blob - src/progress.c
Merge current tip with CSS stuff.
[wget] / src / progress.c
1 /* Download progress.
2    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3    2008 Free Software Foundation, Inc.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work.  */
30
31 #include "wget.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <assert.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #include <signal.h>
41 #ifdef HAVE_WCHAR_H
42 # include <wchar.h>
43 #endif
44
45 #include "progress.h"
46 #include "utils.h"
47 #include "retr.h"
48
49 struct progress_implementation {
50   const char *name;
51   bool interactive;
52   void *(*create) (wgint, wgint);
53   void (*update) (void *, wgint, double);
54   void (*finish) (void *, double);
55   void (*set_params) (const char *);
56 };
57
58 /* Necessary forward declarations. */
59
60 static void *dot_create (wgint, wgint);
61 static void dot_update (void *, wgint, double);
62 static void dot_finish (void *, double);
63 static void dot_set_params (const char *);
64
65 static void *bar_create (wgint, wgint);
66 static void bar_update (void *, wgint, double);
67 static void bar_finish (void *, double);
68 static void bar_set_params (const char *);
69
70 static struct progress_implementation implementations[] = {
71   { "dot", 0, dot_create, dot_update, dot_finish, dot_set_params },
72   { "bar", 1, bar_create, bar_update, bar_finish, bar_set_params }
73 };
74 static struct progress_implementation *current_impl;
75 static int current_impl_locked;
76
77 /* Progress implementation used by default.  Can be overriden in
78    wgetrc or by the fallback one.  */
79
80 #define DEFAULT_PROGRESS_IMPLEMENTATION "bar"
81
82 /* Fallback progress implementation should be something that works
83    under all display types.  If you put something other than "dot"
84    here, remember that bar_set_params tries to switch to this if we're
85    not running on a TTY.  So changing this to "bar" could cause
86    infloop.  */
87
88 #define FALLBACK_PROGRESS_IMPLEMENTATION "dot"
89
90 /* Return true if NAME names a valid progress bar implementation.  The
91    characters after the first : will be ignored.  */
92
93 bool
94 valid_progress_implementation_p (const char *name)
95 {
96   size_t i;
97   struct progress_implementation *pi = implementations;
98   char *colon = strchr (name, ':');
99   size_t namelen = colon ? (size_t) (colon - name) : strlen (name);
100
101   for (i = 0; i < countof (implementations); i++, pi++)
102     if (!strncmp (pi->name, name, namelen))
103       return true;
104   return false;
105 }
106
107 /* Set the progress implementation to NAME.  */
108
109 void
110 set_progress_implementation (const char *name)
111 {
112   size_t i, namelen;
113   struct progress_implementation *pi = implementations;
114   const char *colon;
115
116   if (!name)
117     name = DEFAULT_PROGRESS_IMPLEMENTATION;
118
119   colon = strchr (name, ':');
120   namelen = colon ? (size_t) (colon - name) : strlen (name);
121
122   for (i = 0; i < countof (implementations); i++, pi++)
123     if (!strncmp (pi->name, name, namelen))
124       {
125         current_impl = pi;
126         current_impl_locked = 0;
127
128         if (colon)
129           /* We call pi->set_params even if colon is NULL because we
130              want to give the implementation a chance to set up some
131              things it needs to run.  */
132           ++colon;
133
134         if (pi->set_params)
135           pi->set_params (colon);
136         return;
137       }
138   abort ();
139 }
140
141 static int output_redirected;
142
143 void
144 progress_schedule_redirect (void)
145 {
146   output_redirected = 1;
147 }
148
149 /* Create a progress gauge.  INITIAL is the number of bytes the
150    download starts from (zero if the download starts from scratch).
151    TOTAL is the expected total number of bytes in this download.  If
152    TOTAL is zero, it means that the download size is not known in
153    advance.  */
154
155 void *
156 progress_create (wgint initial, wgint total)
157 {
158   /* Check if the log status has changed under our feet. */
159   if (output_redirected)
160     {
161       if (!current_impl_locked)
162         set_progress_implementation (FALLBACK_PROGRESS_IMPLEMENTATION);
163       output_redirected = 0;
164     }
165
166   return current_impl->create (initial, total);
167 }
168
169 /* Return true if the progress gauge is "interactive", i.e. if it can
170    profit from being called regularly even in absence of data.  The
171    progress bar is interactive because it regularly updates the ETA
172    and current update.  */
173
174 bool
175 progress_interactive_p (void *progress)
176 {
177   return current_impl->interactive;
178 }
179
180 /* Inform the progress gauge of newly received bytes.  DLTIME is the
181    time since the beginning of the download.  */
182
183 void
184 progress_update (void *progress, wgint howmuch, double dltime)
185 {
186   current_impl->update (progress, howmuch, dltime);
187 }
188
189 /* Tell the progress gauge to clean up.  Calling this will free the
190    PROGRESS object, the further use of which is not allowed.  */
191
192 void
193 progress_finish (void *progress, double dltime)
194 {
195   current_impl->finish (progress, dltime);
196 }
197 \f
198 /* Dot-printing. */
199
200 struct dot_progress {
201   wgint initial_length;         /* how many bytes have been downloaded
202                                    previously. */
203   wgint total_length;           /* expected total byte count when the
204                                    download finishes */
205
206   int accumulated;              /* number of bytes accumulated after
207                                    the last printed dot */
208
209   int rows;                     /* number of rows printed so far */
210   int dots;                     /* number of dots printed in this row */
211
212   double last_timer_value;
213 };
214
215 /* Dot-progress backend for progress_create. */
216
217 static void *
218 dot_create (wgint initial, wgint total)
219 {
220   struct dot_progress *dp = xnew0 (struct dot_progress);
221   dp->initial_length = initial;
222   dp->total_length   = total;
223
224   if (dp->initial_length)
225     {
226       int dot_bytes = opt.dot_bytes;
227       const wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
228
229       int remainder = dp->initial_length % ROW_BYTES;
230       wgint skipped = dp->initial_length - remainder;
231
232       if (skipped)
233         {
234           wgint skipped_k = skipped / 1024; /* skipped amount in K */
235           int skipped_k_len = numdigit (skipped_k);
236           if (skipped_k_len < 6)
237             skipped_k_len = 6;
238
239           /* Align the [ skipping ... ] line with the dots.  To do
240              that, insert the number of spaces equal to the number of
241              digits in the skipped amount in K.  */
242           logprintf (LOG_VERBOSE, _("\n%*s[ skipping %sK ]"),
243                      2 + skipped_k_len, "",
244                      number_to_static_string (skipped_k));
245         }
246
247       logprintf (LOG_VERBOSE, "\n%6sK",
248                  number_to_static_string (skipped / 1024));
249       for (; remainder >= dot_bytes; remainder -= dot_bytes)
250         {
251           if (dp->dots % opt.dot_spacing == 0)
252             logputs (LOG_VERBOSE, " ");
253           logputs (LOG_VERBOSE, ",");
254           ++dp->dots;
255         }
256       assert (dp->dots < opt.dots_in_line);
257
258       dp->accumulated = remainder;
259       dp->rows = skipped / ROW_BYTES;
260     }
261
262   return dp;
263 }
264
265 static const char *eta_to_human_short (int, bool);
266
267 /* Prints the stats (percentage of completion, speed, ETA) for current
268    row.  DLTIME is the time spent downloading the data in current
269    row.
270
271    #### This function is somewhat uglified by the fact that current
272    row and last row have somewhat different stats requirements.  It
273    might be worthwhile to split it to two different functions.  */
274
275 static void
276 print_row_stats (struct dot_progress *dp, double dltime, bool last)
277 {
278   const wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
279
280   /* bytes_displayed is the number of bytes indicated to the user by
281      dots printed so far, includes the initially "skipped" amount */
282   wgint bytes_displayed = dp->rows * ROW_BYTES + dp->dots * opt.dot_bytes;
283
284   if (last)
285     /* For last row also count bytes accumulated after last dot */
286     bytes_displayed += dp->accumulated;
287
288   if (dp->total_length)
289     {
290       /* Round to floor value to provide gauge how much data *has*
291          been retrieved.  12.8% will round to 12% because the 13% mark
292          has not yet been reached.  100% is only shown when done.  */
293       int percentage = 100.0 * bytes_displayed / dp->total_length;
294       logprintf (LOG_VERBOSE, "%3d%%", percentage);
295     }
296
297   {
298     static char names[] = {' ', 'K', 'M', 'G'};
299     int units;
300     double rate;
301     wgint bytes_this_row;
302     if (!last)
303       bytes_this_row = ROW_BYTES;
304     else
305       /* For last row also include bytes accumulated after last dot.  */
306       bytes_this_row = dp->dots * opt.dot_bytes + dp->accumulated;
307     /* Don't count the portion of the row belonging to initial_length */
308     if (dp->rows == dp->initial_length / ROW_BYTES)
309       bytes_this_row -= dp->initial_length % ROW_BYTES;
310     rate = calc_rate (bytes_this_row, dltime - dp->last_timer_value, &units);
311     logprintf (LOG_VERBOSE, " %4.*f%c",
312                rate >= 99.95 ? 0 : rate >= 9.995 ? 1 : 2,
313                rate, names[units]);
314     dp->last_timer_value = dltime;
315   }
316
317   if (!last)
318     {
319       /* Display ETA based on average speed.  Inspired by Vladi
320          Belperchinov-Shabanski's "wget-new-percentage" patch.  */
321       if (dp->total_length)
322         {
323           wgint bytes_remaining = dp->total_length - bytes_displayed;
324           /* The quantity downloaded in this download run. */
325           wgint bytes_sofar = bytes_displayed - dp->initial_length;
326           double eta = dltime * bytes_remaining / bytes_sofar;
327           if (eta < INT_MAX - 1)
328             logprintf (LOG_VERBOSE, " %s",
329                        eta_to_human_short ((int) (eta + 0.5), true));
330         }
331     }
332   else
333     {
334       /* When done, print the total download time */
335       if (dltime >= 10)
336         logprintf (LOG_VERBOSE, "=%s",
337                    eta_to_human_short ((int) (dltime + 0.5), true));
338       else
339         logprintf (LOG_VERBOSE, "=%ss", print_decimal (dltime));
340     }
341 }
342
343 /* Dot-progress backend for progress_update. */
344
345 static void
346 dot_update (void *progress, wgint howmuch, double dltime)
347 {
348   struct dot_progress *dp = progress;
349   int dot_bytes = opt.dot_bytes;
350   wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
351
352   log_set_flush (false);
353
354   dp->accumulated += howmuch;
355   for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes)
356     {
357       if (dp->dots == 0)
358         logprintf (LOG_VERBOSE, "\n%6sK",
359                    number_to_static_string (dp->rows * ROW_BYTES / 1024));
360
361       if (dp->dots % opt.dot_spacing == 0)
362         logputs (LOG_VERBOSE, " ");
363       logputs (LOG_VERBOSE, ".");
364
365       ++dp->dots;
366       if (dp->dots >= opt.dots_in_line)
367         {
368           ++dp->rows;
369           dp->dots = 0;
370
371           print_row_stats (dp, dltime, false);
372         }
373     }
374
375   log_set_flush (true);
376 }
377
378 /* Dot-progress backend for progress_finish. */
379
380 static void
381 dot_finish (void *progress, double dltime)
382 {
383   struct dot_progress *dp = progress;
384   wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
385   int i;
386
387   log_set_flush (false);
388
389   if (dp->dots == 0)
390     logprintf (LOG_VERBOSE, "\n%6sK",
391                number_to_static_string (dp->rows * ROW_BYTES / 1024));
392   for (i = dp->dots; i < opt.dots_in_line; i++)
393     {
394       if (i % opt.dot_spacing == 0)
395         logputs (LOG_VERBOSE, " ");
396       logputs (LOG_VERBOSE, " ");
397     }
398
399   print_row_stats (dp, dltime, true);
400   logputs (LOG_VERBOSE, "\n\n");
401   log_set_flush (false);
402
403   xfree (dp);
404 }
405
406 /* This function interprets the progress "parameters".  For example,
407    if Wget is invoked with --progress=dot:mega, it will set the
408    "dot-style" to "mega".  Valid styles are default, binary, mega, and
409    giga.  */
410
411 static void
412 dot_set_params (const char *params)
413 {
414   if (!params || !*params)
415     params = opt.dot_style;
416
417   if (!params)
418     return;
419
420   /* We use this to set the retrieval style.  */
421   if (!strcasecmp (params, "default"))
422     {
423       /* Default style: 1K dots, 10 dots in a cluster, 50 dots in a
424          line.  */
425       opt.dot_bytes = 1024;
426       opt.dot_spacing = 10;
427       opt.dots_in_line = 50;
428     }
429   else if (!strcasecmp (params, "binary"))
430     {
431       /* "Binary" retrieval: 8K dots, 16 dots in a cluster, 48 dots
432          (384K) in a line.  */
433       opt.dot_bytes = 8192;
434       opt.dot_spacing = 16;
435       opt.dots_in_line = 48;
436     }
437   else if (!strcasecmp (params, "mega"))
438     {
439       /* "Mega" retrieval, for retrieving very long files; each dot is
440          64K, 8 dots in a cluster, 6 clusters (3M) in a line.  */
441       opt.dot_bytes = 65536L;
442       opt.dot_spacing = 8;
443       opt.dots_in_line = 48;
444     }
445   else if (!strcasecmp (params, "giga"))
446     {
447       /* "Giga" retrieval, for retrieving very very *very* long files;
448          each dot is 1M, 8 dots in a cluster, 4 clusters (32M) in a
449          line.  */
450       opt.dot_bytes = (1L << 20);
451       opt.dot_spacing = 8;
452       opt.dots_in_line = 32;
453     }
454   else
455     fprintf (stderr,
456              _("Invalid dot style specification %s; leaving unchanged.\n"),
457              quote (params));
458 }
459 \f
460 /* "Thermometer" (bar) progress. */
461
462 /* Assumed screen width if we can't find the real value.  */
463 #define DEFAULT_SCREEN_WIDTH 80
464
465 /* Minimum screen width we'll try to work with.  If this is too small,
466    create_image will overflow the buffer.  */
467 #define MINIMUM_SCREEN_WIDTH 45
468
469 /* The last known screen width.  This can be updated by the code that
470    detects that SIGWINCH was received (but it's never updated from the
471    signal handler).  */
472 static int screen_width;
473
474 /* A flag that, when set, means SIGWINCH was received.  */
475 static volatile sig_atomic_t received_sigwinch;
476
477 /* Size of the download speed history ring. */
478 #define DLSPEED_HISTORY_SIZE 20
479
480 /* The minimum time length of a history sample.  By default, each
481    sample is at least 150ms long, which means that, over the course of
482    20 samples, "current" download speed spans at least 3s into the
483    past.  */
484 #define DLSPEED_SAMPLE_MIN 0.15
485
486 /* The time after which the download starts to be considered
487    "stalled", i.e. the current bandwidth is not printed and the recent
488    download speeds are scratched.  */
489 #define STALL_START_TIME 5
490
491 /* Time between screen refreshes will not be shorter than this, so
492    that Wget doesn't swamp the TTY with output.  */
493 #define REFRESH_INTERVAL 0.2
494
495 /* Don't refresh the ETA too often to avoid jerkiness in predictions.
496    This allows ETA to change approximately once per second.  */
497 #define ETA_REFRESH_INTERVAL 0.99
498
499 struct bar_progress {
500   wgint initial_length;         /* how many bytes have been downloaded
501                                    previously. */
502   wgint total_length;           /* expected total byte count when the
503                                    download finishes */
504   wgint count;                  /* bytes downloaded so far */
505
506   double last_screen_update;    /* time of the last screen update,
507                                    measured since the beginning of
508                                    download. */
509
510   int width;                    /* screen width we're using at the
511                                    time the progress gauge was
512                                    created.  this is different from
513                                    the screen_width global variable in
514                                    that the latter can be changed by a
515                                    signal. */
516   char *buffer;                 /* buffer where the bar "image" is
517                                    stored. */
518   int tick;                     /* counter used for drawing the
519                                    progress bar where the total size
520                                    is not known. */
521
522   /* The following variables (kept in a struct for namespace reasons)
523      keep track of recent download speeds.  See bar_update() for
524      details.  */
525   struct bar_progress_hist {
526     int pos;
527     double times[DLSPEED_HISTORY_SIZE];
528     wgint bytes[DLSPEED_HISTORY_SIZE];
529
530     /* The sum of times and bytes respectively, maintained for
531        efficiency. */
532     double total_time;
533     wgint total_bytes;
534   } hist;
535
536   double recent_start;          /* timestamp of beginning of current
537                                    position. */
538   wgint recent_bytes;           /* bytes downloaded so far. */
539
540   bool stalled;                 /* set when no data arrives for longer
541                                    than STALL_START_TIME, then reset
542                                    when new data arrives. */
543
544   /* create_image() uses these to make sure that ETA information
545      doesn't flicker. */
546   double last_eta_time;         /* time of the last update to download
547                                    speed and ETA, measured since the
548                                    beginning of download. */
549   int last_eta_value;
550 };
551
552 static void create_image (struct bar_progress *, double, bool);
553 static void display_image (char *);
554
555 static void *
556 bar_create (wgint initial, wgint total)
557 {
558   struct bar_progress *bp = xnew0 (struct bar_progress);
559
560   /* In theory, our callers should take care of this pathological
561      case, but it can sometimes happen. */
562   if (initial > total)
563     total = initial;
564
565   bp->initial_length = initial;
566   bp->total_length   = total;
567
568   /* Initialize screen_width if this hasn't been done or if it might
569      have changed, as indicated by receiving SIGWINCH.  */
570   if (!screen_width || received_sigwinch)
571     {
572       screen_width = determine_screen_width ();
573       if (!screen_width)
574         screen_width = DEFAULT_SCREEN_WIDTH;
575       else if (screen_width < MINIMUM_SCREEN_WIDTH)
576         screen_width = MINIMUM_SCREEN_WIDTH;
577       received_sigwinch = 0;
578     }
579
580   /* - 1 because we don't want to use the last screen column. */
581   bp->width = screen_width - 1;
582   /* + enough space for the terminating zero, and hopefully enough room
583    * for multibyte characters. */
584   bp->buffer = xmalloc (bp->width + 100);
585
586   logputs (LOG_VERBOSE, "\n");
587
588   create_image (bp, 0, false);
589   display_image (bp->buffer);
590
591   return bp;
592 }
593
594 static void update_speed_ring (struct bar_progress *, wgint, double);
595
596 static void
597 bar_update (void *progress, wgint howmuch, double dltime)
598 {
599   struct bar_progress *bp = progress;
600   bool force_screen_update = false;
601
602   bp->count += howmuch;
603   if (bp->total_length > 0
604       && bp->count + bp->initial_length > bp->total_length)
605     /* We could be downloading more than total_length, e.g. when the
606        server sends an incorrect Content-Length header.  In that case,
607        adjust bp->total_length to the new reality, so that the code in
608        create_image() that depends on total size being smaller or
609        equal to the expected size doesn't abort.  */
610     bp->total_length = bp->initial_length + bp->count;
611
612   update_speed_ring (bp, howmuch, dltime);
613
614   /* If SIGWINCH (the window size change signal) been received,
615      determine the new screen size and update the screen.  */
616   if (received_sigwinch)
617     {
618       int old_width = screen_width;
619       screen_width = determine_screen_width ();
620       if (!screen_width)
621         screen_width = DEFAULT_SCREEN_WIDTH;
622       else if (screen_width < MINIMUM_SCREEN_WIDTH)
623         screen_width = MINIMUM_SCREEN_WIDTH;
624       if (screen_width != old_width)
625         {
626           bp->width = screen_width - 1;
627           bp->buffer = xrealloc (bp->buffer, bp->width + 100);
628           force_screen_update = true;
629         }
630       received_sigwinch = 0;
631     }
632
633   if (dltime - bp->last_screen_update < REFRESH_INTERVAL && !force_screen_update)
634     /* Don't update more often than five times per second. */
635     return;
636
637   create_image (bp, dltime, false);
638   display_image (bp->buffer);
639   bp->last_screen_update = dltime;
640 }
641
642 static void
643 bar_finish (void *progress, double dltime)
644 {
645   struct bar_progress *bp = progress;
646
647   if (bp->total_length > 0
648       && bp->count + bp->initial_length > bp->total_length)
649     /* See bar_update() for explanation. */
650     bp->total_length = bp->initial_length + bp->count;
651
652   create_image (bp, dltime, true);
653   display_image (bp->buffer);
654
655   logputs (LOG_VERBOSE, "\n\n");
656
657   xfree (bp->buffer);
658   xfree (bp);
659 }
660
661 /* This code attempts to maintain the notion of a "current" download
662    speed, over the course of no less than 3s.  (Shorter intervals
663    produce very erratic results.)
664
665    To do so, it samples the speed in 150ms intervals and stores the
666    recorded samples in a FIFO history ring.  The ring stores no more
667    than 20 intervals, hence the history covers the period of at least
668    three seconds and at most 20 reads into the past.  This method
669    should produce reasonable results for downloads ranging from very
670    slow to very fast.
671
672    The idea is that for fast downloads, we get the speed over exactly
673    the last three seconds.  For slow downloads (where a network read
674    takes more than 150ms to complete), we get the speed over a larger
675    time period, as large as it takes to complete thirty reads.  This
676    is good because slow downloads tend to fluctuate more and a
677    3-second average would be too erratic.  */
678
679 static void
680 update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime)
681 {
682   struct bar_progress_hist *hist = &bp->hist;
683   double recent_age = dltime - bp->recent_start;
684
685   /* Update the download count. */
686   bp->recent_bytes += howmuch;
687
688   /* For very small time intervals, we return after having updated the
689      "recent" download count.  When its age reaches or exceeds minimum
690      sample time, it will be recorded in the history ring.  */
691   if (recent_age < DLSPEED_SAMPLE_MIN)
692     return;
693
694   if (howmuch == 0)
695     {
696       /* If we're not downloading anything, we might be stalling,
697          i.e. not downloading anything for an extended period of time.
698          Since 0-reads do not enter the history ring, recent_age
699          effectively measures the time since last read.  */
700       if (recent_age >= STALL_START_TIME)
701         {
702           /* If we're stalling, reset the ring contents because it's
703              stale and because it will make bar_update stop printing
704              the (bogus) current bandwidth.  */
705           bp->stalled = true;
706           xzero (*hist);
707           bp->recent_bytes = 0;
708         }
709       return;
710     }
711
712   /* We now have a non-zero amount of to store to the speed ring.  */
713
714   /* If the stall status was acquired, reset it. */
715   if (bp->stalled)
716     {
717       bp->stalled = false;
718       /* "recent_age" includes the the entired stalled period, which
719          could be very long.  Don't update the speed ring with that
720          value because the current bandwidth would start too small.
721          Start with an arbitrary (but more reasonable) time value and
722          let it level out.  */
723       recent_age = 1;
724     }
725
726   /* Store "recent" bytes and download time to history ring at the
727      position POS.  */
728
729   /* To correctly maintain the totals, first invalidate existing data
730      (least recent in time) at this position. */
731   hist->total_time  -= hist->times[hist->pos];
732   hist->total_bytes -= hist->bytes[hist->pos];
733
734   /* Now store the new data and update the totals. */
735   hist->times[hist->pos] = recent_age;
736   hist->bytes[hist->pos] = bp->recent_bytes;
737   hist->total_time  += recent_age;
738   hist->total_bytes += bp->recent_bytes;
739
740   /* Start a new "recent" period. */
741   bp->recent_start = dltime;
742   bp->recent_bytes = 0;
743
744   /* Advance the current ring position. */
745   if (++hist->pos == DLSPEED_HISTORY_SIZE)
746     hist->pos = 0;
747
748 #if 0
749   /* Sledgehammer check to verify that the totals are accurate. */
750   {
751     int i;
752     double sumt = 0, sumb = 0;
753     for (i = 0; i < DLSPEED_HISTORY_SIZE; i++)
754       {
755         sumt += hist->times[i];
756         sumb += hist->bytes[i];
757       }
758     assert (sumb == hist->total_bytes);
759     /* We can't use assert(sumt==hist->total_time) because some
760        precision is lost by adding and subtracting floating-point
761        numbers.  But during a download this precision should not be
762        detectable, i.e. no larger than 1ns.  */
763     double diff = sumt - hist->total_time;
764     if (diff < 0) diff = -diff;
765     assert (diff < 1e-9);
766   }
767 #endif
768 }
769
770 #if USE_NLS_PROGRESS_BAR
771 int
772 count_cols (const char *mbs)
773 {
774   wchar_t wc;
775   int     bytes;
776   int     remaining = strlen(mbs);
777   int     cols = 0;
778   int     wccols;
779
780   while (*mbs != '\0')
781     {
782       bytes = mbtowc (&wc, mbs, remaining);
783       assert (bytes != 0);  /* Only happens when *mbs == '\0' */
784       if (bytes == -1)
785         {
786           /* Invalid sequence. We'll just have to fudge it. */
787           return cols + remaining;
788         }
789       mbs += bytes;
790       remaining -= bytes;
791       wccols = wcwidth(wc);
792       cols += (wccols == -1? 1 : wccols);
793     }
794   return cols;
795 }
796 #else
797 # define count_cols(mbs) ((int)(strlen(mbs)))
798 #endif
799
800 const char *
801 get_eta (int *bcd)
802 {
803   /* Translation note: "ETA" is English-centric, but this must
804      be short, ideally 3 chars.  Abbreviate if necessary.  */
805   static const char eta_str[] = N_("  eta %s");
806   static const char *eta_trans;
807   static int bytes_cols_diff;
808   if (eta_trans == NULL)
809     {
810       int nbytes;
811       int ncols;
812
813 #if USE_NLS_PROGRESS_BAR
814       eta_trans = _(eta_str);
815 #else
816       eta_trans = eta_str;
817 #endif
818
819       /* Determine the number of bytes used in the translated string,
820        * versus the number of columns used. This is to figure out how
821        * many spaces to add at the end to pad to the full line width.
822        *
823        * We'll store the difference between the number of bytes and
824        * number of columns, so that removing this from the string length
825        * will reveal the total number of columns in the progress bar. */
826       nbytes = strlen (eta_trans);
827       ncols = count_cols (eta_trans);
828       bytes_cols_diff = nbytes - ncols;
829     }
830
831   if (bcd != NULL)
832     *bcd = bytes_cols_diff;
833
834   return eta_trans;
835 }
836
837 #define APPEND_LITERAL(s) do {                  \
838   memcpy (p, s, sizeof (s) - 1);                \
839   p += sizeof (s) - 1;                          \
840 } while (0)
841
842 /* Use move_to_end (s) to get S to point the end of the string (the
843    terminating \0).  This is faster than s+=strlen(s), but some people
844    are confused when they see strchr (s, '\0') in the code.  */
845 #define move_to_end(s) s = strchr (s, '\0');
846
847 #ifndef MAX
848 # define MAX(a, b) ((a) >= (b) ? (a) : (b))
849 #endif
850
851 static void
852 create_image (struct bar_progress *bp, double dl_total_time, bool done)
853 {
854   char *p = bp->buffer;
855   wgint size = bp->initial_length + bp->count;
856
857   const char *size_grouped = with_thousand_seps (size);
858   int size_grouped_len = count_cols (size_grouped);
859   /* Difference between num cols and num bytes: */
860   int size_grouped_diff = strlen (size_grouped) - size_grouped_len;
861   int size_grouped_pad; /* Used to pad the field width for size_grouped. */
862
863   struct bar_progress_hist *hist = &bp->hist;
864
865   /* The progress bar should look like this:
866      xx% [=======>             ] nn,nnn 12.34K/s  eta 36m 51s
867
868      Calculate the geometry.  The idea is to assign as much room as
869      possible to the progress bar.  The other idea is to never let
870      things "jitter", i.e. pad elements that vary in size so that
871      their variance does not affect the placement of other elements.
872      It would be especially bad for the progress bar to be resized
873      randomly.
874
875      "xx% " or "100%"  - percentage               - 4 chars
876      "[]"              - progress bar decorations - 2 chars
877      " nnn,nnn,nnn"    - downloaded bytes         - 12 chars or very rarely more
878      " 12.5K/s"        - download rate             - 8 chars
879      "  eta 36m 51s"   - ETA                      - 14 chars
880
881      "=====>..."       - progress bar             - the rest
882   */
883   int dlbytes_size = 1 + MAX (size_grouped_len, 11);
884   int progress_size = bp->width - (4 + 2 + dlbytes_size + 8 + 14);
885
886   /* The difference between the number of bytes used,
887      and the number of columns used. */
888   int bytes_cols_diff = 0;
889
890   if (progress_size < 5)
891     progress_size = 0;
892
893   /* "xx% " */
894   if (bp->total_length > 0)
895     {
896       int percentage = 100.0 * size / bp->total_length;
897       assert (percentage <= 100);
898
899       if (percentage < 100)
900         sprintf (p, "%2d%% ", percentage);
901       else
902         strcpy (p, "100%");
903       p += 4;
904     }
905   else
906     APPEND_LITERAL ("    ");
907
908   /* The progress bar: "[====>      ]" or "[++==>      ]". */
909   if (progress_size && bp->total_length > 0)
910     {
911       /* Size of the initial portion. */
912       int insz = (double)bp->initial_length / bp->total_length * progress_size;
913
914       /* Size of the downloaded portion. */
915       int dlsz = (double)size / bp->total_length * progress_size;
916
917       char *begin;
918       int i;
919
920       assert (dlsz <= progress_size);
921       assert (insz <= dlsz);
922
923       *p++ = '[';
924       begin = p;
925
926       /* Print the initial portion of the download with '+' chars, the
927          rest with '=' and one '>'.  */
928       for (i = 0; i < insz; i++)
929         *p++ = '+';
930       dlsz -= insz;
931       if (dlsz > 0)
932         {
933           for (i = 0; i < dlsz - 1; i++)
934             *p++ = '=';
935           *p++ = '>';
936         }
937
938       while (p - begin < progress_size)
939         *p++ = ' ';
940       *p++ = ']';
941     }
942   else if (progress_size)
943     {
944       /* If we can't draw a real progress bar, then at least show
945          *something* to the user.  */
946       int ind = bp->tick % (progress_size * 2 - 6);
947       int i, pos;
948
949       /* Make the star move in two directions. */
950       if (ind < progress_size - 2)
951         pos = ind + 1;
952       else
953         pos = progress_size - (ind - progress_size + 5);
954
955       *p++ = '[';
956       for (i = 0; i < progress_size; i++)
957         {
958           if      (i == pos - 1) *p++ = '<';
959           else if (i == pos    ) *p++ = '=';
960           else if (i == pos + 1) *p++ = '>';
961           else
962             *p++ = ' ';
963         }
964       *p++ = ']';
965
966       ++bp->tick;
967     }
968
969   /* " 234,567,890" */
970   sprintf (p, " %s", size_grouped);
971   move_to_end (p);
972   /* Pad with spaces to 11 chars for the size_grouped field;
973    * couldn't use the field width specifier in sprintf, because
974    * it counts in bytes, not characters. */
975   for (size_grouped_pad = 11 - size_grouped_len;
976        size_grouped_pad > 0;
977        --size_grouped_pad)
978     {
979       *p++ = ' ';
980     }
981
982   /* " 12.52K/s" */
983   if (hist->total_time > 0 && hist->total_bytes)
984     {
985       static const char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
986       int units = 0;
987       /* Calculate the download speed using the history ring and
988          recent data that hasn't made it to the ring yet.  */
989       wgint dlquant = hist->total_bytes + bp->recent_bytes;
990       double dltime = hist->total_time + (dl_total_time - bp->recent_start);
991       double dlspeed = calc_rate (dlquant, dltime, &units);
992       sprintf (p, " %4.*f%s", dlspeed >= 99.95 ? 0 : dlspeed >= 9.995 ? 1 : 2,
993                dlspeed, short_units[units]);
994       move_to_end (p);
995     }
996   else
997     APPEND_LITERAL (" --.-K/s");
998
999   if (!done)
1000     {
1001       /* "  eta ..m ..s"; wait for three seconds before displaying the ETA.
1002          That's because the ETA value needs a while to become
1003          reliable.  */
1004       if (bp->total_length > 0 && bp->count > 0 && dl_total_time > 3)
1005         {
1006           int eta;
1007
1008           /* Don't change the value of ETA more than approximately once
1009              per second; doing so would cause flashing without providing
1010              any value to the user. */
1011           if (bp->total_length != size
1012               && bp->last_eta_value != 0
1013               && dl_total_time - bp->last_eta_time < ETA_REFRESH_INTERVAL)
1014             eta = bp->last_eta_value;
1015           else
1016             {
1017               /* Calculate ETA using the average download speed to predict
1018                  the future speed.  If you want to use a speed averaged
1019                  over a more recent period, replace dl_total_time with
1020                  hist->total_time and bp->count with hist->total_bytes.
1021                  I found that doing that results in a very jerky and
1022                  ultimately unreliable ETA.  */
1023               wgint bytes_remaining = bp->total_length - size;
1024               double eta_ = dl_total_time * bytes_remaining / bp->count;
1025               if (eta_ >= INT_MAX - 1)
1026                 goto skip_eta;
1027               eta = (int) (eta_ + 0.5);
1028               bp->last_eta_value = eta;
1029               bp->last_eta_time = dl_total_time;
1030             }
1031
1032           sprintf (p, get_eta(&bytes_cols_diff),
1033                    eta_to_human_short (eta, false));
1034           move_to_end (p);
1035         }
1036       else if (bp->total_length > 0)
1037         {
1038         skip_eta:
1039           APPEND_LITERAL ("             ");
1040         }
1041     }
1042   else
1043     {
1044       /* When the download is done, print the elapsed time.  */
1045       int nbytes;
1046       int ncols;
1047
1048       /* Note to translators: this should not take up more room than
1049          available here.  Abbreviate if necessary.  */
1050       strcpy (p, _("   in "));
1051       nbytes = strlen (p);
1052       ncols  = count_cols (p);
1053       bytes_cols_diff = nbytes - ncols;
1054       p += nbytes;
1055       if (dl_total_time >= 10)
1056         strcpy (p, eta_to_human_short ((int) (dl_total_time + 0.5), false));
1057       else
1058         sprintf (p, "%ss", print_decimal (dl_total_time));
1059       move_to_end (p);
1060     }
1061
1062   while (p - bp->buffer - bytes_cols_diff - size_grouped_diff < bp->width)
1063     *p++ = ' ';
1064   *p = '\0';
1065 }
1066
1067 /* Print the contents of the buffer as a one-line ASCII "image" so
1068    that it can be overwritten next time.  */
1069
1070 static void
1071 display_image (char *buf)
1072 {
1073   bool old = log_set_save_context (false);
1074   logputs (LOG_VERBOSE, "\r");
1075   logputs (LOG_VERBOSE, buf);
1076   log_set_save_context (old);
1077 }
1078
1079 static void
1080 bar_set_params (const char *params)
1081 {
1082   char *term = getenv ("TERM");
1083
1084   if (params
1085       && 0 == strcmp (params, "force"))
1086     current_impl_locked = 1;
1087
1088   if ((opt.lfilename
1089 #ifdef HAVE_ISATTY
1090        /* The progress bar doesn't make sense if the output is not a
1091           TTY -- when logging to file, it is better to review the
1092           dots.  */
1093        || !isatty (fileno (stderr))
1094 #endif
1095        /* Normally we don't depend on terminal type because the
1096           progress bar only uses ^M to move the cursor to the
1097           beginning of line, which works even on dumb terminals.  But
1098           Jamie Zawinski reports that ^M and ^H tricks don't work in
1099           Emacs shell buffers, and only make a mess.  */
1100        || (term && 0 == strcmp (term, "emacs"))
1101        )
1102       && !current_impl_locked)
1103     {
1104       /* We're not printing to a TTY, so revert to the fallback
1105          display.  #### We're recursively calling
1106          set_progress_implementation here, which is slightly kludgy.
1107          It would be nicer if we provided that function a return value
1108          indicating a failure of some sort.  */
1109       set_progress_implementation (FALLBACK_PROGRESS_IMPLEMENTATION);
1110       return;
1111     }
1112 }
1113
1114 #ifdef SIGWINCH
1115 void
1116 progress_handle_sigwinch (int sig)
1117 {
1118   received_sigwinch = 1;
1119   signal (SIGWINCH, progress_handle_sigwinch);
1120 }
1121 #endif
1122
1123 /* Provide a short human-readable rendition of the ETA.  This is like
1124    secs_to_human_time in main.c, except the output doesn't include
1125    fractions (which would look silly in by nature imprecise ETA) and
1126    takes less room.  If the time is measured in hours, hours and
1127    minutes (but not seconds) are shown; if measured in days, then days
1128    and hours are shown.  This ensures brevity while still displaying
1129    as much as possible.
1130
1131    If CONDENSED is true, the separator between minutes and seconds
1132    (and hours and minutes, etc.) is not included, shortening the
1133    display by one additional character.  This is used for dot
1134    progress.
1135
1136    The display never occupies more than 7 characters of screen
1137    space.  */
1138
1139 static const char *
1140 eta_to_human_short (int secs, bool condensed)
1141 {
1142   static char buf[10];          /* 8 should be enough, but just in case */
1143   static int last = -1;
1144   const char *space = condensed ? "" : " ";
1145
1146   /* Trivial optimization.  create_image can call us every 200 msecs
1147      (see bar_update) for fast downloads, but ETA will only change
1148      once per 900 msecs.  */
1149   if (secs == last)
1150     return buf;
1151   last = secs;
1152
1153   if (secs < 100)
1154     sprintf (buf, "%ds", secs);
1155   else if (secs < 100 * 60)
1156     sprintf (buf, "%dm%s%ds", secs / 60, space, secs % 60);
1157   else if (secs < 48 * 3600)
1158     sprintf (buf, "%dh%s%dm", secs / 3600, space, (secs / 60) % 60);
1159   else if (secs < 100 * 86400)
1160     sprintf (buf, "%dd%s%dh", secs / 86400, space, (secs / 3600) % 60);
1161   else
1162     /* even (2^31-1)/86400 doesn't overflow BUF. */
1163     sprintf (buf, "%dd", secs / 86400);
1164
1165   return buf;
1166 }