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