NeoMutt  2021-02-05-329-g9e03b7
Teaching an old dog new tricks
DOXYGEN
progress.c File Reference

Progress bar. More...

#include "config.h"
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "progress.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "options.h"
+ Include dependency graph for progress.c:

Go to the source code of this file.

Functions

static void message_bar (int percent, const char *fmt,...)
 Draw a colourful progress bar. More...
 
static size_t progress_choose_increment (enum ProgressType type)
 Choose the right increment given a ProgressType. More...
 
static bool progress_pos_needs_update (const struct Progress *progress, long pos)
 Do we need to update, given the current pos? More...
 
static bool progress_time_needs_update (const struct Progress *progress, size_t now)
 Do we need to update, given the current time? More...
 
void mutt_progress_init (struct Progress *progress, const char *msg, enum ProgressType type, size_t size)
 Set up a progress bar. More...
 
void mutt_progress_update (struct Progress *progress, size_t pos, int percent)
 Update the state of the progress bar. More...
 

Detailed Description

Progress bar.

Authors
  • Richard Russon
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file progress.c.

Function Documentation

◆ message_bar()

static void message_bar ( int  percent,
const char *  fmt,
  ... 
)
static

Draw a colourful progress bar.

Parameters
percentage complete
fmtprintf(1)-like formatting string
...Arguments to formatting string

Definition at line 49 of file progress.c.

50 {
51  if (!fmt || !MessageWindow)
52  return;
53 
54  va_list ap;
55  char buf[256], buf2[256];
56  int w = (percent * MessageWindow->state.cols) / 100;
57  size_t l;
58 
59  va_start(ap, fmt);
60  vsnprintf(buf, sizeof(buf), fmt, ap);
61  l = mutt_strwidth(buf);
62  va_end(ap);
63 
64  mutt_simple_format(buf2, sizeof(buf2), 0, MessageWindow->state.cols - 2,
65  JUSTIFY_LEFT, 0, buf, sizeof(buf), false);
66 
68 
69  if (mutt_color(MT_COLOR_PROGRESS) == 0)
70  {
71  mutt_window_addstr(buf2);
72  }
73  else
74  {
75  if (l < w)
76  {
77  /* The string fits within the colour bar */
79  mutt_window_addstr(buf2);
80  w -= l;
81  while (w-- > 0)
82  {
83  mutt_window_addch(' ');
84  }
86  }
87  else
88  {
89  /* The string is too long for the colour bar */
90  int off = mutt_wstr_trunc(buf2, sizeof(buf2), w, NULL);
91 
92  char ch = buf2[off];
93  buf2[off] = '\0';
95  mutt_window_addstr(buf2);
96  buf2[off] = ch;
98  mutt_window_addstr(&buf2[off]);
99  }
100  }
101 
102  clrtoeol();
103  mutt_refresh();
104 }
Progress bar.
Definition: color.h:60
Left justify the text.
Definition: curs_lib.h:43
void mutt_curses_set_color(enum ColorId color)
Set the current colour for text.
Definition: mutt_curses.c:56
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:382
Plain text.
Definition: color.h:58
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:58
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:102
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:122
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:45
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1249
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition: curs_lib.c:1199
int mutt_color(enum ColorId id)
Return the color of an object.
Definition: color.c:1393
int mutt_window_addch(int ch)
Write one character to a Window.
Definition: mutt_window.c:489
int mutt_window_addstr(const char *str)
Write a string to a Window.
Definition: mutt_window.c:519
void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width, enum FormatJustify justify, char pad_char, const char *s, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: curs_lib.c:983
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ progress_choose_increment()

static size_t progress_choose_increment ( enum ProgressType  type)
static

Choose the right increment given a ProgressType.

Parameters
typeProgressType
Return values
Incrementvalue

Definition at line 111 of file progress.c.

112 {
113  const short c_read_inc = cs_subset_number(NeoMutt->sub, "read_inc");
114  const short c_write_inc = cs_subset_number(NeoMutt->sub, "write_inc");
115  const short c_net_inc = cs_subset_number(NeoMutt->sub, "net_inc");
116  const short *incs[] = { &c_read_inc, &c_write_inc, &c_net_inc };
117  return (type >= mutt_array_size(incs)) ? 0 : *incs[type];
118 }
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:159
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define mutt_array_size(x)
Definition: memory.h:33
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ progress_pos_needs_update()

static bool progress_pos_needs_update ( const struct Progress progress,
long  pos 
)
static

Do we need to update, given the current pos?

Parameters
progressProgress
posCurrent pos
Return values
trueProgress needs an update

Definition at line 126 of file progress.c.

127 {
128  const unsigned shift = progress->is_bytes ? 10 : 0;
129  return pos >= (progress->pos + (progress->inc << shift));
130 }
bool is_bytes
Definition: progress.h:52
size_t pos
Definition: progress.h:48
size_t inc
Definition: progress.h:50
+ Here is the caller graph for this function:

◆ progress_time_needs_update()

static bool progress_time_needs_update ( const struct Progress progress,
size_t  now 
)
static

Do we need to update, given the current time?

Parameters
progressProgress
nowCurrent time
Return values
trueProgress needs an update

Definition at line 138 of file progress.c.

139 {
140  const size_t elapsed = (now - progress->timestamp);
141  const short c_time_inc = cs_subset_number(NeoMutt->sub, "time_inc");
142  return (c_time_inc == 0) || (now < progress->timestamp) || (c_time_inc < elapsed);
143 }
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:159
Container for Accounts, Notifications.
Definition: neomutt.h:36
uint64_t timestamp
Definition: progress.h:51
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_progress_init()

void mutt_progress_init ( struct Progress progress,
const char *  msg,
enum ProgressType  type,
size_t  size 
)

Set up a progress bar.

Parameters
progressProgress bar
msgMessage to display; this is copied into the Progress object
typeType, e.g. MUTT_PROGRESS_READ
sizeTotal size of expected file / traffic

Definition at line 152 of file progress.c.

154 {
155  if (!progress || OptNoCurses)
156  return;
157 
158  /* Initialize Progress structure */
159  memset(progress, 0, sizeof(struct Progress));
160  mutt_str_copy(progress->msg, msg, sizeof(progress->msg));
161  progress->size = size;
162  progress->inc = progress_choose_increment(type);
163  progress->is_bytes = (type == MUTT_PROGRESS_NET);
164 
165  /* Generate the size string, if a total size was specified */
166  if (progress->size != 0)
167  {
168  if (progress->is_bytes)
169  {
170  mutt_str_pretty_size(progress->sizestr, sizeof(progress->sizestr),
171  progress->size);
172  }
173  else
174  {
175  snprintf(progress->sizestr, sizeof(progress->sizestr), "%zu", progress->size);
176  }
177  }
178 
179  if (progress->inc == 0)
180  {
181  /* This progress bar does not increment - write the initial message */
182  if (progress->size == 0)
183  {
184  mutt_message(progress->msg);
185  }
186  else
187  {
188  mutt_message("%s (%s)", progress->msg, progress->sizestr);
189  }
190  }
191  else
192  {
193  /* This progress bar does increment - perform the initial update */
194  mutt_progress_update(progress, 0, 0);
195  }
196 }
Progress tracks bytes, according to $net_inc
Definition: progress.h:38
size_t size
Definition: progress.h:49
bool is_bytes
Definition: progress.h:52
#define mutt_message(...)
Definition: logging.h:83
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
A progress bar.
Definition: progress.h:44
void mutt_progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:211
static size_t progress_choose_increment(enum ProgressType type)
Choose the right increment given a ProgressType.
Definition: progress.c:111
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1679
size_t inc
Definition: progress.h:50
char msg[1024]
Definition: progress.h:46
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
char sizestr[24]
Definition: progress.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_progress_update()

void mutt_progress_update ( struct Progress progress,
size_t  pos,
int  percent 
)

Update the state of the progress bar.

Parameters
progressProgress bar
posPosition, or count
percentPercentage complete

If percent is -1, then the percentage will be calculated using pos and the size in progress.

If percent is positive, it is displayed as percentage, otherwise percentage is calculated from progress->size and pos if progress was initialized with positive size, otherwise no percentage is shown

Definition at line 211 of file progress.c.

212 {
213  if (OptNoCurses)
214  return;
215 
216  const uint64_t now = mutt_date_epoch_ms();
217 
218  const bool update = (pos == 0) /* always show the first update */ ||
219  (progress_pos_needs_update(progress, pos) &&
220  progress_time_needs_update(progress, now));
221 
222  if (progress->inc != 0 && update)
223  {
224  progress->pos = pos;
225  progress->timestamp = now;
226 
227  char posstr[128];
228  if (progress->is_bytes)
229  {
230  const size_t round_pos =
231  (progress->pos / (progress->inc << 10)) * (progress->inc << 10);
232  mutt_str_pretty_size(posstr, sizeof(posstr), round_pos);
233  }
234  else
235  {
236  snprintf(posstr, sizeof(posstr), "%zu", progress->pos);
237  }
238 
239  mutt_debug(LL_DEBUG4, "updating progress: %s\n", posstr);
240 
241  if (progress->size != 0)
242  {
243  if (percent < 0)
244  {
245  percent = 100.0 * progress->pos / progress->size;
246  }
247  message_bar(percent, "%s %s/%s (%d%%)", progress->msg, posstr,
248  progress->sizestr, percent);
249  }
250  else
251  {
252  if (percent > 0)
253  message_bar(percent, "%s %s (%d%%)", progress->msg, posstr, percent);
254  else
255  mutt_message("%s %s", progress->msg, posstr);
256  }
257  }
258 
259  if (progress->pos >= progress->size)
261 }
Log at debug level 4.
Definition: logging.h:43
uint64_t mutt_date_epoch_ms(void)
Return the number of milliseconds since the Unix epoch.
Definition: date.c:425
size_t size
Definition: progress.h:49
bool is_bytes
Definition: progress.h:52
#define mutt_message(...)
Definition: logging.h:83
static void message_bar(int percent, const char *fmt,...)
Draw a colourful progress bar.
Definition: progress.c:49
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
static bool progress_pos_needs_update(const struct Progress *progress, long pos)
Do we need to update, given the current pos?
Definition: progress.c:126
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
size_t pos
Definition: progress.h:48
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1679
size_t inc
Definition: progress.h:50
char msg[1024]
Definition: progress.h:46
uint64_t timestamp
Definition: progress.h:51
static bool progress_time_needs_update(const struct Progress *progress, size_t now)
Do we need to update, given the current time?
Definition: progress.c:138
char sizestr[24]
Definition: progress.h:47
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function: