X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fprogress.c;h=f2be154afc07f429f3e7b73532bc66c90743401d;hp=6dd96018b3c1e13b0d11def47b4f7dfa6eeb1d9d;hb=d763f8bf6d6e13ce006ffab616cc8a77e747a633;hpb=c2c71c32cf7e75336bb45fc299658910e0f9f8af diff --git a/src/progress.c b/src/progress.c index 6dd96018..f2be154a 100644 --- a/src/progress.c +++ b/src/progress.c @@ -1,6 +1,6 @@ /* Download progress. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software - Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, + 2008 Free Software Foundation, Inc. This file is part of GNU Wget. @@ -17,17 +17,18 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wget. If not, see . -In addition, as a special exception, the Free Software Foundation -gives permission to link the code of its release of Wget with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. */ +Additional permission under GNU GPL version 3 section 7 -#include +If you modify this program, or any covered work, by linking or +combining it with the OpenSSL project's OpenSSL library (or a +modified version of that library), containing parts covered by the +terms of the OpenSSL or SSLeay licenses, the Free Software Foundation +grants you additional permission to convey the resulting work. +Corresponding Source for a non-source form of such a combination +shall include the source code for the parts of OpenSSL used as well +as that of the covered work. */ + +#include "wget.h" #include #include @@ -37,8 +38,10 @@ so, delete this exception statement from your version. */ # include #endif #include +#ifdef HAVE_WCHAR_H +# include +#endif -#include "wget.h" #include "progress.h" #include "utils.h" #include "retr.h" @@ -90,10 +93,10 @@ static int current_impl_locked; bool valid_progress_implementation_p (const char *name) { - int i; + size_t i; struct progress_implementation *pi = implementations; char *colon = strchr (name, ':'); - int namelen = colon ? colon - name : strlen (name); + size_t namelen = colon ? (size_t) (colon - name) : strlen (name); for (i = 0; i < countof (implementations); i++, pi++) if (!strncmp (pi->name, name, namelen)) @@ -106,7 +109,7 @@ valid_progress_implementation_p (const char *name) void set_progress_implementation (const char *name) { - int i, namelen; + size_t i, namelen; struct progress_implementation *pi = implementations; const char *colon; @@ -114,7 +117,7 @@ set_progress_implementation (const char *name) name = DEFAULT_PROGRESS_IMPLEMENTATION; colon = strchr (name, ':'); - namelen = colon ? colon - name : strlen (name); + namelen = colon ? (size_t) (colon - name) : strlen (name); for (i = 0; i < countof (implementations); i++, pi++) if (!strncmp (pi->name, name, namelen)) @@ -450,8 +453,8 @@ dot_set_params (const char *params) } else fprintf (stderr, - _("Invalid dot style specification `%s'; leaving unchanged.\n"), - params); + _("Invalid dot style specification %s; leaving unchanged.\n"), + quote (params)); } /* "Thermometer" (bar) progress. */ @@ -576,8 +579,9 @@ bar_create (wgint initial, wgint total) /* - 1 because we don't want to use the last screen column. */ bp->width = screen_width - 1; - /* + 1 for the terminating zero. */ - bp->buffer = xmalloc (bp->width + 1); + /* + enough space for the terminating zero, and hopefully enough room + * for multibyte characters. */ + bp->buffer = xmalloc (bp->width + 100); logputs (LOG_VERBOSE, "\n"); @@ -620,7 +624,7 @@ bar_update (void *progress, wgint howmuch, double dltime) if (screen_width != old_width) { bp->width = screen_width - 1; - bp->buffer = xrealloc (bp->buffer, bp->width + 1); + bp->buffer = xrealloc (bp->buffer, bp->width + 100); force_screen_update = true; } received_sigwinch = 0; @@ -763,6 +767,73 @@ update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime) #endif } +#if USE_NLS_PROGRESS_BAR +int +count_cols (const char *mbs) +{ + wchar_t wc; + int bytes; + int remaining = strlen(mbs); + int cols = 0; + int wccols; + + while (*mbs != '\0') + { + bytes = mbtowc (&wc, mbs, remaining); + assert (bytes != 0); /* Only happens when *mbs == '\0' */ + if (bytes == -1) + { + /* Invalid sequence. We'll just have to fudge it. */ + return cols + remaining; + } + mbs += bytes; + remaining -= bytes; + wccols = wcwidth(wc); + cols += (wccols == -1? 1 : wccols); + } + return cols; +} +#else +# define count_cols(mbs) ((int)(strlen(mbs))) +#endif + +const char * +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_trans; + static int bytes_cols_diff; + if (eta_trans == NULL) + { + int nbytes; + int ncols; + +#if USE_NLS_PROGRESS_BAR + eta_trans = _(eta_str); +#else + eta_trans = eta_str; +#endif + + /* Determine the number of bytes used in the translated string, + * versus the number of columns used. This is to figure out how + * many spaces to add at the end to pad to the full line width. + * + * We'll store the difference between the number of bytes and + * number of columns, so that removing this from the string length + * will reveal the total number of columns in the progress bar. */ + nbytes = strlen (eta_trans); + ncols = count_cols (eta_trans); + bytes_cols_diff = nbytes - ncols; + } + + if (bcd != NULL) + *bcd = bytes_cols_diff; + + return eta_trans; +} + #define APPEND_LITERAL(s) do { \ memcpy (p, s, sizeof (s) - 1); \ p += sizeof (s) - 1; \ @@ -784,7 +855,10 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) wgint size = bp->initial_length + bp->count; const char *size_grouped = with_thousand_seps (size); - int size_grouped_len = strlen (size_grouped); + int size_grouped_len = count_cols (size_grouped); + /* Difference between num cols and num bytes: */ + int size_grouped_diff = strlen (size_grouped) - size_grouped_len; + int size_grouped_pad; /* Used to pad the field width for size_grouped. */ struct bar_progress_hist *hist = &bp->hist; @@ -802,12 +876,16 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) "[]" - progress bar decorations - 2 chars " nnn,nnn,nnn" - downloaded bytes - 12 chars or very rarely more " 12.5K/s" - download rate - 8 chars - " eta 36m 51s" - ETA - 13 chars + " 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 + 13); + int progress_size = bp->width - (4 + 2 + dlbytes_size + 8 + 14); + + /* The difference between the number of bytes used, + and the number of columns used. */ + int bytes_cols_diff = 0; if (progress_size < 5) progress_size = 0; @@ -889,8 +967,17 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) } /* " 234,567,890" */ - sprintf (p, " %-11s", size_grouped); + sprintf (p, " %s", size_grouped); move_to_end (p); + /* Pad with spaces to 11 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; + size_grouped_pad > 0; + --size_grouped_pad) + { + *p++ = ' '; + } /* " 12.52K/s" */ if (hist->total_time > 0 && hist->total_bytes) @@ -942,9 +1029,8 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) bp->last_eta_time = dl_total_time; } - /* Translation note: "ETA" is English-centric, but this must - be short, ideally 3 chars. Abbreviate if necessary. */ - sprintf (p, _(" eta %s"), eta_to_human_short (eta, false)); + sprintf (p, get_eta(&bytes_cols_diff), + eta_to_human_short (eta, false)); move_to_end (p); } else if (bp->total_length > 0) @@ -956,11 +1042,16 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) else { /* When the download is done, print the elapsed time. */ + int nbytes; + int ncols; /* Note to translators: this should not take up more room than available here. Abbreviate if necessary. */ strcpy (p, _(" in ")); - move_to_end (p); /* not p+=6, think translations! */ + nbytes = strlen (p); + ncols = count_cols (p); + bytes_cols_diff = nbytes - ncols; + p += nbytes; if (dl_total_time >= 10) strcpy (p, eta_to_human_short ((int) (dl_total_time + 0.5), false)); else @@ -968,9 +1059,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done) move_to_end (p); } - assert (p - bp->buffer <= bp->width); - - while (p < bp->buffer + bp->width) + while (p - bp->buffer - bytes_cols_diff - size_grouped_diff < bp->width) *p++ = ' '; *p = '\0'; } @@ -1068,7 +1157,7 @@ eta_to_human_short (int secs, bool condensed) else if (secs < 48 * 3600) sprintf (buf, "%dh%s%dm", secs / 3600, space, (secs / 60) % 60); else if (secs < 100 * 86400) - sprintf (buf, "%dd%s%dh", secs / 86400, space, (secs / 3600) % 60); + sprintf (buf, "%dd%s%dh", secs / 86400, space, (secs / 3600) % 24); else /* even (2^31-1)/86400 doesn't overflow BUF. */ sprintf (buf, "%dd", secs / 86400);