]> git.pld-linux.org Git - packages/wget.git/blob - wget-porn.patch
- new (now builtin) fancy progress bar, try --progress=porn
[packages/wget.git] / wget-porn.patch
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
4 @@ -69,9 +69,15 @@
5  static void bar_finish PARAMS ((void *, double));
6  static void bar_set_params PARAMS ((const char *));
7  
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 *));
12 +
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 }
18  };
19  static struct progress_implementation *current_impl;
20  static int current_impl_locked;
21 @@ -473,6 +479,7 @@
22  
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));
26  
27  static void *
28  bar_create (long initial, long total)
29 @@ -888,6 +895,339 @@
30      screen_width = sw;
31  }
32  
33 +
34 +static void *
35 +porn_create (long initial, long total)
36 +{
37 +  struct bar_progress *bp = xmalloc (sizeof (struct bar_progress));
38 +
39 +  memset (bp, 0, sizeof (*bp));
40 +
41 +  /* In theory, our callers should take care of this pathological
42 +     case, but it can sometimes happen. */
43 +  if (initial > total)
44 +    total = initial;
45 +
46 +  bp->initial_length = initial;
47 +  bp->total_length   = total;
48 +
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);
53 +
54 +  logputs (LOG_VERBOSE, "\n");
55 +
56 +  porn_create_image (bp, 0);
57 +  display_image (bp->buffer);
58 +
59 +  return bp;
60 +}
61 +
62 +static void
63 +porn_update (void *progress, long howmuch, double dltime)
64 +{
65 +  struct bar_progress *bp = progress;
66 +  int force_screen_update = 0;
67 +
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;
77 +
78 +  update_speed_ring (bp, howmuch, dltime);
79 +
80 +  if (screen_width - 1 != bp->width)
81 +    {
82 +      bp->width = screen_width - 1;
83 +      bp->buffer = xrealloc (bp->buffer, bp->width + 1);
84 +      force_screen_update = 1;
85 +    }
86 +
87 +  if (dltime - bp->last_screen_update < 200 && !force_screen_update)
88 +    /* Don't update more often than five times per second. */
89 +    return;
90 +
91 +  porn_create_image (bp, dltime);
92 +  display_image (bp->buffer);
93 +  bp->last_screen_update = dltime;
94 +}
95 +
96 +static void
97 +porn_finish (void *progress, double dltime)
98 +{
99 +  struct bar_progress *bp = progress;
100 +
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;
105 +
106 +  porn_create_image (bp, dltime);
107 +  display_image (bp->buffer);
108 +
109 +  logputs (LOG_VERBOSE, "\n\n");
110 +
111 +  xfree (bp->buffer);
112 +  xfree (bp);
113 +}
114 +
115 +static void
116 +porn_create_image (struct bar_progress *bp, double dl_total_time)
117 +{
118 +  char *p = bp->buffer;
119 +  long size = bp->initial_length + bp->count;
120 +
121 +  char *size_legible = legible (size);
122 +  int size_legible_len = strlen (size_legible);
123 +
124 +  struct bar_progress_hist *hist = &bp->hist;
125 +
126 +  /* The progress bar should look like this:
127 +     xx% [=======>             ] nn,nnn 12.34K/s ETA 00:00
128 +
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
134 +     randomly.
135 +
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
141 +
142 +     "=====D..."       - progress bar             - the rest
143 +  */
144 +  int dlbytes_size = 1 + MAX (size_legible_len, 11);
145 +  int progress_size = bp->width - (4 + 6 + dlbytes_size + 11 + 13);
146 +
147 +  int percentage = (int)(100.0 * size / bp->total_length);
148 +
149 +  assert (percentage <= 100);
150 +
151 +  if (progress_size < 5)
152 +    progress_size = 0;
153 +
154 +  /* "xx% " */
155 +  if (bp->total_length > 0)
156 +    {
157 +
158 +      if (percentage < 100)
159 +       sprintf (p, "%2d%% ", percentage);
160 +      else
161 +       strcpy (p, "100%");
162 +      p += 4;
163 +    }
164 +  else
165 +    APPEND_LITERAL ("    ");
166 +
167 +  /* The progress bar: "[====>      ]" or "[++==>      ]". */
168 +  if (progress_size && bp->total_length > 0)
169 +    {
170 +      /* Size of the initial portion. */
171 +      int insz = (double)bp->initial_length / bp->total_length * progress_size;
172 +
173 +      /* Size of the downloaded portion. */
174 +      int dlsz = (double)size / bp->total_length * progress_size;
175 +
176 +      char *begin;
177 +      int i;
178 +
179 +      assert (dlsz <= progress_size);
180 +      assert (insz <= dlsz);
181 +
182 +      *p++ = '8';
183 +      begin = p;
184 +
185 +      /* Print the initial portion of the download with '+' chars, the
186 +        rest with '=' and one '>'.  */
187 +      for (i = 0; i < insz; i++)
188 +       *p++ = '+';
189 +      dlsz -= insz;
190 +      if (dlsz > 0)
191 +       {
192 +         for (i = 0; i < dlsz - 1; i++)
193 +           *p++ = '=';
194 +         *p++ = 'D';
195 +       }
196 +
197 +      while (p - begin < progress_size)
198 +       *p++ = ' ';
199 +      *p++ = '(';
200 +      *p++ = '_';
201 +      if (percentage < 25)
202 +        *p++ = '.';
203 +      else if (percentage < 50)
204 +        *p++ = 'o';
205 +      else if (percentage < 75)
206 +        *p++ = '0';
207 +      else
208 +        *p++ = 'O';
209 +      *p++ = '_';
210 +      *p++ = ')';
211 +    }
212 +  else if (progress_size)
213 +    {
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);
217 +      int i, pos;
218 +
219 +      /* Make the star move in two directions. */
220 +      if (ind < progress_size - 2)
221 +       pos = ind + 1;
222 +      else
223 +       pos = progress_size - (ind - progress_size + 5);
224 +
225 +      *p++ = '[';
226 +      for (i = 0; i < progress_size; i++)
227 +       {
228 +         if      (i == pos - 1) *p++ = '8';
229 +         else if (i == pos    ) *p++ = '=';
230 +         else if (i == pos + 1) *p++ = 'D';
231 +         else
232 +           *p++ = ' ';
233 +       }
234 +      *p++ = ']';
235 +
236 +      ++bp->tick;
237 +    }
238 +
239 +  /* " 234,567,890" */
240 +  sprintf (p, " %-11s", legible (size));
241 +  p += strlen (p);
242 +
243 +  /* " 1012.45K/s" */
244 +  if (hist->total_time && hist->total_bytes)
245 +    {
246 +      static char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
247 +      int units = 0;
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]);
254 +      p += strlen (p);
255 +    }
256 +  else
257 +    APPEND_LITERAL ("   --.--K/s");
258 +
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
261 +     reliable.  */
262 +  if (bp->total_length > 0 && dl_total_time > 3000)
263 +    {
264 +      long eta;
265 +      int eta_hrs, eta_min, eta_sec;
266 +
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;
274 +      else
275 +       {
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;
287 +       }
288 +
289 +      eta_hrs = eta / 3600, eta %= 3600;
290 +      eta_min = eta / 60,   eta %= 60;
291 +      eta_sec = eta;
292 +
293 +      if (eta_hrs > 99)
294 +       goto no_eta;
295 +
296 +      if (eta_hrs == 0)
297 +       {
298 +         /* Hours not printed: pad with three spaces. */
299 +         APPEND_LITERAL ("   ");
300 +         sprintf (p, " ETA %02d:%02d", eta_min, eta_sec);
301 +       }
302 +      else
303 +       {
304 +         if (eta_hrs < 10)
305 +           /* Hours printed with one digit: pad with one space. */
306 +           *p++ = ' ';
307 +         sprintf (p, " ETA %d:%02d:%02d", eta_hrs, eta_min, eta_sec);
308 +       }
309 +      p += strlen (p);
310 +    }
311 +  else if (bp->total_length > 0)
312 +    {
313 +    no_eta:
314 +      APPEND_LITERAL ("             ");
315 +    }
316 +
317 +  assert (p - bp->buffer <= bp->width);
318 +
319 +  while (p < bp->buffer + bp->width)
320 +    *p++ = ' ';
321 +  *p = '\0';
322 +}
323 +
324 +static void
325 +porn_set_params (const char *params)
326 +{
327 +  int sw;
328 +  char *term = getenv ("TERM");
329 +
330 +  if (params
331 +      && 0 == strcmp (params, "force"))
332 +    current_impl_locked = 1;
333 +
334 +  if ((opt.lfilename
335 +#ifdef HAVE_ISATTY
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
338 +         dots.  */
339 +       || !isatty (fileno (stderr))
340 +#else
341 +       1
342 +#endif
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"))
349 +       )
350 +      && !current_impl_locked)
351 +    {
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);
358 +      return;
359 +    }
360 +
361 +  sw = determine_screen_width ();
362 +  if (sw && sw >= MINIMUM_SCREEN_WIDTH)
363 +    screen_width = sw;
364 +}
365 +
366  #ifdef SIGWINCH
367  RETSIGTYPE
368  progress_handle_sigwinch (int sig)
This page took 0.074302 seconds and 3 git commands to generate.