]> sjero.net Git - wget/blobdiff - src/progress.c
[svn] Implemented breadth-first retrieval.
[wget] / src / progress.c
index fc7ced31a881b5d7fbc605bbbd265e4f6f34b45b..e167b7bfc41843c4288c9caf0f937fe2615e0fab 100644 (file)
@@ -27,6 +27,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 # include <strings.h>
 #endif /* HAVE_STRING_H */
 #include <assert.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
 
 #include "wget.h"
 #include "progress.h"
@@ -43,10 +46,10 @@ struct progress_implementation {
 
 /* Necessary forward declarations. */
 
-static void *dp_create PARAMS ((long, long));
-static void dp_update PARAMS ((void *, long));
-static void dp_finish PARAMS ((void *));
-static void dp_set_params PARAMS ((const char *));
+static void *dot_create PARAMS ((long, long));
+static void dot_update PARAMS ((void *, long));
+static void dot_finish PARAMS ((void *));
+static void dot_set_params PARAMS ((const char *));
 
 static void *bar_create PARAMS ((long, long));
 static void bar_update PARAMS ((void *, long));
@@ -54,11 +57,19 @@ static void bar_finish PARAMS ((void *));
 static void bar_set_params PARAMS ((const char *));
 
 static struct progress_implementation implementations[] = {
-  { "dot", dp_create, dp_update, dp_finish, dp_set_params },
+  { "dot", dot_create, dot_update, dot_finish, dot_set_params },
   { "bar", bar_create, bar_update, bar_finish, bar_set_params }
 };
 static struct progress_implementation *current_impl;
 
+/* Default progress implementation should be something that works
+   under all display types.  If you put something other than "dot"
+   here, remember that bar_set_params tries to switch to this if we're
+   not running on a TTY.  So changing this to "bar" could cause
+   infloop.  */
+
+#define DEFAULT_PROGRESS_IMPLEMENTATION "dot"
+
 /* Return non-zero if NAME names a valid progress bar implementation.
    The characters after the first : will be ignored.  */
 
@@ -81,10 +92,15 @@ valid_progress_implementation_p (const char *name)
 void
 set_progress_implementation (const char *name)
 {
-  int i = 0;
+  int i, namelen;
   struct progress_implementation *pi = implementations;
-  char *colon = strchr (name, ':');
-  int namelen = colon ? colon - name : strlen (name);
+  char *colon;
+
+  if (!name)
+    name = DEFAULT_PROGRESS_IMPLEMENTATION;
+
+  colon = strchr (name, ':');
+  namelen = colon ? colon - name : strlen (name);
 
   for (i = 0; i < ARRAY_SIZE (implementations); i++, pi++)
     if (!strncmp (pi->name, name, namelen))
@@ -154,7 +170,7 @@ struct dot_progress {
 /* Dot-progress backend for progress_create. */
 
 static void *
-dp_create (long initial, long total)
+dot_create (long initial, long total)
 {
   struct dot_progress *dp = xmalloc (sizeof (struct dot_progress));
 
@@ -204,10 +220,10 @@ print_percentage (long bytes, long expected)
 }
 
 static void
-print_elapsed (struct dot_progress *dp, long bytes)
+print_download_speed (struct dot_progress *dp, long bytes)
 {
   long timer_value = wtimer_elapsed (dp->timer);
-  logprintf (LOG_VERBOSE, " %s",
+  logprintf (LOG_VERBOSE, " %s",
             rate (bytes, timer_value - dp->last_timer_value, 1));
   dp->last_timer_value = timer_value;
 }
@@ -215,7 +231,7 @@ print_elapsed (struct dot_progress *dp, long bytes)
 /* Dot-progress backend for progress_update. */
 
 static void
-dp_update (void *progress, long howmuch)
+dot_update (void *progress, long howmuch)
 {
   struct dot_progress *dp = progress;
   int dot_bytes = opt.dot_bytes;
@@ -242,7 +258,8 @@ dp_update (void *progress, long howmuch)
          if (dp->total_length)
            print_percentage (dp->rows * row_bytes, dp->total_length);
 
-         print_elapsed (dp, row_bytes - (dp->initial_length % row_bytes));
+         print_download_speed (dp,
+                               row_bytes - (dp->initial_length % row_bytes));
        }
     }
 
@@ -252,7 +269,7 @@ dp_update (void *progress, long howmuch)
 /* Dot-progress backend for progress_finish. */
 
 static void
-dp_finish (void *progress)
+dot_finish (void *progress)
 {
   struct dot_progress *dp = progress;
   int dot_bytes = opt.dot_bytes;
@@ -275,9 +292,9 @@ dp_finish (void *progress)
                        dp->total_length);
     }
 
-  print_elapsed (dp, dp->dots * dot_bytes
-                + dp->accumulated
-                - dp->initial_length % row_bytes);
+  print_download_speed (dp, dp->dots * dot_bytes
+                       + dp->accumulated
+                       - dp->initial_length % row_bytes);
   logputs (LOG_VERBOSE, "\n\n");
 
   log_set_flush (0);
@@ -292,7 +309,7 @@ dp_finish (void *progress)
    giga.  */
 
 static void
-dp_set_params (const char *params)
+dot_set_params (const char *params)
 {
   if (!params)
     return;
@@ -397,6 +414,14 @@ bar_update (void *progress, long howmuch)
   long dltime = wtimer_elapsed (bp->timer);
 
   bp->count += howmuch;
+  if (bp->total_length > 0
+      && bp->count + bp->initial_length > bp->total_length)
+    /* We could be downloading more than total_length, e.g. when the
+       server sends an incorrect Content-Length header.  In that case,
+       adjust bp->total_length to the new reality, so that the code in
+       create_image() that depends on total size being smaller or
+       equal to the expected size doesn't abort.  */
+    bp->total_length = bp->count + bp->initial_length;
 
   if (screen_width != bp->width)
     {
@@ -418,8 +443,15 @@ static void
 bar_finish (void *progress)
 {
   struct bar_progress *bp = progress;
+  long elapsed = wtimer_elapsed (bp->timer);
+
+  if (elapsed == 0)
+    /* If the download was faster than the granularity of the timer,
+       fake some output so that we don't get the ugly "----.--" rate
+       at the download finish.  */
+    elapsed = 1;
 
-  create_image (bp, wtimer_elapsed (bp->timer));
+  create_image (bp, elapsed);
   display_image (bp->buffer);
 
   logputs (LOG_VERBOSE, "\n\n");
@@ -441,14 +473,14 @@ create_image (struct bar_progress *bp, long dltime)
      Calculate its geometry:
 
      "xxx% "         - percentage                - 5 chars
-     "| ... | "      - progress bar decorations  - 3 chars
-     "1234.56 K/s "  - dl rate                   - 12 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
 
      "=====>..."     - progress bar content      - the rest
   */
-  int progress_len = screen_width - (5 + 3 + 12 + 11 + 13);
+  int progress_len = screen_width - (5 + 2 + 12 + 11 + 13);
 
   if (progress_len < 7)
     progress_len = 0;
@@ -491,7 +523,7 @@ create_image (struct bar_progress *bp, long dltime)
       *p++ = ' ';
     }
 
-  /* "2.3 KB/s " */
+  /* "1012.45 K/s " */
   if (dltime && bp->count)
     {
       char *rt = rate (bp->count, dltime, 1);
@@ -501,12 +533,12 @@ create_image (struct bar_progress *bp, long dltime)
     }
   else
     {
-      strcpy (p, "----.-- KB/s ");
-      p += 13;
+      strcpy (p, "  --.-- K/s ");
+      p += 12;
     }
 
   /* "12376 " */
-  sprintf (p, _("%ld "), size);
+  sprintf (p, "%ld ", size);
   p += strlen (p);
 
   /* "ETA: xx:xx:xx" */
@@ -553,6 +585,9 @@ create_image (struct bar_progress *bp, long dltime)
   *p = '\0';
 }
 
+/* Print the contents of the buffer as a one-line ASCII "image" so
+   that it can be overwritten next time.  */
+
 static void
 display_image (char *buf)
 {
@@ -568,9 +603,30 @@ display_image (char *buf)
 }
 
 static void
-bar_set_params (const char *ignored)
+bar_set_params (const char *params)
 {
-  int sw = determine_screen_width ();
+  int sw;
+
+  if ((opt.lfilename
+#ifdef HAVE_ISATTY
+       || !isatty (fileno (stderr))
+#else
+       1
+#endif
+       )
+      && !(params != NULL
+          && 0 == strcmp (params, "force")))
+    {
+      /* We're not printing to a TTY, so revert to the fallback
+        display.  #### We're recursively calling
+        set_progress_implementation here, which is slightly kludgy.
+        It would be nicer if that function could resolve this problem
+        itself.  */
+      set_progress_implementation (NULL);
+      return;
+    }
+
+  sw = determine_screen_width ();
   if (sw && sw >= MINIMUM_SCREEN_WIDTH)
     screen_width = sw;
 }