NeoMutt  2024-02-01-35-geee02f
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
status.c
Go to the documentation of this file.
1
34#include "config.h"
35#include <stdbool.h>
36#include <stdint.h>
37#include <stdio.h>
38#include "mutt/lib.h"
39#include "config/lib.h"
40#include "core/lib.h"
41#include "status.h"
42#include "index/lib.h"
43#include "menu/lib.h"
44#include "postpone/lib.h"
45#include "format_flags.h"
46#include "globals.h"
47#include "mutt_mailbox.h"
48#include "mutt_thread.h"
49#include "muttlib.h"
50#include "mview.h"
51
59static char *get_sort_str(char *buf, size_t buflen, enum SortType method)
60{
61 snprintf(buf, buflen, "%s%s%s", (method & SORT_REVERSE) ? "reverse-" : "",
62 (method & SORT_LAST) ? "last-" : "",
64 return buf;
65}
66
71{
73 struct Menu *menu;
74};
75
105static const char *status_format_str(char *buf, size_t buflen, size_t col, int cols,
106 char op, const char *src, const char *prec,
107 const char *if_str, const char *else_str,
108 intptr_t data, MuttFormatFlags flags)
109{
110 char fmt[128] = { 0 };
111 char tmp[128] = { 0 };
112 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
113 struct MenuStatusLineData *msld = (struct MenuStatusLineData *) data;
114 struct IndexSharedData *shared = msld->shared;
115 struct MailboxView *mv = shared->mailbox_view;
116 struct Mailbox *m = shared->mailbox;
117 struct Menu *menu = msld->menu;
118
119 *buf = '\0';
120 switch (op)
121 {
122 case 'b':
123 {
125 if (!optional)
126 {
127 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
128 snprintf(buf, buflen, fmt, num);
129 }
130 else if (num == 0)
131 {
132 optional = false;
133 }
134 break;
135 }
136
137 case 'd':
138 {
139 const int num = m ? m->msg_deleted : 0;
140 if (!optional)
141 {
142 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
143 snprintf(buf, buflen, fmt, num);
144 }
145 else if (num == 0)
146 {
147 optional = false;
148 }
149 break;
150 }
151
152 case 'D':
153 // If there's a descriptive name, use it. Otherwise, fall-through
154 if (m && m->name)
155 {
156 mutt_str_copy(tmp, m->name, sizeof(tmp));
157 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
158 snprintf(buf, buflen, fmt, tmp);
159 break;
160 }
162
163 case 'f':
164 if (m && m->compress_info && (m->realpath[0] != '\0'))
165 {
166 mutt_str_copy(tmp, m->realpath, sizeof(tmp));
167 mutt_pretty_mailbox(tmp, sizeof(tmp));
168 }
169 else if (m && (m->type == MUTT_NOTMUCH) && m->name)
170 {
171 mutt_str_copy(tmp, m->name, sizeof(tmp));
172 }
173 else if (m && !buf_is_empty(&m->pathbuf))
174 {
175 mutt_str_copy(tmp, mailbox_path(m), sizeof(tmp));
176 mutt_pretty_mailbox(tmp, sizeof(tmp));
177 }
178 else
179 {
180 mutt_str_copy(tmp, _("(no mailbox)"), sizeof(tmp));
181 }
182
183 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
184 snprintf(buf, buflen, fmt, tmp);
185 break;
186 case 'F':
187 {
188 const int num = m ? m->msg_flagged : 0;
189 if (!optional)
190 {
191 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
192 snprintf(buf, buflen, fmt, num);
193 }
194 else if (num == 0)
195 {
196 optional = false;
197 }
198 break;
199 }
200
201 case 'h':
202 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
203 snprintf(buf, buflen, fmt, NONULL(ShortHostname));
204 break;
205
206 case 'l':
207 {
208 const off_t num = m ? m->size : 0;
209 if (!optional)
210 {
211 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
212 mutt_str_pretty_size(tmp, sizeof(tmp), num);
213 snprintf(buf, buflen, fmt, tmp);
214 }
215 else if (num == 0)
216 {
217 optional = false;
218 }
219 break;
220 }
221
222 case 'L':
223 if (!optional)
224 {
225 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
226 mutt_str_pretty_size(tmp, sizeof(tmp), mv ? mv->vsize : 0);
227 snprintf(buf, buflen, fmt, tmp);
228 }
229 else if (!mview_has_limit(mv))
230 {
231 optional = false;
232 }
233 break;
234
235 case 'm':
236 {
237 const int num = m ? m->msg_count : 0;
238 if (!optional)
239 {
240 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
241 snprintf(buf, buflen, fmt, num);
242 }
243 else if (num == 0)
244 {
245 optional = false;
246 }
247 break;
248 }
249
250 case 'M':
251 if (!optional)
252 {
253 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
254 snprintf(buf, buflen, fmt, m ? m->vcount : 0);
255 }
256 else if (!mview_has_limit(mv))
257 {
258 optional = false;
259 }
260 break;
261
262 case 'n':
263 {
264 const int num = m ? m->msg_new : 0;
265 if (!optional)
266 {
267 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
268 snprintf(buf, buflen, fmt, num);
269 }
270 else if (num == 0)
271 {
272 optional = false;
273 }
274 break;
275 }
276
277 case 'o':
278 {
279 const int num = m ? (m->msg_unread - m->msg_new) : 0;
280 if (!optional)
281 {
282 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
283 snprintf(buf, buflen, fmt, num);
284 }
285 else if (num == 0)
286 {
287 optional = false;
288 }
289 break;
290 }
291
292 case 'p':
293 {
294 const int count = mutt_num_postponed(m, false);
295 if (!optional)
296 {
297 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
298 snprintf(buf, buflen, fmt, count);
299 }
300 else if (count == 0)
301 {
302 optional = false;
303 }
304 break;
305 }
306
307 case 'P':
308 {
309 if (!menu)
310 break;
311 char *cp = NULL;
312 if (menu->top + menu->page_len >= menu->max)
313 {
314 cp = menu->top ?
315 /* L10N: Status bar message: the end of the list emails is visible in the index */
316 _("end") :
317 /* L10N: Status bar message: all the emails are visible in the index */
318 _("all");
319 }
320 else
321 {
322 int count = (100 * (menu->top + menu->page_len)) / menu->max;
323 /* L10N: Status bar, percentage of way through index.
324 `%d` is the number, `%%` is the percent symbol.
325 They may be reordered, or space inserted, if you wish. */
326 snprintf(tmp, sizeof(tmp), _("%d%%"), count);
327 cp = tmp;
328 }
329 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
330 snprintf(buf, buflen, fmt, cp);
331 break;
332 }
333
334 case 'r':
335 {
336 size_t i = 0;
337
338 if (m)
339 {
340 i = shared->attach_msg ? 3 :
341 ((m->readonly || m->dontwrite) ? 2 :
342 (m->changed ||
343 /* deleted doesn't necessarily mean changed in IMAP */
344 (m->type != MUTT_IMAP && m->msg_deleted)) ?
345 1 :
346 0);
347 }
348
349 const struct MbTable *c_status_chars = cs_subset_mbtable(NeoMutt->sub, "status_chars");
350 if (!c_status_chars || !c_status_chars->len)
351 buf[0] = '\0';
352 else if (i >= c_status_chars->len)
353 snprintf(buf, buflen, "%s", c_status_chars->chars[0]);
354 else
355 snprintf(buf, buflen, "%s", c_status_chars->chars[i]);
356 break;
357 }
358
359 case 'R':
360 {
361 const int read = m ? (m->msg_count - m->msg_unread) : 0;
362 if (!optional)
363 {
364 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
365 snprintf(buf, buflen, fmt, read);
366 }
367 else if (read == 0)
368 {
369 optional = false;
370 }
371 break;
372 }
373
374 case 's':
375 {
376 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
377 const enum SortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
378 snprintf(buf, buflen, fmt, get_sort_str(tmp, sizeof(tmp), c_sort));
379 break;
380 }
381
382 case 'S':
383 {
384 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
385 const enum SortType c_sort_aux = cs_subset_sort(NeoMutt->sub, "sort_aux");
386 snprintf(buf, buflen, fmt, get_sort_str(tmp, sizeof(tmp), c_sort_aux));
387 break;
388 }
389
390 case 't':
391 {
392 const int num = m ? m->msg_tagged : 0;
393 if (!optional)
394 {
395 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
396 snprintf(buf, buflen, fmt, num);
397 }
398 else if (num == 0)
399 {
400 optional = false;
401 }
402 break;
403 }
404
405 case 'T':
406 {
407 const enum UseThreads c_use_threads = mutt_thread_style();
408 if (!optional)
409 {
410 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
411 snprintf(buf, buflen, fmt, get_use_threads_str(c_use_threads));
412 }
413 else if (c_use_threads == UT_FLAT)
414 {
415 optional = false;
416 }
417 break;
418 }
419
420 case 'u':
421 if (!optional)
422 {
423 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
424 snprintf(buf, buflen, fmt, m ? m->msg_unread : 0);
425 }
426 else if (!m || (m->msg_unread == 0))
427 {
428 optional = false;
429 }
430 break;
431
432 case 'v':
433 snprintf(buf, buflen, "%s", mutt_make_version());
434 break;
435
436 case 'V':
437 if (!optional)
438 {
439 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
440 snprintf(buf, buflen, fmt, mview_has_limit(mv) ? mv->pattern : "");
441 }
442 else if (!mview_has_limit(mv))
443 {
444 optional = false;
445 }
446 break;
447
448 case 0:
449 *buf = '\0';
450 return src;
451
452 default:
453 snprintf(buf, buflen, "%%%s%c", prec, op);
454 break;
455 }
456
457 if (optional)
458 {
459 mutt_expando_format(buf, buflen, col, cols, if_str, status_format_str, data,
461 }
462 else if (flags & MUTT_FORMAT_OPTIONAL)
463 {
464 mutt_expando_format(buf, buflen, col, cols, else_str, status_format_str,
466 }
467
468 /* We return the format string, unchanged */
469 return src;
470}
471
482void menu_status_line(struct Buffer *buf, struct IndexSharedData *shared,
483 struct Menu *menu, int cols, const char *fmt)
484{
485 struct MenuStatusLineData data = { shared, menu };
486
487 mutt_expando_format(buf->data, buf->dsize, 0, cols, fmt, status_format_str,
488 (intptr_t) &data, MUTT_FORMAT_NO_FLAGS);
489}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:308
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:478
struct MbTable * cs_subset_mbtable(const struct ConfigSubset *sub, const char *name)
Get a Multibyte table config item by name.
Definition: helpers.c:120
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:267
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
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
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
char * ShortHostname
Short version of the hostname.
Definition: globals.c:39
Global variables.
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:105
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:740
GUI manage the main index (list of emails)
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 FALLTHROUGH
Definition: lib.h:111
#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:630
int mutt_mailbox_check(struct Mailbox *m_cur, CheckStatsFlags flags)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:168
Mailbox helper functions.
const char * get_use_threads_str(enum UseThreads value)
Convert UseThreads enum to string.
Definition: mutt_thread.c:101
enum UseThreads mutt_thread_style(void)
Which threading style is active?
Definition: mutt_thread.c:83
Create/manipulate threading in emails.
UseThreads
Which threading style is active, $use_threads.
Definition: mutt_thread.h:97
@ UT_FLAT
Unthreaded.
Definition: mutt_thread.h:99
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1436
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1644
Some miscellaneous functions.
bool mview_has_limit(const struct MailboxView *mv)
Is a limit active?
Definition: mview.c:439
View of a Mailbox.
#define MUTT_MAILBOX_CHECK_NO_FLAGS
No flags are set.
Definition: mxapi.h:53
Postponed Emails.
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:70
const struct Mapping SortMethods[]
Sort methods for '$sort' for the index.
Definition: mutt_config.c:79
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:70
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition: sort2.h:72
SortType
Methods for sorting.
Definition: sort2.h:34
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:71
static char * get_sort_str(char *buf, size_t buflen, enum SortType method)
Get the sort method as a string.
Definition: status.c:59
void menu_status_line(struct Buffer *buf, struct IndexSharedData *shared, struct Menu *menu, int cols, const char *fmt)
Create the status line.
Definition: status.c:482
GUI display a user-configurable status line.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:39
char * data
Pointer to data.
Definition: buffer.h:37
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:37
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
bool attach_msg
Are we in "attach message" mode?
Definition: shared_data.h:46
struct MailboxView * mailbox_view
Current Mailbox view.
Definition: shared_data.h:40
View of a Mailbox.
Definition: mview.h:40
off_t vsize
Size (in bytes) of the messages shown.
Definition: mview.h:41
char * pattern
Limit pattern string.
Definition: mview.h:42
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:110
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:111
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:36
int len
Number of characters.
Definition: mbtable.h:38
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:39
Data for creating a Menu line.
Definition: status.c:71
struct IndexSharedData * shared
Data shared between Index, Pager and Sidebar.
Definition: status.c:72
struct Menu * menu
Current Menu.
Definition: status.c:73
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:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45