Skip to content

Commit 993dd56

Browse files
committed
curl: progress bar refresh, get width using ioctl()
Get screen width from the environment variable COLUMNS first, if set. If not, use ioctl(). If nether works, assume 79. Closes #2242 The "refresh" is for the -# output when no total transfer size is known. It will now only use a single updated line even for this case: The "-=O=-" ship moves when data is transferred. The four flying "hashes" move (on a sine wave) on each refresh, independent of data.
1 parent 9d82cde commit 993dd56

File tree

3 files changed

+95
-21
lines changed

3 files changed

+95
-21
lines changed

src/tool_cb_prg.c

Lines changed: 89 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* | (__| |_| | _ <| |___
66
* \___|\___/|_| \_\_____|
77
*
8-
* Copyright (C) 1998 - 2014, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
8+
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
99
*
1010
* This software is licensed as described in the file COPYING, which
1111
* you should have received as part of this distribution. The terms
@@ -21,6 +21,10 @@
2121
***************************************************************************/
2222
#include "tool_setup.h"
2323

24+
#ifdef HAVE_SYS_IOCTL_H
25+
#include <sys/ioctl.h>
26+
#endif
27+
2428
#define ENABLE_CURLX_PRINTF
2529
/* use our own printf() functions */
2630
#include "curlx.h"
@@ -31,6 +35,65 @@
3135

3236
#include "memdebug.h" /* keep this as LAST include */
3337

38+
/* 200 values generated by this perl code:
39+
40+
my $pi = 3.1415;
41+
foreach my $i (1 .. 200) {
42+
printf "%d, ", sin($i/200 * 2 * $pi) * 5000 + 5000;
43+
}
44+
*/
45+
static const unsigned int sinus[] = {
46+
5157, 5313, 5470, 5626, 5782, 5936, 6090, 6243, 6394, 6545, 6693, 6840, 6985,
47+
7128, 7269, 7408, 7545, 7679, 7810, 7938, 8064, 8187, 8306, 8422, 8535, 8644,
48+
8750, 8852, 8950, 9045, 9135, 9221, 9303, 9381, 9454, 9524, 9588, 9648, 9704,
49+
9755, 9801, 9842, 9879, 9911, 9938, 9960, 9977, 9990, 9997, 9999, 9997, 9990,
50+
9977, 9960, 9938, 9911, 9879, 9842, 9801, 9755, 9704, 9648, 9588, 9524, 9455,
51+
9381, 9303, 9221, 9135, 9045, 8950, 8852, 8750, 8645, 8535, 8422, 8306, 8187,
52+
8064, 7939, 7810, 7679, 7545, 7409, 7270, 7129, 6986, 6841, 6694, 6545, 6395,
53+
6243, 6091, 5937, 5782, 5627, 5470, 5314, 5157, 5000, 4843, 4686, 4529, 4373,
54+
4218, 4063, 3909, 3757, 3605, 3455, 3306, 3159, 3014, 2871, 2730, 2591, 2455,
55+
2321, 2190, 2061, 1935, 1813, 1693, 1577, 1464, 1355, 1249, 1147, 1049, 955,
56+
864, 778, 696, 618, 545, 476, 411, 351, 295, 244, 198, 157, 120, 88, 61, 39,
57+
22, 9, 2, 0, 2, 9, 22, 39, 61, 88, 120, 156, 198, 244, 295, 350, 410, 475,
58+
544, 618, 695, 777, 864, 954, 1048, 1146, 1248, 1354, 1463, 1576, 1692, 1812,
59+
1934, 2060, 2188, 2320, 2454, 2590, 2729, 2870, 3013, 3158, 3305, 3454, 3604,
60+
3755, 3908, 4062, 4216, 4372, 4528, 4685, 4842, 4999
61+
};
62+
63+
static void fly(struct ProgressData *bar, bool moved)
64+
{
65+
char buf[256];
66+
int pos;
67+
int check = bar->width - 2;
68+
69+
snprintf(buf, sizeof(buf), "%*s\r", bar->width-1, " ");
70+
memcpy(&buf[bar->bar], "-=O=-", 5);
71+
72+
pos = sinus[bar->tick%200] / (10000 / check);
73+
buf[pos] = '#';
74+
pos = sinus[(bar->tick + 5)%200] / (10000 / check);
75+
buf[pos] = '#';
76+
pos = sinus[(bar->tick + 10)%200] / (10000 / check);
77+
buf[pos] = '#';
78+
pos = sinus[(bar->tick + 15)%200] / (10000 / check);
79+
buf[pos] = '#';
80+
81+
fputs(buf, stderr);
82+
bar->tick += 2;
83+
if(bar->tick >= 200)
84+
bar->tick -= 200;
85+
86+
bar->bar += (moved?bar->barmove:0);
87+
if(bar->bar >= (bar->width - 6)) {
88+
bar->barmove = -1;
89+
bar->bar = bar->width - 6;
90+
}
91+
else if(bar->bar < 0) {
92+
bar->barmove = 1;
93+
bar->bar = 0;
94+
}
95+
}
96+
3497
/*
3598
** callback for CURLOPT_XFERINFOFUNCTION
3699
*/
@@ -74,27 +137,17 @@ int tool_progress_cb(void *clientp,
74137
}
75138
else {
76139
/* total is unknown */
77-
if(bar->prev/1024 == point/1024)
78-
/* the same kilobyte level as last invoke */
79-
return 0;
80-
else if(tvdiff(now, bar->prevtime) < 100L)
140+
if(tvdiff(now, bar->prevtime) < 100L)
81141
/* limit progress-bar updating to 10 Hz */
82142
return 0;
143+
fly(bar, point != bar->prev);
83144
}
84145
}
85146

86147
/* simply count invokes */
87148
bar->calls++;
88149

89-
if(total < 1) {
90-
curl_off_t prevblock = bar->prev / 1024;
91-
curl_off_t thisblock = point / 1024;
92-
while(thisblock > prevblock) {
93-
fprintf(bar->out, "#");
94-
prevblock++;
95-
}
96-
}
97-
else if(point != bar->prev) {
150+
if((total > 0) && (point != bar->prev)) {
98151
if(point > total)
99152
/* we have got more than the expected total! */
100153
total = point;
@@ -121,7 +174,6 @@ void progressbarinit(struct ProgressData *bar,
121174
struct OperationConfig *config)
122175
{
123176
char *colp;
124-
125177
memset(bar, 0, sizeof(struct ProgressData));
126178

127179
/* pass this through to progress function so
@@ -134,14 +186,32 @@ void progressbarinit(struct ProgressData *bar,
134186
if(colp) {
135187
char *endptr;
136188
long num = strtol(colp, &endptr, 10);
137-
if((endptr != colp) && (endptr == colp + strlen(colp)) && (num > 0))
189+
if((endptr != colp) && (endptr == colp + strlen(colp)) && (num > 20))
138190
bar->width = (int)num;
139-
else
140-
bar->width = 79;
141191
curl_free(colp);
142192
}
143-
else
193+
194+
if(!bar->width) {
195+
int cols = 0;
196+
197+
#ifdef TIOCGSIZE
198+
struct ttysize ts;
199+
if(!ioctl(STDIN_FILENO, TIOCGSIZE, &ts))
200+
cols = ts.ts_cols;
201+
#elif defined(TIOCGWINSZ)
202+
struct winsize ts;
203+
if(!ioctl(STDIN_FILENO, TIOCGWINSZ, &ts))
204+
cols = ts.ws_col;
205+
#endif /* TIOCGSIZE */
206+
bar->width = cols;
207+
}
208+
209+
if(!bar->width)
144210
bar->width = 79;
211+
else if(bar->width > MAX_BARLENGTH)
212+
bar->width = MAX_BARLENGTH;
145213

146214
bar->out = config->global->errors;
215+
bar->tick = 150;
216+
bar->barmove = 1;
147217
}

src/tool_cb_prg.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* | (__| |_| | _ <| |___
88
* \___|\___/|_| \_\_____|
99
*
10-
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
10+
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
1111
*
1212
* This software is licensed as described in the file COPYING, which
1313
* you should have received as part of this distribution. The terms
@@ -33,6 +33,9 @@ struct ProgressData {
3333
int width;
3434
FILE *out; /* where to write everything to */
3535
curl_off_t initial_size;
36+
unsigned int tick;
37+
int bar;
38+
int barmove;
3639
};
3740

3841
void progressbarinit(struct ProgressData *bar,

tests/runtests.pl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# | (__| |_| | _ <| |___
77
# \___|\___/|_| \_\_____|
88
#
9-
# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9+
# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
1010
#
1111
# This software is licensed as described in the file COPYING, which
1212
# you should have received as part of this distribution. The terms
@@ -340,6 +340,7 @@ sub logmsg {
340340
$ENV{'CURL_ENTROPY'}="12345678";
341341
$ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic
342342
$ENV{'HOME'}=$pwd;
343+
$ENV{'COLUMNS'}=79; # screen width!
343344

344345
sub catch_zap {
345346
my $signame = shift;

0 commit comments

Comments
 (0)