#endif /* HAVE_GDBM || HAVE_BDB */
#endif /* USE_HCACHE */
-#ifdef USE_SOCKET
-WHERE short C_NetInc; ///< Config: (socket) Update the progress bar after this many KB sent/received (0 to disable)
-#endif /* USE_SOCKET */
#ifdef USE_NNTP
WHERE char *C_NewsServer; ///< Config: (nntp) Url of the news server
WHERE char *C_TsIconFormat; ///< Config: printf-like format string for the terminal's icon title
WHERE char *C_Visual; ///< Config: Editor to use when '~v' is given in the built-in editor
-WHERE short C_ReadInc; ///< Config: Update the progress bar after this many records read (0 to disable)
WHERE short C_SleepTime; ///< Config: Time to pause after certain info messages
WHERE short C_Timeout; ///< Config: Time to wait for user input in menus
WHERE short C_Wrap; ///< Config: Width to wrap text in the pager
-WHERE short C_WriteInc; ///< Config: Update the progress bar after this many records written (0 to disable)
#ifdef USE_SIDEBAR
WHERE short C_SidebarWidth; ///< Config: (sidebar) Width of the sidebar
int idx = m->msg_count;
/* L10N: Comparing the cached data with the IMAP server's data */
- mutt_progress_init(&progress, _("Evaluating cache..."), MUTT_PROGRESS_MSG,
- C_ReadInc, msn_end);
+ mutt_progress_init(&progress, _("Evaluating cache..."), MUTT_PROGRESS_READ, msn_end);
/* If we are using CONDSTORE's "FETCH CHANGEDSINCE", then we keep
* the flags in the header cache, and update them further below.
struct ImapMboxData *mdata = imap_mdata_get(m);
/* L10N: Fetching IMAP flag changes, using the CONDSTORE extension */
- mutt_progress_init(&progress, _("Fetching flag updates..."),
- MUTT_PROGRESS_MSG, C_ReadInc, msn_end);
+ mutt_progress_init(&progress, _("Fetching flag updates..."), MUTT_PROGRESS_READ, msn_end);
snprintf(buf, sizeof(buf), "UID FETCH 1:%u (FLAGS) (CHANGEDSINCE %llu%s)",
uid_next - 1, hc_modseq, eval_qresync ? " VANISHED" : "");
}
unlink(tempfile);
- mutt_progress_init(&progress, _("Fetching message headers..."),
- MUTT_PROGRESS_MSG, C_ReadInc, msn_end);
+ mutt_progress_init(&progress, _("Fetching message headers..."), MUTT_PROGRESS_READ, msn_end);
buf = mutt_buffer_pool_get();
}
rewind(fp);
- mutt_progress_init(&progress, _("Uploading message..."), MUTT_PROGRESS_SIZE, C_NetInc, len);
+ mutt_progress_init(&progress, _("Uploading message..."), MUTT_PROGRESS_NET, len);
mutt_date_make_imap(internaldate, sizeof(internaldate), msg->received);
}
if (output_progress)
{
- mutt_progress_init(&progress, _("Fetching message..."),
- MUTT_PROGRESS_SIZE, C_NetInc, bytes);
+ mutt_progress_init(&progress, _("Fetching message..."), MUTT_PROGRESS_NET, bytes);
}
if (imap_read_literal(msg->fp, adata, bytes, output_progress ? &progress : NULL) < 0)
{
if (!Context->mailbox->quiet)
{
- mutt_progress_init(&progress, _("Update tags..."), MUTT_PROGRESS_MSG,
- 1, Context->mailbox->msg_tagged);
+ mutt_progress_init(&progress, _("Update tags..."),
+ MUTT_PROGRESS_WRITE, Context->mailbox->msg_tagged);
}
#ifdef USE_NOTMUCH
{
char msg[PATH_MAX];
snprintf(msg, sizeof(msg), _("Scanning %s..."), mailbox_path(m));
- mutt_progress_init(&progress, msg, MUTT_PROGRESS_MSG, C_ReadInc, 0);
+ mutt_progress_init(&progress, msg, MUTT_PROGRESS_READ, 0);
}
struct MaildirMboxData *mdata = maildir_mdata_get(m);
{
char msg[PATH_MAX];
snprintf(msg, sizeof(msg), _("Reading %s..."), mailbox_path(m));
- mutt_progress_init(&progress, msg, MUTT_PROGRESS_MSG, C_ReadInc, count);
+ mutt_progress_init(&progress, msg, MUTT_PROGRESS_READ, count);
}
maildir_delayed_parsing(m, &md, &progress);
{
char msg[PATH_MAX];
snprintf(msg, sizeof(msg), _("Writing %s..."), mailbox_path(m));
- mutt_progress_init(&progress, msg, MUTT_PROGRESS_MSG, C_WriteInc, m->msg_count);
+ mutt_progress_init(&progress, msg, MUTT_PROGRESS_WRITE, m->msg_count);
}
for (i = 0; i < m->msg_count; i++)
{
char msg[PATH_MAX];
snprintf(msg, sizeof(msg), _("Reading %s..."), mailbox_path(m));
- mutt_progress_init(&progress, msg, MUTT_PROGRESS_MSG, C_ReadInc, 0);
+ mutt_progress_init(&progress, msg, MUTT_PROGRESS_READ, 0);
}
while (true)
{
char msg[PATH_MAX];
snprintf(msg, sizeof(msg), _("Reading %s..."), mailbox_path(m));
- mutt_progress_init(&progress, msg, MUTT_PROGRESS_MSG, C_ReadInc, 0);
+ mutt_progress_init(&progress, msg, MUTT_PROGRESS_READ, 0);
}
if (!m->emails)
{
char msg[PATH_MAX];
snprintf(msg, sizeof(msg), _("Writing %s..."), mailbox_path(m));
- mutt_progress_init(&progress, msg, MUTT_PROGRESS_MSG, C_WriteInc, m->msg_count);
+ mutt_progress_init(&progress, msg, MUTT_PROGRESS_WRITE, m->msg_count);
}
for (i = first, j = 0; i < m->msg_count; i++)
struct Progress progress;
if (msg)
- mutt_progress_init(&progress, msg, MUTT_PROGRESS_MSG, C_ReadInc, 0);
+ mutt_progress_init(&progress, msg, MUTT_PROGRESS_READ, 0);
mutt_str_strfcpy(buf, query, sizeof(buf));
if (nntp_query(mdata, buf, sizeof(buf)) < 0)
if (!m->quiet)
{
mutt_progress_init(&fc.progress, _("Fetching message headers..."),
- MUTT_PROGRESS_MSG, C_ReadInc, last - first + 1);
+ MUTT_PROGRESS_READ, last - first + 1);
}
for (current = first; current <= last && rc == 0; current++)
{
struct Progress progress;
mutt_progress_init(&progress, _("Loading descriptions..."),
- MUTT_PROGRESS_MSG, C_ReadInc, adata->groups_num - i);
+ MUTT_PROGRESS_READ, adata->groups_num - i);
for (i = groups_num; i < adata->groups_num; i++)
{
struct NntpMboxData *mdata = adata->groups_list[i];
{
// The total mail count is in oldmsgcount, so use that instead of recounting.
mutt_progress_init(&mdata->progress, _("Reading messages..."),
- MUTT_PROGRESS_MSG, C_ReadInc, mdata->oldmsgcount);
+ MUTT_PROGRESS_READ, mdata->oldmsgcount);
mdata->progress_ready = true;
}
/* all is in this function so we don't use data->progress here */
char msg[PATH_MAX];
snprintf(msg, sizeof(msg), _("Writing %s..."), mailbox_path(m));
- mutt_progress_init(&progress, msg, MUTT_PROGRESS_MSG, C_WriteInc, m->msg_count);
+ mutt_progress_init(&progress, msg, MUTT_PROGRESS_WRITE, m->msg_count);
}
header_cache_t *h = nm_hcache_open(m);
goto bail;
#endif
- mutt_progress_init(&progress, _("Executing command on matching messages..."),
- MUTT_PROGRESS_MSG, C_ReadInc,
- (op == MUTT_LIMIT) ? Context->mailbox->msg_count :
- Context->mailbox->vcount);
+ mutt_progress_init(
+ &progress, _("Executing command on matching messages..."), MUTT_PROGRESS_READ,
+ (op == MUTT_LIMIT) ? Context->mailbox->msg_count : Context->mailbox->vcount);
if (op == MUTT_LIMIT)
{
if (op == OP_SEARCH_OPPOSITE)
incr = -incr;
- mutt_progress_init(&progress, _("Searching..."), MUTT_PROGRESS_MSG, C_ReadInc,
+ mutt_progress_init(&progress, _("Searching..."), MUTT_PROGRESS_READ,
Context->mailbox->vcount);
for (int i = cur + incr, j = 0; j != Context->mailbox->vcount; j++)
if (!m->quiet)
{
mutt_progress_init(&progress, _("Fetching message headers..."),
- MUTT_PROGRESS_MSG, C_ReadInc, new_count - old_count);
+ MUTT_PROGRESS_READ, new_count - old_count);
}
if (rc == 0)
return -1;
mutt_progress_init(&progress, _("Marking messages deleted..."),
- MUTT_PROGRESS_MSG, C_WriteInc, num_deleted);
+ MUTT_PROGRESS_WRITE, num_deleted);
#ifdef USE_HCACHE
hc = pop_hcache_open(adata, mailbox_path(m));
return -1;
}
- mutt_progress_init(&progress, _("Fetching message..."), MUTT_PROGRESS_SIZE,
- C_NetInc, e->content->length + e->content->offset - 1);
+ mutt_progress_init(&progress, _("Fetching message..."), MUTT_PROGRESS_NET,
+ e->content->length + e->content->offset - 1);
/* see if we can put in body cache; use our cache as fallback */
msg->fp = mutt_bcache_put(adata->bcache, cache_id(edata->uid));
if (ret == 0)
{
struct Progress progress;
- mutt_progress_init(&progress, _("Verifying message indexes..."),
- MUTT_PROGRESS_SIZE, C_NetInc, 0);
+ mutt_progress_init(&progress, _("Verifying message indexes..."), MUTT_PROGRESS_NET, 0);
for (int i = 0; i < m->msg_count; i++)
m->emails[i]->refno = -1;
*
* @authors
* Copyright (C) 2018 Richard Russon <rich@flatcap.org>
+ * Copyright (C) 2019 Pietro Cerutti <gahr@gahr.ch>
*
* @copyright
* This program is free software: you can redistribute it and/or modify it under
/* These Config Variables are only used in progress.c */
short C_TimeInc; ///< Config: Frequency of progress bar updates (milliseconds)
+short C_ReadInc; ///< Config: Update the progress bar after this many records read (0 to disable)
+short C_WriteInc; ///< Config: Update the progress bar after this many records written (0 to disable)
+short C_NetInc; ///< Config: (socket) Update the progress bar after this many KB sent/received (0 to disable)
/**
* message_bar - Draw a colourful progress bar
mutt_refresh();
}
+/**
+ * progress_choose_increment - Choose the right increment given a ProgressType
+ * @param type ProgressType
+ * @retval Increment value
+ */
+static size_t progress_choose_increment(enum ProgressType type)
+{
+ static short *incs[] = { &C_ReadInc, &C_WriteInc, &C_NetInc };
+ return (type < 0 || type >= mutt_array_size(incs)) ? 0 : *incs[type];
+}
+
+/**
+ * progress_pos_needs_update - Do we need to update, given the current pos?
+ * @param progress Progress
+ * @param pos Current pos
+ * @retval bool Progress needs an update.
+ */
+static bool progress_pos_needs_update(const struct Progress *progress, long pos)
+{
+ const unsigned shift = progress->is_bytes ? 10 : 0;
+ return pos >= (progress->pos + (progress->inc << shift));
+}
+
+/**
+ * progress_time_needs_update - Do we need to update, given the current time?
+ * @param progress Progress
+ * @param now Current time
+ * @retval bool Progress needs an update.
+ */
+static bool progress_time_needs_update(const struct Progress *progress, size_t now)
+{
+ const size_t elapsed = (now - progress->timestamp);
+ return (C_TimeInc == 0) || (now < progress->timestamp) || (C_TimeInc < elapsed);
+}
+
+/**
+ * progress_timestamp - Return the number of milliseconds since the Unix epoch
+ * @retval ms Milliseconds since the Unix epoch
+ */
+static size_t progress_timestamp(void)
+{
+ struct timeval tv = { 0, 0 };
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
/**
* mutt_progress_init - Set up a progress bar
* @param progress Progress bar
* @param msg Message to display; this is copied into the Progress object
- * @param flags Flags, e.g. #MUTT_PROGRESS_SIZE
- * @param inc Increments to display (0 disables updates)
+ * @param type Type, e.g. #MUTT_PROGRESS_READ
* @param size Total size of expected file / traffic
*/
void mutt_progress_init(struct Progress *progress, const char *msg,
- unsigned short flags, unsigned short inc, size_t size)
+ enum ProgressType type, size_t size)
{
- if (!progress)
- return;
- if (OptNoCurses)
+ if (!progress || OptNoCurses)
return;
- struct timeval tv = { 0, 0 };
-
+ /* Initialize Progress structure */
memset(progress, 0, sizeof(struct Progress));
- progress->inc = inc;
- progress->flags = flags;
mutt_str_strfcpy(progress->msg, msg, sizeof(progress->msg));
progress->size = size;
+ progress->inc = progress_choose_increment(type);
+ progress->is_bytes = (type == MUTT_PROGRESS_NET);
+
+ /* Generate the size string, if a total size was specified */
if (progress->size != 0)
{
- if (progress->flags & MUTT_PROGRESS_SIZE)
+ if (progress->is_bytes)
{
mutt_str_pretty_size(progress->sizestr, sizeof(progress->sizestr),
progress->size);
}
else
+ {
snprintf(progress->sizestr, sizeof(progress->sizestr), "%zu", progress->size);
+ }
}
- if (inc == 0)
+
+ if (progress->inc == 0)
{
- if (size != 0)
- mutt_message("%s (%s)", msg, progress->sizestr);
+ /* This progress bar does not increment - write the initial message */
+ if (progress->size != 0)
+ {
+ mutt_message("%s (%s)", progress->msg, progress->sizestr);
+ }
else
- mutt_message(msg);
- return;
+ {
+ mutt_message(progress->msg);
+ }
}
- if (gettimeofday(&tv, NULL) < 0)
- mutt_debug(LL_DEBUG1, "gettimeofday failed: %d\n", errno);
- /* if timestamp is 0 no time-based suppression is done */
- if (C_TimeInc != 0)
+ else
{
- progress->timestamp =
- ((unsigned int) tv.tv_sec * 1000) + (unsigned int) (tv.tv_usec / 1000);
+ /* This progress bar does increment - perform the initial update */
+ mutt_progress_update(progress, 0, 0);
}
- mutt_progress_update(progress, 0, 0);
}
/**
* percentage is calculated from progress->size and pos if progress
* was initialized with positive size, otherwise no percentage is shown
*/
-void mutt_progress_update(struct Progress *progress, long pos, int percent)
+void mutt_progress_update(struct Progress *progress, size_t pos, int percent)
{
- char posstr[128];
- bool update = false;
- struct timeval tv = { 0, 0 };
- unsigned int now = 0;
-
if (OptNoCurses)
return;
- if (progress->inc == 0)
- goto out;
+ const size_t now = progress_timestamp();
- /* refresh if size > inc */
- if ((progress->flags & MUTT_PROGRESS_SIZE) &&
- (pos >= (progress->pos + (progress->inc << 10))))
- {
- update = true;
- }
- else if (pos >= (progress->pos + progress->inc))
- update = true;
+ const bool update = (pos == 0) /* always show the first update */ ||
+ (progress_pos_needs_update(progress, pos) &&
+ progress_time_needs_update(progress, now));
- /* skip refresh if not enough time has passed */
- if (update && progress->timestamp && (gettimeofday(&tv, NULL) == 0))
+ if (progress->inc != 0 && update)
{
- now = ((unsigned int) tv.tv_sec * 1000) + (unsigned int) (tv.tv_usec / 1000);
- if (now && ((now - progress->timestamp) < C_TimeInc))
- update = false;
- }
-
- /* always show the first update */
- if (pos == 0)
- update = true;
+ progress->pos = pos;
+ progress->timestamp = now;
- if (update)
- {
- if (progress->flags & MUTT_PROGRESS_SIZE)
+ char posstr[128];
+ if (progress->is_bytes)
{
- pos = pos / (progress->inc << 10) * (progress->inc << 10);
- mutt_str_pretty_size(posstr, sizeof(posstr), pos);
+ mutt_str_pretty_size(posstr, sizeof(posstr), progress->pos);
}
else
- snprintf(posstr, sizeof(posstr), "%ld", pos);
+ {
+ const size_t round_pos =
+ (progress->pos / (progress->inc << 10)) * (progress->inc << 10);
+ snprintf(posstr, sizeof(posstr), "%zu", round_pos);
+ }
mutt_debug(LL_DEBUG4, "updating progress: %s\n", posstr);
- progress->pos = pos;
- if (now)
- progress->timestamp = now;
-
- if (progress->size > 0)
+ if (progress->size != 0)
{
- message_bar(
- (percent > 0) ? percent :
- (int) (100.0 * (double) progress->pos / progress->size),
- "%s %s/%s (%d%%)", progress->msg, posstr, progress->sizestr,
- (percent > 0) ? percent :
- (int) (100.0 * (double) progress->pos / progress->size));
+ if (percent < 0)
+ {
+ percent = 100.0 * progress->pos / progress->size;
+ }
+ message_bar(percent, "%s %s/%s (%d%%)", progress->msg, posstr,
+ progress->sizestr, percent);
}
else
{
}
}
-out:
- if (pos >= progress->size)
+ if (progress->pos >= progress->size)
mutt_clear_error();
}
*
* @authors
* Copyright (C) 2018 Richard Russon <rich@flatcap.org>
+ * Copyright (C) 2019 Pietro Cerutti <gahr@gahr.ch>
*
* @copyright
* This program is free software: you can redistribute it and/or modify it under
/* These Config Variables are only used in progress.c */
extern short C_TimeInc;
+extern short C_ReadInc;
+extern short C_WriteInc;
+extern short C_NetInc;
-#define MUTT_PROGRESS_SIZE (1 << 0) /**< traffic-based progress */
-#define MUTT_PROGRESS_MSG (1 << 1) /**< message-based progress */
+/**
+ * Enum ProgressType - What kind of operation is this progress tracking?
+ */
+enum ProgressType
+{
+ MUTT_PROGRESS_READ, ///< Progress tracks elements, according to C_ReadInc
+ MUTT_PROGRESS_WRITE, ///< Progress tracks elements, according to C_WriteInc
+ MUTT_PROGRESS_NET ///< Progress tracks bytes, according to C_NetInc
+};
/**
* struct Progress - A progress bar
*/
struct Progress
{
- unsigned short inc;
- unsigned short flags;
char msg[1024];
- long pos;
+ char sizestr[24];
+ size_t pos;
size_t size;
- unsigned int timestamp;
- char sizestr[128];
+ size_t inc;
+ long timestamp;
+ bool is_bytes;
};
-void mutt_progress_init(struct Progress *progress, const char *msg,
- unsigned short flags, unsigned short inc, size_t size);
-void mutt_progress_update(struct Progress *progress, long pos, int percent);
+void mutt_progress_init(struct Progress *progress, const char *msg, enum ProgressType type, size_t size);
+void mutt_progress_update(struct Progress *progress, size_t pos, int percent);
#endif /* MUTT_PROGRESS_H */
}
stat(msgfile, &st);
unlink(msgfile);
- mutt_progress_init(&progress, _("Sending message..."), MUTT_PROGRESS_SIZE,
- C_NetInc, st.st_size);
+ mutt_progress_init(&progress, _("Sending message..."), MUTT_PROGRESS_NET, st.st_size);
snprintf(buf, sizeof(buf), "DATA\r\n");
if (mutt_socket_send(conn, buf) == -1)
}
void mutt_progress_init(struct Progress *progress, const char *msg,
- unsigned short flags, unsigned short inc, size_t size)
+ int type, size_t size)
{
}
void mutt_progress_update(struct Progress *progress, long pos, int percent)