NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
status.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <stdbool.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include "mutt/lib.h"
35 #include "config/lib.h"
36 #include "core/lib.h"
37 #include "status.h"
38 #include "index/lib.h"
39 #include "menu/lib.h"
40 #include "context.h"
41 #include "format_flags.h"
42 #include "mutt_globals.h"
43 #include "mutt_mailbox.h"
44 #include "mutt_thread.h"
45 #include "muttlib.h"
46 #include "options.h"
47 #include "protos.h"
48 
56 static char *get_sort_str(char *buf, size_t buflen, enum SortType method)
57 {
58  snprintf(buf, buflen, "%s%s%s", (method & SORT_REVERSE) ? "reverse-" : "",
59  (method & SORT_LAST) ? "last-" : "",
61  return buf;
62 }
63 
68 {
70  struct Menu *menu;
71 };
72 
102 static const char *status_format_str(char *buf, size_t buflen, size_t col, int cols,
103  char op, const char *src, const char *prec,
104  const char *if_str, const char *else_str,
105  intptr_t data, MuttFormatFlags flags)
106 {
107  char fmt[128], tmp[128];
108  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
109  struct MenuStatusLineData *msld = (struct MenuStatusLineData *) data;
110  struct IndexSharedData *shared = msld->shared;
111  struct Context *ctx = shared->ctx;
112  struct Mailbox *m = shared->mailbox;
113  struct Menu *menu = msld->menu;
114 
115  *buf = '\0';
116  switch (op)
117  {
118  case 'b':
119  {
120  const int num = mutt_mailbox_check(m, 0);
121  if (!optional)
122  {
123  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
124  snprintf(buf, buflen, fmt, num);
125  }
126  else if (num == 0)
127  optional = false;
128  break;
129  }
130 
131  case 'd':
132  {
133  const int num = m ? m->msg_deleted : 0;
134  if (!optional)
135  {
136  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
137  snprintf(buf, buflen, fmt, num);
138  }
139  else if (num == 0)
140  optional = false;
141  break;
142  }
143 
144  case 'D':
145  // If there's a descriptive name, use it. Otherwise, fall-through
146  if (m && m->name)
147  {
148  mutt_str_copy(tmp, m->name, sizeof(tmp));
149  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
150  snprintf(buf, buflen, fmt, tmp);
151  break;
152  }
153  /* fallthrough */
154  case 'f':
155 #ifdef USE_COMP_MBOX
156  if (m && m->compress_info && (m->realpath[0] != '\0'))
157  {
158  mutt_str_copy(tmp, m->realpath, sizeof(tmp));
159  mutt_pretty_mailbox(tmp, sizeof(tmp));
160  }
161  else
162 #endif
163  if (m && (m->type == MUTT_NOTMUCH) && m->name)
164  {
165  mutt_str_copy(tmp, m->name, sizeof(tmp));
166  }
167  else if (m && !mutt_buffer_is_empty(&m->pathbuf))
168  {
169  mutt_str_copy(tmp, mailbox_path(m), sizeof(tmp));
170  mutt_pretty_mailbox(tmp, sizeof(tmp));
171  }
172  else
173  mutt_str_copy(tmp, _("(no mailbox)"), sizeof(tmp));
174 
175  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
176  snprintf(buf, buflen, fmt, tmp);
177  break;
178  case 'F':
179  {
180  const int num = m ? m->msg_flagged : 0;
181  if (!optional)
182  {
183  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
184  snprintf(buf, buflen, fmt, num);
185  }
186  else if (num == 0)
187  optional = false;
188  break;
189  }
190 
191  case 'h':
192  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
193  snprintf(buf, buflen, fmt, NONULL(ShortHostname));
194  break;
195 
196  case 'l':
197  {
198  const off_t num = m ? m->size : 0;
199  if (!optional)
200  {
201  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
202  mutt_str_pretty_size(tmp, sizeof(tmp), num);
203  snprintf(buf, buflen, fmt, tmp);
204  }
205  else if (num == 0)
206  optional = false;
207  break;
208  }
209 
210  case 'L':
211  if (!optional)
212  {
213  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
214  mutt_str_pretty_size(tmp, sizeof(tmp), ctx ? ctx->vsize : 0);
215  snprintf(buf, buflen, fmt, tmp);
216  }
217  else if (!ctx_has_limit(ctx))
218  optional = false;
219  break;
220 
221  case 'm':
222  {
223  const int num = m ? m->msg_count : 0;
224  if (!optional)
225  {
226  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
227  snprintf(buf, buflen, fmt, num);
228  }
229  else if (num == 0)
230  optional = false;
231  break;
232  }
233 
234  case 'M':
235  if (!optional)
236  {
237  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
238  snprintf(buf, buflen, fmt, m ? m->vcount : 0);
239  }
240  else if (!ctx_has_limit(ctx))
241  optional = false;
242  break;
243 
244  case 'n':
245  {
246  const int num = m ? m->msg_new : 0;
247  if (!optional)
248  {
249  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
250  snprintf(buf, buflen, fmt, num);
251  }
252  else if (num == 0)
253  optional = false;
254  break;
255  }
256 
257  case 'o':
258  {
259  const int num = m ? (m->msg_unread - m->msg_new) : 0;
260  if (!optional)
261  {
262  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
263  snprintf(buf, buflen, fmt, num);
264  }
265  else if (num == 0)
266  optional = false;
267  break;
268  }
269 
270  case 'p':
271  {
272  const int count = mutt_num_postponed(m, false);
273  if (!optional)
274  {
275  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
276  snprintf(buf, buflen, fmt, count);
277  }
278  else if (count == 0)
279  optional = false;
280  break;
281  }
282 
283  case 'P':
284  {
285  if (!menu)
286  break;
287  char *cp = NULL;
288  if (menu->top + menu->pagelen >= menu->max)
289  {
290  cp = menu->top ?
291  /* L10N: Status bar message: the end of the list emails is visible in the index */
292  _("end") :
293  /* L10N: Status bar message: all the emails are visible in the index */
294  _("all");
295  }
296  else
297  {
298  int count = (100 * (menu->top + menu->pagelen)) / menu->max;
299  snprintf(tmp, sizeof(tmp), "%d%%", count);
300  cp = tmp;
301  }
302  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
303  snprintf(buf, buflen, fmt, cp);
304  break;
305  }
306 
307  case 'r':
308  {
309  size_t i = 0;
310 
311  if (m)
312  {
313  i = OptAttachMsg ? 3 :
314  ((m->readonly || m->dontwrite) ? 2 :
315  (m->changed ||
316  /* deleted doesn't necessarily mean changed in IMAP */
317  (m->type != MUTT_IMAP && m->msg_deleted)) ?
318  1 :
319  0);
320  }
321 
322  const struct MbTable *c_status_chars =
323  cs_subset_mbtable(NeoMutt->sub, "status_chars");
324  if (!c_status_chars || !c_status_chars->len)
325  buf[0] = '\0';
326  else if (i >= c_status_chars->len)
327  snprintf(buf, buflen, "%s", c_status_chars->chars[0]);
328  else
329  snprintf(buf, buflen, "%s", c_status_chars->chars[i]);
330  break;
331  }
332 
333  case 'R':
334  {
335  const int read = m ? (m->msg_count - m->msg_unread) : 0;
336  if (!optional)
337  {
338  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
339  snprintf(buf, buflen, fmt, read);
340  }
341  else if (read == 0)
342  optional = false;
343  break;
344  }
345 
346  case 's':
347  {
348  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
349  const short c_sort = cs_subset_sort(NeoMutt->sub, "sort");
350  snprintf(buf, buflen, fmt, get_sort_str(tmp, sizeof(tmp), c_sort));
351  break;
352  }
353 
354  case 'S':
355  {
356  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
357  const short c_sort_aux = cs_subset_sort(NeoMutt->sub, "sort_aux");
358  snprintf(buf, buflen, fmt, get_sort_str(tmp, sizeof(tmp), c_sort_aux));
359  break;
360  }
361 
362  case 't':
363  {
364  const int num = m ? m->msg_tagged : 0;
365  if (!optional)
366  {
367  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
368  snprintf(buf, buflen, fmt, num);
369  }
370  else if (num == 0)
371  optional = false;
372  break;
373  }
374 
375  case 'T':
376  {
377  const enum UseThreads c_use_threads = mutt_thread_style();
378  if (!optional)
379  {
380  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
381  snprintf(buf, buflen, fmt, get_use_threads_str(c_use_threads));
382  }
383  else if (c_use_threads == UT_FLAT)
384  optional = false;
385  break;
386  }
387 
388  case 'u':
389  if (!optional)
390  {
391  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
392  snprintf(buf, buflen, fmt, m ? m->msg_unread : 0);
393  }
394  else if (!m || (m->msg_unread == 0))
395  optional = false;
396  break;
397 
398  case 'v':
399  snprintf(buf, buflen, "%s", mutt_make_version());
400  break;
401 
402  case 'V':
403  if (!optional)
404  {
405  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
406  snprintf(buf, buflen, fmt, ctx_has_limit(ctx) ? ctx->pattern : "");
407  }
408  else if (!ctx_has_limit(ctx))
409  optional = false;
410  break;
411 
412  case 0:
413  *buf = '\0';
414  return src;
415 
416  default:
417  snprintf(buf, buflen, "%%%s%c", prec, op);
418  break;
419  }
420 
421  if (optional)
422  {
423  mutt_expando_format(buf, buflen, col, cols, if_str, status_format_str, data,
425  }
426  else if (flags & MUTT_FORMAT_OPTIONAL)
427  {
428  mutt_expando_format(buf, buflen, col, cols, else_str, status_format_str,
429  data, MUTT_FORMAT_NO_FLAGS);
430  }
431 
432  /* We return the format string, unchanged */
433  return src;
434 }
435 
445 void menu_status_line(char *buf, size_t buflen, struct IndexSharedData *shared,
446  struct Menu *menu, int cols, const char *fmt)
447 {
448  struct MenuStatusLineData data = { shared, menu };
449 
450  mutt_expando_format(buf, buflen, 0, cols, fmt, status_format_str,
451  (intptr_t) &data, MUTT_FORMAT_NO_FLAGS);
452 }
The "current" mailbox.
Definition: context.h:37
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
static const char * status_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Create the status bar string - Implements format_t -Expando Description %b Number of incoming folder...
Definition: status.c:102
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:526
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:780
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:91
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
SortType
Methods for sorting.
Definition: sort2.h:41
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:37
Definition: lib.h:67
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
The "currently-open" mailbox.
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
bool ctx_has_limit(const struct Context *ctx)
Is a limit active?
Definition: context.c:433
#define _(a)
Definition: message.h:28
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:36
enum UseThreads mutt_thread_style(void)
Which threading style is active?
Definition: mutt_thread.c:89
multibyte character table
Definition: mbtable.h:33
Flags to control mutt_expando_format()
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
int vcount
The number of virtual messages.
Definition: mailbox.h:102
Convenience wrapper for the config headers.
Some miscellaneous functions.
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
UseThreads
Which threading style is active, $use_threads.
Definition: mutt_thread.h:77
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
static char * get_sort_str(char *buf, size_t buflen, enum SortType method)
Get the sort method as a string.
Definition: status.c:56
Convenience wrapper for the core headers.
struct Context * ctx
Current Mailbox view.
Definition: shared_data.h:39
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:39
Prototypes for many functions.
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
Create/manipulate threading in emails.
A mailbox.
Definition: mailbox.h:81
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:137
int top
Entry that is the top of the current page.
Definition: lib.h:89
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1679
bool dontwrite
Don&#39;t write the mailbox on close.
Definition: mailbox.h:115
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
int pagelen
Number of entries per screen.
Definition: lib.h:74
void menu_status_line(char *buf, size_t buflen, struct IndexSharedData *shared, struct Menu *menu, int cols, const char *fmt)
Create the status line.
Definition: status.c:445
Data for creating a Menu line.
Definition: status.c:67
struct MbTable * cs_subset_mbtable(const struct ConfigSubset *sub, const char *name)
Get a Multibyte table config item by name.
Definition: helpers.c:145
Unthreaded.
Definition: mutt_thread.h:80
int max
Number of entries in the menu.
Definition: lib.h:71
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
GUI display a user-configurable status line.
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:127
const struct Mapping SortMethods[]
Sort methods for &#39;$sort&#39; for the index.
Definition: mutt_config.c:77
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:749
struct IndexSharedData * shared
Data shared between Index, Pager and Sidebar.
Definition: status.c:69
int msg_new
Number of new messages.
Definition: mailbox.h:95
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
struct Buffer pathbuf
Definition: mailbox.h:83
const char * get_use_threads_str(enum UseThreads value)
Convert UseThreads enum to string.
Definition: mutt_thread.c:108
Convenience wrapper for the library headers.
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
GUI manage the main index (list of emails)
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
char * pattern
Limit pattern string.
Definition: context.h:40
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition: sort2.h:80
struct Menu * menu
Current Menu.
Definition: status.c:70
Mailbox helper functions.
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:78
int len
Number of characters.
Definition: mbtable.h:36
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1476