1 diff -ur wget-1.9.1/src/progress.c wget-1.9.1-patrys/src/progress.c
2 --- wget-1.9.1/src/progress.c 2003-09-23 22:48:10.000000000 +0200
3 +++ wget-1.9.1-patrys/src/progress.c 2004-05-28 12:32:20.964152440 +0200
5 static void bar_finish PARAMS ((void *, double));
6 static void bar_set_params PARAMS ((const char *));
8 +static void *porn_create PARAMS ((long, long));
9 +static void porn_update PARAMS ((void *, long, double));
10 +static void porn_finish PARAMS ((void *, double));
11 +static void porn_set_params PARAMS ((const char *));
13 static struct progress_implementation implementations[] = {
14 { "dot", dot_create, dot_update, dot_finish, dot_set_params },
15 - { "bar", bar_create, bar_update, bar_finish, bar_set_params }
16 + { "bar", bar_create, bar_update, bar_finish, bar_set_params },
17 + { "porn", porn_create, porn_update, porn_finish, porn_set_params }
19 static struct progress_implementation *current_impl;
20 static int current_impl_locked;
23 static void create_image PARAMS ((struct bar_progress *, double));
24 static void display_image PARAMS ((char *));
25 +static void porn_create_image PARAMS ((struct bar_progress *, double));
28 bar_create (long initial, long total)
35 +porn_create (long initial, long total)
37 + struct bar_progress *bp = xmalloc (sizeof (struct bar_progress));
39 + memset (bp, 0, sizeof (*bp));
41 + /* In theory, our callers should take care of this pathological
42 + case, but it can sometimes happen. */
43 + if (initial > total)
46 + bp->initial_length = initial;
47 + bp->total_length = total;
49 + /* - 1 because we don't want to use the last screen column. */
50 + bp->width = screen_width - 1;
51 + /* + 1 for the terminating zero. */
52 + bp->buffer = xmalloc (bp->width + 1);
54 + logputs (LOG_VERBOSE, "\n");
56 + porn_create_image (bp, 0);
57 + display_image (bp->buffer);
63 +porn_update (void *progress, long howmuch, double dltime)
65 + struct bar_progress *bp = progress;
66 + int force_screen_update = 0;
68 + bp->count += howmuch;
69 + if (bp->total_length > 0
70 + && bp->count + bp->initial_length > bp->total_length)
71 + /* We could be downloading more than total_length, e.g. when the
72 + server sends an incorrect Content-Length header. In that case,
73 + adjust bp->total_length to the new reality, so that the code in
74 + create_image() that depends on total size being smaller or
75 + equal to the expected size doesn't abort. */
76 + bp->total_length = bp->initial_length + bp->count;
78 + update_speed_ring (bp, howmuch, dltime);
80 + if (screen_width - 1 != bp->width)
82 + bp->width = screen_width - 1;
83 + bp->buffer = xrealloc (bp->buffer, bp->width + 1);
84 + force_screen_update = 1;
87 + if (dltime - bp->last_screen_update < 200 && !force_screen_update)
88 + /* Don't update more often than five times per second. */
91 + porn_create_image (bp, dltime);
92 + display_image (bp->buffer);
93 + bp->last_screen_update = dltime;
97 +porn_finish (void *progress, double dltime)
99 + struct bar_progress *bp = progress;
101 + if (bp->total_length > 0
102 + && bp->count + bp->initial_length > bp->total_length)
103 + /* See bar_update() for explanation. */
104 + bp->total_length = bp->initial_length + bp->count;
106 + porn_create_image (bp, dltime);
107 + display_image (bp->buffer);
109 + logputs (LOG_VERBOSE, "\n\n");
111 + xfree (bp->buffer);
116 +porn_create_image (struct bar_progress *bp, double dl_total_time)
118 + char *p = bp->buffer;
119 + long size = bp->initial_length + bp->count;
121 + char *size_legible = legible (size);
122 + int size_legible_len = strlen (size_legible);
124 + struct bar_progress_hist *hist = &bp->hist;
126 + /* The progress bar should look like this:
127 + xx% [=======> ] nn,nnn 12.34K/s ETA 00:00
129 + Calculate the geometry. The idea is to assign as much room as
130 + possible to the progress bar. The other idea is to never let
131 + things "jitter", i.e. pad elements that vary in size so that
132 + their variance does not affect the placement of other elements.
133 + It would be especially bad for the progress bar to be resized
136 + "xx% " or "100%" - percentage - 4 chars
137 + "8(_o_)" - progress bar decorations - 6 chars
138 + " nnn,nnn,nnn" - downloaded bytes - 12 chars or very rarely more
139 + " 1012.56K/s" - dl rate - 11 chars
140 + " ETA xx:xx:xx" - ETA - 13 chars
142 + "=====D..." - progress bar - the rest
144 + int dlbytes_size = 1 + MAX (size_legible_len, 11);
145 + int progress_size = bp->width - (4 + 6 + dlbytes_size + 11 + 13);
147 + int percentage = (int)(100.0 * size / bp->total_length);
149 + assert (percentage <= 100);
151 + if (progress_size < 5)
155 + if (bp->total_length > 0)
158 + if (percentage < 100)
159 + sprintf (p, "%2d%% ", percentage);
161 + strcpy (p, "100%");
165 + APPEND_LITERAL (" ");
167 + /* The progress bar: "[====> ]" or "[++==> ]". */
168 + if (progress_size && bp->total_length > 0)
170 + /* Size of the initial portion. */
171 + int insz = (double)bp->initial_length / bp->total_length * progress_size;
173 + /* Size of the downloaded portion. */
174 + int dlsz = (double)size / bp->total_length * progress_size;
179 + assert (dlsz <= progress_size);
180 + assert (insz <= dlsz);
185 + /* Print the initial portion of the download with '+' chars, the
186 + rest with '=' and one '>'. */
187 + for (i = 0; i < insz; i++)
192 + for (i = 0; i < dlsz - 1; i++)
197 + while (p - begin < progress_size)
201 + if (percentage < 25)
203 + else if (percentage < 50)
205 + else if (percentage < 75)
212 + else if (progress_size)
214 + /* If we can't draw a real progress bar, then at least show
215 + *something* to the user. */
216 + int ind = bp->tick % (progress_size * 2 - 6);
219 + /* Make the star move in two directions. */
220 + if (ind < progress_size - 2)
223 + pos = progress_size - (ind - progress_size + 5);
226 + for (i = 0; i < progress_size; i++)
228 + if (i == pos - 1) *p++ = '8';
229 + else if (i == pos ) *p++ = '=';
230 + else if (i == pos + 1) *p++ = 'D';
239 + /* " 234,567,890" */
240 + sprintf (p, " %-11s", legible (size));
243 + /* " 1012.45K/s" */
244 + if (hist->total_time && hist->total_bytes)
246 + static char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
248 + /* Calculate the download speed using the history ring and
249 + recent data that hasn't made it to the ring yet. */
250 + long dlquant = hist->total_bytes + bp->recent_bytes;
251 + double dltime = hist->total_time + (dl_total_time - bp->recent_start);
252 + double dlspeed = calc_rate (dlquant, dltime, &units);
253 + sprintf (p, " %7.2f%s", dlspeed, short_units[units]);
257 + APPEND_LITERAL (" --.--K/s");
259 + /* " ETA xx:xx:xx"; wait for three seconds before displaying the ETA.
260 + That's because the ETA value needs a while to become
262 + if (bp->total_length > 0 && dl_total_time > 3000)
265 + int eta_hrs, eta_min, eta_sec;
267 + /* Don't change the value of ETA more than approximately once
268 + per second; doing so would cause flashing without providing
269 + any value to the user. */
270 + if (bp->total_length != size
271 + && bp->last_eta_value != 0
272 + && dl_total_time - bp->last_eta_time < 900)
273 + eta = bp->last_eta_value;
276 + /* Calculate ETA using the average download speed to predict
277 + the future speed. If you want to use a speed averaged
278 + over a more recent period, replace dl_total_time with
279 + hist->total_time and bp->count with hist->total_bytes.
280 + I found that doing that results in a very jerky and
281 + ultimately unreliable ETA. */
282 + double time_sofar = (double)dl_total_time / 1000;
283 + long bytes_remaining = bp->total_length - size;
284 + eta = (long) (time_sofar * bytes_remaining / bp->count);
285 + bp->last_eta_value = eta;
286 + bp->last_eta_time = dl_total_time;
289 + eta_hrs = eta / 3600, eta %= 3600;
290 + eta_min = eta / 60, eta %= 60;
298 + /* Hours not printed: pad with three spaces. */
299 + APPEND_LITERAL (" ");
300 + sprintf (p, " ETA %02d:%02d", eta_min, eta_sec);
305 + /* Hours printed with one digit: pad with one space. */
307 + sprintf (p, " ETA %d:%02d:%02d", eta_hrs, eta_min, eta_sec);
311 + else if (bp->total_length > 0)
314 + APPEND_LITERAL (" ");
317 + assert (p - bp->buffer <= bp->width);
319 + while (p < bp->buffer + bp->width)
325 +porn_set_params (const char *params)
328 + char *term = getenv ("TERM");
331 + && 0 == strcmp (params, "force"))
332 + current_impl_locked = 1;
336 + /* The progress bar doesn't make sense if the output is not a
337 + TTY -- when logging to file, it is better to review the
339 + || !isatty (fileno (stderr))
343 + /* Normally we don't depend on terminal type because the
344 + progress bar only uses ^M to move the cursor to the
345 + beginning of line, which works even on dumb terminals. But
346 + Jamie Zawinski reports that ^M and ^H tricks don't work in
347 + Emacs shell buffers, and only make a mess. */
348 + || (term && 0 == strcmp (term, "emacs"))
350 + && !current_impl_locked)
352 + /* We're not printing to a TTY, so revert to the fallback
353 + display. #### We're recursively calling
354 + set_progress_implementation here, which is slightly kludgy.
355 + It would be nicer if we provided that function a return value
356 + indicating a failure of some sort. */
357 + set_progress_implementation (FALLBACK_PROGRESS_IMPLEMENTATION);
361 + sw = determine_screen_width ();
362 + if (sw && sw >= MINIMUM_SCREEN_WIDTH)
368 progress_handle_sigwinch (int sig)